Mazmunga o'tish
Tez Base

Prometheus не принимает метрики кластера 1С: диагностика по симптомам

· Chop etilgan:

Мониторинг и журналы

Экспортер метрик кластера 1С запущен, по адресу /metrics отдаётся текст с кодом 200, а в Prometheus цель висит в down или в Grafana пустые панели. Ниже поломки, которые мы поймали на собственном экспортере, сгруппированные по тому, что вы видите. Для каждой команда, которой её подтвердить, и починка. Экспортер снимает кластер штатной утилитой rac через сервер администрирования RAS, поэтому большая часть сказанного относится к любому самописному сбору метрик поверх rac, не только к нашему.

Что видноВероятная причинаРаздел
цель down, invalid metric type "gauge\r"в выводе CRLF вместо LF1
RAS запущен, rac пишет “Различаются версии клиента и сервера”ras.exe не той версии, что агент кластера2
после обновления платформы метрик нет, служба RAS остановленапуть к ras.exe в службе содержит старую версию3
на тестовом кластере пусто в панели лицензийметрики лицензий печатаются только при выданных лицензиях4
мусор или обрезки в метках, пустые infobaseразбор вывода rac5

1. Цель down и invalid metric type “gauge\r”

На странице Targets в Prometheus:

health    = down
lastError = invalid metric type "gauge\r"

Формат экспозиции Prometheus принимает строки, которые заканчиваются только переводом строки (LF). Если в конце стоит CRLF, возврат каретки прилипает к последнему слову строки. Объявление # TYPE onec_sessions gauge превращается в тип gauge\r, такого типа нет, и сервер отвергает документ целиком. В базу не попадает ни один ряд.

Откуда берётся CRLF на Windows: StringBuilder.AppendLine() в .NET и PowerShell ставит Environment.NewLine, а на Windows это два символа. Проверить свой вывод можно без Prometheus, посчитав байты с кодом 13:

$r = Invoke-WebRequest http://localhost:9098/metrics -UseBasicParsing
$b = $r.RawContentStream.ToArray()
"байт: {0}, CR: {1}" -f $b.Length, @($b | Where-Object { $_ -eq 13 }).Count
# CR должно быть 0

Надёжнее прогнать вывод тем, кто его будет читать. promtool из поставки Prometheus разбирает текст так же, как сервер:

curl -s http://localhost:9098/metrics | promtool check metrics

Починка в PowerShell: вместо AppendLine() дописывать перевод строки к каждой строке явно.

# Было: на Windows каждая строка кончается CRLF
[void]$sb.AppendLine('# TYPE ' + $name + ' ' + $type)

# Стало: только LF, как требует формат экспозиции
[void]$sb.Append('# TYPE ' + $name + ' ' + $type + "`n")

Если в репозитории лежит эталонный образец вывода для тестов, проверьте и его. У нас он был записан с того же вывода и тоже содержал CRLF, так что тесты сверяли испорченный продукт с испорченным эталоном.

2. Различаются версии клиента и сервера

Экспортер или ваш скрипт поднимает RAS сам, процесс живой, порт слушает, а соединения с кластером нет:

Различаются версии клиента и сервера (8.3.27.2325 - 8.3.27.1606)

Так бывает, когда на сервере стоят две платформы, и скрипт берёт самый свежий ras.exe. На нашем стенде проверены обе комбинации:

Кто с кемРезультат
rac 8.3.27.2325 и RAS 8.3.27.1606работает
RAS 8.3.27.2325 и агент кластера 8.3.27.1606не соединяется

То есть rac может быть новее RAS, а RAS обязан совпадать с версией агента. Версию агента надёжнее всего взять из пути его службы: ras.exe лежит в том же каталоге bin.

$svc = Get-WmiObject Win32_Service | Where-Object { $_.PathName -match 'ragent' } | Select-Object -First 1
$m = [regex]::Match($svc.PathName, '"?([A-Za-z]:\\[^"]*?\\bin)\\ragent\.exe')
$ras = Join-Path $m.Groups[1].Value 'ras.exe'
Test-Path -LiteralPath $ras    # True - этот ras.exe и запускать

Если агент запущен не службой, тот же каталог берётся из пути процесса: (Get-Process ragent).Path.

3. Служба RAS перестала стартовать после обновления платформы

В проде RAS обычно работает службой Windows, и в её binPath записан полный путь к ras.exe вместе с номером версии платформы. Обновили платформу, старый каталог удалили, служба смотрит в пустоту. Она остаётся в списке служб и просто не стартует, а мониторинг замолкает как раз тогда, когда все заняты обновлением.

Проверка, на что смотрят службы агента и RAS и существует ли этот файл:

