Мониторинг кластера серверов 1С в Zabbix

Дано.

  • Есть кластер серверов 1С из одного сервера (будем называть его «сервер 1С«).
  • На сервере 1С много баз, базы постоянно создаются, удаляются.
  • В базах с некоторой регулярностью работают пользователи.

Надо.

Следить за следующими параметрами сервера 1С:

  • Общее количество серверных рабочих процессов в каждый момент времени.
  • Общее количество активных сеансов пользователей в каждый момент времени
  • Количество баз 1С в каждый момент времени.
  • Текущее количество активных пользователей по каждой базе.
  • Период «простоя» по каждой базе, т.е. сколько времени с каждой базой не проводились работы (отсутствовали сеансы пользователей).

Следить за событиями:

  • В какой-то базе не работали 1 неделю. Важность: информация.
  • В какой-то базе не работали 2 недели. Важность: предупреждение.
  • В какой-то базе не работали 3 недели. Важность: средняя.
  • В какой-то базе не работали 4 недели. Важность: высокая.
  • Общее количество активных пользователей в базах 1С приближается к максимально возможному количеству клиентских лицензий 1С. Важность: предупреждение.

Дополнительная информация и размышления.

  1. Количество баз может меняться, поэтому чтобы избежать постоянного ручного добавления/удаления баз 1C в/из Zabbix будем использовать LLD (низкоуровневое обнаружение).
  2. Т.к. будем использовать LLD, а LLD не умеет суммировать что-то опираясь на обнаруженные элементы, будем высчитывать общее количество баз, сеансов и серверных процессов скриптом, запускаемом на клиенте Zabbix.
  3. Т.к. наблюдаемый сервер 1С может находится за NAT, будем стараться обойтись активным агентом Zabbix. Этим же мы несколько снизим нагрузку на Zabbix-сервер.
  4. Т.к. будем использовать активного Zabbix-клиента постараемся использовать версию поновее, где добавлены дополнительные «фишки». Возьмём Zabbix-сервер и клиент версии 4.4 или выше.
  5. Скрипты, которые будут собирать всю необходимую нам информацию по кластеру 1С разместим в каталоге «C:\zabbix\scripts\Cluster1C«
  6. Скрипты будем писать на VBScript, т.к. он уже встроен в систему. Это избавит нас от необходимости ставить Powershell, Python и прочее.
  7. Помня о том, что мы будем использовать LLD, пишем скрипты, которые некоторую информацию будут выдавать в формате JSON.
  8. Скрипты сбора информации будем запускать регулярно используя планировщик заданий Windows. Частоту запуска скриптов каждый может выбирать индивидуально для себя. Я выбрал частоту запуска 1 раз в 10 минут, т.к. бухгалтеры если зашли в базу, то зашли, а если вышли, то вышли, т.е. они не перезаходят в базу по 100500 раз в минуту. Этим мы опять-таки снизим нагрузку как на Zabbix-сервер, так и на сервер 1С.
  9. Кластер серверов 1С разрешает с собой взаимодействовать посредством COM-соединения, поэтому нужно зарегистрировать в системе COMConnector.  Команда регистрации меняется в зависимости от разрядности операционной системы и разрядности самого кластера серверов 1С. В моём случае COMConnector я зарегистрировал так:
    regsvr32 "C:\Program Files\1cv8\8.3.18.1208\bin\comcntr.dll"
  10. Помним, что в 64-разрядных версиях Windows есть две версии файла Regsv32.exe:
    • 64-разрядная версия — %systemroot%\System32\regsvr32.exe;
    • 32-разрядная версия — %systemroot%\SysWoW64\regsvr32.exe.
  11. Наблюдать за кластером сервером 1С  не обязательно с компьютера, где он непосредственно установлен. Мы можем взять, например, бухгалтерский ПК и настраивать систему мониторинга на нём.

PS.

Файлы для скачивания в конце страницы.

Решение.

Шаг 1.

Создадим каталог «C:\zabbix\scripts\Cluster1C»

