Prometheus не принимает метрики кластера 1С: диагностика по симптомам
Иван Недомолков · Опубликовано:
Экспортер метрик кластера 1С запущен, по адресу /metrics отдаётся текст с кодом 200, а в Prometheus цель висит в down или в Grafana пустые панели. Ниже поломки, которые мы поймали на собственном экспортере, сгруппированные по тому, что вы видите. Для каждой команда, которой её подтвердить, и починка. Экспортер снимает кластер штатной утилитой rac через сервер администрирования RAS, поэтому большая часть сказанного относится к любому самописному сбору метрик поверх rac, не только к нашему.
| Что видно | Вероятная причина | Раздел |
|---|---|---|
цель down, invalid metric type "gauge\r" | в выводе CRLF вместо LF | 1 |
RAS запущен, rac пишет “Различаются версии клиента и сервера” | ras.exe не той версии, что агент кластера | 2 |
| после обновления платформы метрик нет, служба RAS остановлена | путь к ras.exe в службе содержит старую версию | 3 |
| на тестовом кластере пусто в панели лицензий | метрики лицензий печатаются только при выданных лицензиях | 4 |
мусор или обрезки в метках, пустые infobase | разбор вывода rac | 5 |
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-режима. Каждая проверяла то, о чём автор уже знал. Шесть зелёных проверок, ноль рядов в базе. Список, который их заменил:
promtool check metricsна живом выводе экспортера.promtool check rulesна файле правил тревог иpromtool check configна кускеscrape_configs.- Счётчик байтов с кодом 13 в ответе, если вывод собирается на Windows.
- Живой Prometheus рядом: цель в
up, правила загружены, у каждогоhealth=ok. - Импорт дашборда тем путём, которым его будет импортировать пользователь, и подсчёт панелей с данными. У нас на кластере с одним сеансом вышло 20 из 20, на кластере без сеансов 14 из 20: шесть пустых честно пустые, “самый долгий вызов прямо сейчас” без сеансов рисовать нечего.
- Прогон на пустом тестовом кластере, как у пользователя в первый день.
- Прогон с нуля, без поднятого RAS, если экспортер умеет поднимать его сам.
Границы наших собственных замеров, чтобы вы знали, на что опираетесь. Стенд был один рабочий сервер, один rphost и четыре базы. Сбор занимал от 1,3 до 2,4 секунды, это пять замеров подряд на одном сеансе. Как оно масштабируется на сотнях сеансов, мы не мерили, и интервал опроса 30 секунд в поставке выбран с запасом на глаз. Кластер из нескольких рабочих серверов проверен только логикой кода.
Готовый экспортер и что посмотреть рядом
Наш экспортер с исправленными поломками выше, дашбордом Grafana на 20 панелей, куском scrape_configs и восемью правилами тревоги описан на странице экспортера метрик кластера 1С в Prometheus, скачивание - на Инфостарте. Это один файл PowerShell без зависимостей, к базе данных он не обращается. Короткая история о том, как все шесть проверок оказались зелёными, опубликована там же статьёй.
Как весь мониторинг 1С собирается из трёх слоёв (СУБД, кластер, журналы) и какие алерты не надоедают, разобрано в статье о мониторинге 1С в Grafana. Если внешнего стека нет и ставить его не хочется, кто грузил кластер, видно прямо из 1С через анализ нагрузки кластера, а настройки кластера и рабочих процессов проверяет чек-ап сервера 1С.
Поднять сбор метрик, дашборды и тревоги на вашем контуре целиком, от службы RAS до правил оповещения, можно в рамках услуги мониторинга 1С.