Get-WmiObject Win32_Service | Where-Object { $_.PathName -match 'ras\.exe|ragent\.exe' } | ForEach-Object {
    $m = [regex]::Match($_.PathName, '"?([A-Za-z]:\\[^"]*?\.exe)')
    "{0} | {1} | файл на месте: {2}" -f $_.Name, $_.State, (Test-Path -LiteralPath $m.Groups[1].Value)
}

Лечится скриптом установки, который рассчитан на повторный запуск после каждого обновления: сначала остановить и удалить службу, потом создать заново с актуальным путём. В PowerShell вызывайте именно sc.exe, потому что sc там занят командой Set-Content.

sc stop "1C:Enterprise 8.3 Remote Server"
sc delete "1C:Enterprise 8.3 Remote Server"
sc create "1C:Enterprise 8.3 Remote Server" binPath= "\"C:\Program Files\1cv8\<версия>\bin\ras.exe\" cluster --service --port=1545 localhost:1540" start= auto obj= ".\<локальная_учётка>" password= "<пароль>"

В этой строке два порта, и их легко перепутать. 1545 это порт, на котором слушает сам RAS, к нему подключаются rac и экспортер. 1540 это порт агента кластера, к которому подключается RAS. При ошибке служба стартует и молчит.

Учётка для службы отдельная и локальная, это правильно по правам. Обратная сторона: пароль лежит в скрипте установки открытым текстом, поэтому скрипт храните там, куда не ходят посторонние, или спрашивайте пароль при запуске.

4. Пустые панели на тестовом кластере

Первый запуск почти всегда идёт на тестовом кластере, где никто не работает. Метрики по лицензиям (onec_licenses_issued, onec_license_available_users, onec_license_max_users) при сборе по сеансам появляются только тогда, когда лицензии кому-то выданы. Панель пустая, правило тревоги “лицензии заканчиваются” смотрит в пустоту.

Печатать нули здесь нельзя по двум причинам. Метки этих рядов (тип лицензии, серия, кем выдана) приходят из самой лицензии, и ряд с пустыми метками потом даст на графике ступеньку из ниоткуда. А ноль в onec_license_available_users сразу зажигает тревогу “свободных меньше десяти”, и каждый новый стенд начинает жизнь с ложного срабатывания. Тревоги, которые врут с первого дня, перестают читать.

Работает второй источник числа: лицензию, которую держит сам рабочий процесс, rac отдаёт и на кластере без сеансов.

rac process list --licenses --cluster=<id кластера> localhost:1545

После добавления такого источника у метрики появляется новая метка (у нас holder: сеанс или процесс). Пересмотрите все пороги, которые на ней стоят. У нас правило про заканчивающиеся лицензии сразу сработало на ключе процесса, где свободно одно место, хотя рядом было 500 свободных клиентских. Порог писался под клиентские места, теперь в нём стоит holder="session".

5. Испорченные метки

Вывод rac выглядит как пары “ключ : значение”, и у его разбора свои ловушки. Все четыре мы встретили на живом кластере.

  • Кодировка. При перенаправлении вывода rac у нас писал в UTF-8, и кириллица в имени кластера доезжала целой. Под другой локалью вывод может прийти в OEM-кодировке, и тогда мусор навсегда осядет в метке ряда. Декодируйте строго как UTF-8 и при ошибке переключайтесь на OEM.
  • Двоеточия в значениях. У сеанса веб-клиента адрес бывает IPv6 вида fe80::.... Разбор по первому двоеточию режет его пополам, ключ надо искать по началу строки.
  • Кавычки. Имя кластера приходит как name : "Локальный кластер" вместе с кавычками. Не снятые, они уедут в метку и удвоятся при экранировании.
  • Соединения без базы. Служебные соединения агента и планировщика приходят с нулевым идентификатором информационной базы. Без отдельной обработки они получат пустую метку infobase, а пустая метка в Prometheus тоже значение. Мы помечаем их явным infobase="cluster-service".

Отдельно про имена баз. В сеансах и соединениях база приходит идентификатором, поэтому карту “идентификатор - имя” мы строим отдельным вызовом rac infobase summary list и подставляем при сборе. Без неё на дашборде шестнадцатеричные строки.

И про единицы. memory-size рабочего процесса в выводе rac оказался в килобайтах: на стенде 1 700 868 у rac и ровно столько же килобайт в PrivateMemorySize64 того же процесса в тот же момент. По соглашению об именовании метрик память отдаётся в байтах, так что умножаем на 1024.

Что прогнать до того, как объявить готовность