Шаг 2.

В  каталоге «C:\zabbix\scripts\Cluster1C» размещаем скрипт Get_Cluster_Info.vbs , который будет собирать всю необходимую информацию и раскладывать её по файлам.

  • Общее количество информационных баз (число) — в файл Information_Bases_Count.txt
  • Общее количество активных пользователей (число) — в файл Users_Count.txt
  • Общее количество серверных рабочих процессов (число) — в файл Working_Processes_Count.txt
  • Список информационных баз с указанием имён, описаний и количеством активных клиентов (JSON) — в файл Bases_List.txt

Файл Bases_List.txt мы будем использовать для LLD, поэтому он должен иметь формат  JSON.

Содержимое файла Bases_List.txt должно быть примерно таким:

{
    "data": [
        {"{#IBDNAME}": "demo01", "{#IBDDESCR}": "Тестовая база 1", "{#IBDUSERCOUNT}": "1"},
        {"{#IBDNAME}": "demo02", "{#IBDDESCR}": "Тестовая база 1", "{#IBDUSERCOUNT}": "3"}
    ]
}

Здесь {#IBDNAME} — имя информационной базы, {#IBDDESCR} — описание информационной базы, {#IBDUSERCOUNT} — количество активных пользователей в информационной базе.

Текст скрипта ниже:

Get_Cluster_Info.vbs
Option Explicit

' Зададим параметры доступа к кластеру 1С
Dim ServerName                ' имя кластера 1С:Предприятия
Dim ClusterAdmin            ' Имя админа кластера, если есть
Dim ClusterAdminPassword    ' Пароль админа кластера, если есть.

ServerName = "SERVER1C"
ClusterAdmin = ""
ClusterAdminPassword = ""

' Зададим пути к рабочим файлам
Const strBasesListFileName                 = "C:\zabbix\scripts\Cluster1C\Bases_List.txt"
Const strInformationBasesCountFileName     = "C:\zabbix\scripts\Cluster1C\Information_Bases_Count.txt"
Const strUsersCountFileName             = "C:\zabbix\scripts\Cluster1C\Users_Count.txt"
Const strWorkingProcessesCountFileName    = "C:\zabbix\scripts\Cluster1C\Working_Processes_Count.txt"

' Опишем переменные
Dim intInformationBasesCount            ' Количество информационных баз в кластере 1С
Dim intUsersCount                        ' Общее количество сеансов на кластере 1С
Dim intWorkingProcessesCount            ' Количество рабочих процессов в кластере 1С
Dim strBasesList                        ' Список баз

Dim Connector
Dim AgentConnection
Dim Cluster
Dim Clusters
Dim WorkingProcesses
Dim IBB
Dim IBBl
Dim Sessions
Dim SessionsActiv
Dim MyBaseName
Dim MyBaseDescr
Dim MyBaseConnectionHost
Dim SessionsActivConnection
Dim UC
Dim BC
Dim BN

'********************************************************************
'*
'*  Процедура   : WriteToFile
'*  Описание    : Записывает/Перезаписывает в файл текстовую информацию
'*  Вход        : strFileName - имя файла, в который нужно писать информацию
'*                strString   - записываемая информация
'*
'********************************************************************
Sub WriteToFile (ByVal strFileName, ByVal strString)

' Опишем константы для работы с текстовыми файлами
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8

Dim fso, f

    Err.Clear
    On Error Resume Next

    Set fso = CreateObject("Scripting.FileSystemObject")
        Set f = fso.OpenTextFile(strFileName, ForWriting, True)
            f.WriteLine strString
            f.Close
        Set f = Nothing
    Set fso = Nothing

End Sub

' Начало программы

intUsersCount = 0

strBasesList =  "{"
strBasesList = strBasesList & vbCrLf & "    ""data"": ["

Set Connector = CreateObject("V83.COMConnector")
    Set AgentConnection = Connector.ConnectAgent(ServerName)
        Clusters = AgentConnection.GetClusters()

        For Each Cluster In Clusters
            AgentConnection.Authenticate Cluster, ClusterAdmin,ClusterAdminPassword
            WorkingProcesses = AgentConnection.GetWorkingProcesses(Cluster)
            intWorkingProcessesCount =  UBound(WorkingProcesses) + 1                ' Определили количество рабочих процессов
            IBB = AgentConnection.GetInfoBases(Cluster)
                intInformationBasesCount = UBound(IBB) + 1                            ' Определили количество баз
                BC = UBound(IBB)
                BN = 0
                For Each IBBl In IBB
                    UC = 0
                    MyBaseDescr = IBBl.Descr
                    Sessions = AgentConnection.GetInfoBaseSessions (Cluster,IBBl)
                    For Each SessionsActiv In Sessions
                        If not ((SessionsActiv.AppID = "COMConsole") or (SessionsActiv.AppID = "BackgroundJob")) Then
                            UC = UC + 1
                            intUsersCount = intUsersCount + 1                        ' Считаем пользователей в базах
                        End if
                    Next
                    MyBaseDescr = Replace(IBBl.Descr,""""," ")
                    If BN = BC Then
                            strBasesList = strBasesList & vbCrLf & "        {""{#IBDNAME}"": """ & IBBl.Name & """, ""{#IBDDESCR}"": """ & MyBaseDescr & """, ""{#IBDUSERCOUNT}"": """ & UC & """}"
                    Else
                            strBasesList = strBasesList & vbCrLf & "        {""{#IBDNAME}"": """ & IBBl.Name & """, ""{#IBDDESCR}"": """ & MyBaseDescr & """, ""{#IBDUSERCOUNT}"": """ & UC & """},"
                    End If
                    BN = BN +1
                Next
        Next
    Set AgentConnection = nothing
Set Connector = Nothing

strBasesList = strBasesList & vbCrLf & "    ]"
strBasesList = strBasesList & vbCrLf & "}"

' Выводим на экран результаты работы
' WScript.Echo "intUsersCount =" & intUsersCount
' WScript.Echo "intInformationBasesCount =" & intInformationBasesCount
' WScript.Echo "intWorkingProcessesCount =" & intWorkingProcessesCount
WScript.Echo strBasesList

' Записываем по файлам результаты работы
'WriteToFile strBasesListFileName, strBasesList
WriteToFile strInformationBasesCountFileName, intInformationBasesCount
WriteToFile strUsersCountFileName, intUsersCount
WriteToFile strWorkingProcessesCountFileName, intWorkingProcessesCount

Замечание.

Названия баз или их описания могут содержать кириллические символы. VBScript в Windows при создании текстовых файлов, скорее всего, использует UTF-8 с BOM или CP1251, что часто приводит к ошибкам отображения этих данных в Zabbix (появляются знаки вопроса или крякозябры). Чтобы решить эту проблему  мы не будет писать JSON напрямую в файл, а будем выводить его в консоль (STDOUT) и при помощи «обёртки» в виде BAT-скрипта будем заворачивать вывод в нужный нам файл. BAT-скрипт будет простейшим:

Get_Cluster_Info.bat
@echo off

"%windir%\System32\cscript.exe" /nologo C:\zabbix\scripts\Cluster1C\Get_Cluster_Info.vbs > C:\zabbix\scripts\Cluster1C\Bases_List.txt

Замечание.

Если у вас система 64х-разрядная, а сервер 1С 32х-разрядный, то в BAT-скрипте нужно вместо «%windir%\System32\cscript.exe» указать «%windir%\SysWOW64\cscript.exe»

Использование «обёртки» приведёт к тому, что файл Bases_List.txt будет в DOS-кодировке (CP866), которую Zabbix отлично понимает.

Теперь запустим скрипт Get_Cluster_Info.bat и проверим, что в папке «C:\zabbix\scripts\Cluster1C\» появились файлы:

    • Bases_List.txt
    • Information_Bases_Count.txt
    • Users_Count.txt
    • Working_Processes_Count.txt

Если файлы появились и в них указана правильная информация, значит всё сделано верно. Проверить можно через консоль «Администрирование серверов 1С Предприятия».

Теперь при помощи вашего любимого JSON-валидатора проверяем файл Bases_List.txt на соответствие формату. Мне нравится использовать сайт https://tools.icoder.uz/json-validator.php

Видим, что JSON валиден, — идём дальше.

Шаг 3.

Запланируем регулярное выполнение данного скрипта при помощи планировщика Windows.

Тут нужно отметить вот что,  если вы как-то особенно не настраивали в Windows подсистему DCOM, то запускать скрипт Get_Cluster_Info.vbs в планировщике от имени системы не получится. Точнее так: скрипт запускаться будет, но данные собирать он не будет.

Чтобы не  заморачиваться с настройкой разрешений в DCOM, будем настраивать запуск скрипта от имени реального пользователя. Можно запускать от имени пользователя USR1CV8 или какого-то другого. Я для простоты описания буду использовать учётку Администратор.

Можно, конечно,  руками создать задачу в планировщике, но т.к. мы планируем потом использовать данный шаблон на многих серверах, напишем простенький BAT-скрипт по регистрации в системе задачи планировщика.

Скрипт нужно запускать «через  правую кнопку мыши», т.е. «Запуск от имени администратора«.

INSTALL_Get_Cluster_Info.bat
@echo off

SET HasAdminRights=0

FOR /F %%i IN ('WHOAMI /PRIV /NH') DO (
	IF "%%i"=="SeTakeOwnershipPrivilege" SET HasAdminRights=1
)

IF NOT %HasAdminRights%==1 (
	ECHO .
	ECHO Not enough permissions to run the script !!!
	ECHO .
	GOTO END
)

SCHTASKS /Create /RU "%COMPUTERNAME%\Администратор" /RP "AdminPass" /SC DAILY /ST 00:00 /RI 10 /DU 24:00 /TN "Get_Cluster_Info" /TR "C:\zabbix\scripts\Cluster1C\Get_Cluster_Info.bat" /RL HIGHEST /F

echo 0 > C:\zabbix\scripts\Cluster1C\LicensesCount.txt

:END

EXIT /B

После создания задачи можно для проверки её запустить.

Шаг 4.

Т.к. мы не будем мудрствовать лукаво и гадать сколько у вас имеется лицензий на запуск 1С, создадим файл C:\zabbix\scripts\Cluster1C\LicensesCount.txt, в котором укажем количество доступных нам лицензий для  запуска клиентов 1С.

Замечание. Если для создания задачи планировщика использовался скрипт, то файл LicensesCount.txt уже будет создан, но в нём будет указано число 0.

Шаг 5.

Заходим в интерфейс Zabbix и начинаем создавать шаблон. Стрелками буду отмечать те поля, которые заполняем.

Шаг 5.1.

Создаём шаблон с имемем «Template Module Windows Cluster1C by Zabbix agent active«.

Шаг 5.2.

Создаём новую группу элементов данных с именем Cluster1C

Шаг 5.3.

Нам нужно следить за количеством лицензий. Для этого создаём 2 элемента данных: Client_Licenses_Count с ключом vfs.file.contents[C:\zabbix\scripts\Cluster1C\LicensesCount.txt]

и Exist_Client_Licenses_Count_File с ключом vfs.file.exists[C:\zabbix\scripts\Cluster1C\LicensesCount.txt]

Теперт создадим триггер с именем « не указано количество клиентских лицензий 1С«, который будет срабатывать когда файла LicensesCount.txt нет, или в нём указан 0 (ноль).

Условие срабатывания триггера будет следующим

{Template Module Windows Cluster1C by Zabbix agent active:vfs.file.contents[C:\zabbix\scripts\Cluster1C\LicensesCount.txt].last()}=0 or {Template Module Windows Cluster1C by Zabbix agent active:vfs.file.exists[C:\zabbix\scripts\Cluster1C\LicensesCount.txt].last()}=0

Шаг 5.4.

Теперь создадим 3 элемента данных, которые будут забирать из файлов собранную скриптом информацию.

Information_Bases_Count — vfs.file.contents[C:\zabbix\scripts\Cluster1C\Information_Bases_Count.txt]

Working_Processes_Count — vfs.file.contents[C:\zabbix\scripts\Cluster1C\Working_Processes_Count.txt]

Working_Users_count — vfs.file.contents[C:\zabbix\scripts\Cluster1C\Users_Count.txt]

Шаг 5.5.

А теперь самое интересное. Начинаем настраивать обнаружение баз при помощи LLD.

Создадим правило обнаружения с именем «Information bases discovery» и ключом «vfs.file.contents[C:\zabbix\scripts\Cluster1C\Bases_List.txt,CP866]»

И у этого же правила нужно настроить фильтр на основе которого будут искаться новые элементы, т.е. базы 1С. В файле Bases_List.txt нам нужно искать элементы {#IBDNAME} с любым именем, т.е. именем подходящим под шаблон «^.*$»

Шаг 5.6.

Создадим прототип элемента данных: «1C Base {#IBDNAME} — {#IBDDESCR} — working users count» с ключом «vfs.file.regexp[C:\zabbix\scripts\Cluster1C\Bases_List.txt,^.*{#IBDNAME}.*$,CP866]» и предобработкой RegExp с шаблоном «IBDUSERCOUNT.*»([0-9]*)«) .

Другими словами, мы из файла Bases_List.txt  будем «выдёргивать» строки текста, в которых содержится имя найденной при помощи LLD базы 1С (за это отвечает регулярное выражение «^.*{#IBDNAME}.*$«), а потом в этой строке при помощи регулярного выражения выделим количество активных пользователей (за это отвечает регулярное вырежение «IBDUSERCOUNT.*»([0-9]*)«)

Замечание.

Для проверки своих регулярных выражений можно использовать онлайн-ресурсы. Мне нравится использовать этот: https://regex101.com/

Вот например, как я проверял своё регулярное выражение

Теперь осталось добавить шаблон к серверу 1С и немного подождать чтобы  проверить, что данные стали собираться.

Если данные не собираются, то ОЧЕНЬ ВНИМАТЕЛЬНО проверьте все сделанные настройки на наличие опечаток. У меня, например, данные не собирались из-за случайного ненужного пробела… Еле нашёл эту ошибку.

Шаг 5.7.

Создадим триггеры. Т.к. мы собираем данные каждые 10 минут, то в час будет 6 измерений, в сутки 6*24=144 измерения, в неделю 144*7=1008 измерений. Округляем до 1000. 🙂

Чтобы отследить, что в базе никто не работал неделю достаточно проверить, что в последней1000 измерений ровно1000 раз количество активных пользователей в базе равнялось нулю.

Так мы настроим триггеры на 1,2,3 и 4 недели простоя базы.

Начнём с 1 недели

{HOST.NAME} - база 1С {#IBDNAME} база не используется 1 неделю

{Template Module Windows Cluster1C by Zabbix agent active:vfs.file.regexp[C:\zabbix\scripts\Cluster1C\Bases_List.txt,^.*{#IBDNAME}.*$,CP866].count(#1000,0)}=1000

Дальше аналогично…

Шаг 6.

Ну, а теперь можем добавить всякие красивости и ненужности. Например, можно добавить:

  • вычисляемый элемент данных, отображающий текущее количество лицензий;
  • триггер, срабатывающий, если осталось мало свободных лицензий;
  • красивые графики отображающие текущее состояние дел.

Всё это несложно, поэтому как-то объяснять, думаю, смысла нет.

Для тех, кому интересно, дам ссылку на свой репозиторий с этим шаблоном.

https://github.com/mihanik2000/ZabbixActiveAgent/tree/master/zabbix/scripts/Cluster1C