Все поломки выше прошли мимо наших собственных проверок: код ответа 200, правильный Content-Type, длина ответа, число семейств и рядов, самопроверка с нулём ошибок rac, отсутствие BOM в файле для textfile-режима. Каждая проверяла то, о чём автор уже знал. Шесть зелёных проверок, ноль рядов в базе. Список, который их заменил:

  1. promtool check metrics на живом выводе экспортера.
  2. promtool check rules на файле правил тревог и promtool check config на куске scrape_configs.
  3. Счётчик байтов с кодом 13 в ответе, если вывод собирается на Windows.
  4. Живой Prometheus рядом: цель в up, правила загружены, у каждого health=ok.
  5. Импорт дашборда тем путём, которым его будет импортировать пользователь, и подсчёт панелей с данными. У нас на кластере с одним сеансом вышло 20 из 20, на кластере без сеансов 14 из 20: шесть пустых честно пустые, “самый долгий вызов прямо сейчас” без сеансов рисовать нечего.
  6. Прогон на пустом тестовом кластере, как у пользователя в первый день.
  7. Прогон с нуля, без поднятого RAS, если экспортер умеет поднимать его сам.

Границы наших собственных замеров, чтобы вы знали, на что опираетесь. Стенд был один рабочий сервер, один rphost и четыре базы. Сбор занимал от 1,3 до 2,4 секунды, это пять замеров подряд на одном сеансе. Как оно масштабируется на сотнях сеансов, мы не мерили, и интервал опроса 30 секунд в поставке выбран с запасом на глаз. Кластер из нескольких рабочих серверов проверен только логикой кода.

Готовый экспортер и что посмотреть рядом

Наш экспортер с исправленными поломками выше, дашбордом Grafana на 20 панелей, куском scrape_configs и восемью правилами тревоги описан на странице экспортера метрик кластера 1С в Prometheus, скачивание - на Инфостарте. Это один файл PowerShell без зависимостей, к базе данных он не обращается. Короткая история о том, как все шесть проверок оказались зелёными, опубликована там же статьёй.

Как весь мониторинг 1С собирается из трёх слоёв (СУБД, кластер, журналы) и какие алерты не надоедают, разобрано в статье о мониторинге 1С в Grafana. Если внешнего стека нет и ставить его не хочется, кто грузил кластер, видно прямо из 1С через анализ нагрузки кластера, а настройки кластера и рабочих процессов проверяет чек-ап сервера 1С.

Поднять сбор метрик, дашборды и тревоги на вашем контуре целиком, от службы RAS до правил оповещения, можно в рамках услуги мониторинга 1С.

Buni siz uchun hal qila olaman

1C klasteri va MBBT boʻyicha Grafana dashbordlari, muammolarda Telegramga alertlar. Nosozlik haqida foydalanuvchilardan oldin bilasiz - degradatsiyani esa avariyadan haftalar oldin koʻrasiz.

Narxi
450 000 ₸ dantoʻliq joriy etish; soliqlarsiz

Yozishga erta? O'zingiz o'lchang

Кластер 1С в том же Grafana, где уже живёт остальное

Ishlov berishni ochish

INFOSTART TECH EVENT 2026: конференция для 1с-специалистов. если собираетесь, регистрируйтесь по нашей ссылке. Регистрация →

Buni ham o'qing

Ночная загрузка данных упала без видимой ошибки: как узнать об этом в первую же ночь

Одно значение не влезло в числовую колонку, и вся ночная пачка откатилась. Отчёты открываются, цифры вчерашние, алерта нет. Разбираем по вопросам: откуда ноль строк, как найти брак, чем платите за обрезку и расширение типа, какой счётчик ловит аварию сразу и как найти узкие числовые реквизиты в своей 1С.

Сервер 1С грузит процессор: как найти причину и не обвинить не тот процесс

Порядок поиска причины, когда сервер 1С грузит процессор, а в диспетчере задач сверху rmngr или rphost. Проверки расставлены по цене: от накопленного времени ЦП и часового ряда по журналу регистрации до технологического журнала и поиска сервиса внутри менеджера кластера без перезапуска агента. С готовыми скриптами PowerShell и рабочим фильтром техжурнала.

Кто блокирует базу 1С: найти виновника сейчас и восстановить, кто держал ночью

Когда база встаёт, вопрос звучит одинаково: кто её держит. Ответ на него собирается за пять минут тремя способами - консолью кластера, командой rac и запросом к СУБД, и у каждого способа своя слепая зона. Хуже другое: к моменту, когда вы открыли консоль, виновник обычно уже отпустил замок, и на вопрос про ночь снимок текущего момента не отвечает вовсе. Разбираем оба случая: как назвать держателя по имени прямо сейчас и как устроить историю снимков, по которой утром видно, кто держал базу с двух до четырёх.