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

04.04.22

Администрирование - Мониторинг

На Инфостарте достаточно большое количество статей по мониторингу 1С с помощью Zabbix, однако все, которые мне попались, описывали настройку сбора данных средствами 1С (http-сервисы, регламентные задания и пр.), поэтому в данной статье поделюсь своим опытом мониторинга с точки зрения системного администратора. Для сбора данных было решено использовать скрипт на Powershell.

Скачать исходный код

Наименование Файл Версия Размер
Мониторинг кластера 1С 8.3 в Zabbix:
.7z 11,44Kb
147
.7z 11,44Kb 147 Скачать

Проверено на:  Операционная система Windows 2016/2019  Сервер приложений 1С 8.3.16/8.3.17  Windows PowerShell 5.1  На более младших версиях не проверялось, возможно потребуется доработать напильником

В качестве параметра/аргумента скрипта передаётся строка формата "Имя_сервера[:Порт]". Параметр не является обязательным и по умолчанию задает значение текущего сервера:

param (
    [System.String]$WorkBaseServer="$($env:COMPUTERNAME):1540"
)

В качестве способа получения данных с кластера 1С решил использовать "V83.COMConnector"

function Get-AgentConnection {
    param(
        [Parameter(Position=0)]
        [System.String]$WorkBaseServer=$WorkBaseServer
    )
 
    $Connector = new-object -comobject "V83.COMConnector"
    $AgentConnection = $Connector.ConnectAgent($WorkBaseServer)
    $Clusters = $AgentConnection.GetClusters()
    $Cluster = $Clusters.GetValue(0)
    $AgentConnection.Authenticate($Cluster,"","")
     
    return $Cluster, $AgentConnection
}
 
$Cluster, $AgentConnection = Get-AgentConnection

После успешного подключения к кластеру, стал актуален вопрос что именно мы хотим собрать с кластера:

  1. Сбор параметров сервера и кластера
  2. Обнаружение всех рабочих сервер в кластере и сбор их параметров
  3. Обнаружение всех рабочих процессов кластера и сбор их параметров
  4. Обнаружение информационных баз кластера 1С и сбор их параметров

Далее о каждом из блоков подробнее

 Изначально пробовал собирать данные разными скриптами и с заданной периодичностью, однако после не продолжительной эксплуатации пришел к выводу что проще осуществлять сбор сразу всех данных в JSON-формате в одном файле.

 

1. Сбор параметров сервера и кластера

1.1. Общие сведения о сервере

  • Статус службы сервера 1С

Выясняем статус службы Агента сервера.

Название службы агента сервера 1С задаем как макрос в шаблоне "{$CLUSTER1C.SERVICE.NAME}", значение по умолчанию "1C:Enterprise 8.3 Server Agent (x86-64)". Статус получаем стандартным методом Zabbix агента

service_state["{$CLUSTER1C.SERVICE.NAME}"]
  • Запущен технологический журнал

    (далее ТЖ)

Не однократно возникала ситуация, особенно со стороны не опытных специалистов, что в порыве решить задачу производительности или неизвестной ошибки запускали ТЖ по инструкции из интернет и без дополнительных настроек со сбором всего и вся, на всякий случай ("... данных много не бывает ..."  ). В таких ситуациях важно не пропустить момент и вовремя скорректировать порыв в нужном направлении.

Поскольку ТЖ запускается с пользовательскими параметрами путем помещения файла "logcfg.xml" в каталоге конфигурационных файлов системы «1С:Предприятие», мониторим его наличие через Zabbix агент:

vfs.dir.count["C:\\Program Files\\1cv8",".*logcfg.xml$",,file]
  • Мониторинг процессов настроен

По умолчанию если процессов ОС с одним и тем же именем несколько, то Performance monitor добавляет к каждому такому процессу порядковый номер (например, rphost#1). Для того, чтобы в имени счетчика отображался PID процесса необходимо отредактировать реестр, добавив в ветку HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PerfProc\Performance ключ ProcessNameFormat типа DWORD 32 бит со значением 2 (более детально на Infostart или Microsoft Docs).

Проверяем наличие ключа и его значение средствами агента запуская команду PowerShell для корректной работы мониторинга:

system.run[powershell -Command "try {Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PerfProc\Performance | Select-Object -ExpandProperty ProcessNameFormat -ErrorAction Stop}catch {0}"]
  • Скрипт сборщика данных существует

Проверяем наличие файла скрипта на сервере. Папку задаем как макрос в шаблоне "{$CLUSTER1C.SERVICE.NAME}", значение по умолчанию "C:\Program Files\Zabbix Agent\scripts". Проверка осуществляется стандартным методом Zabbix агента:

vfs.file.exists["{$CLUSTER1C.SCRIPTPATH}\get_cluster_data.ps1"]
  • Версия службы и Архитектура

Определяем версию службы, архитектуру (разрядность), а так-же путь к файлу настроек кластера.

В общих чертах последовательность: через WMI получаем путь из службы где находятся все интересующие нас данные

function Get-Service1C-Info {
    param(
        [Parameter(Position=0)]
        [System.String]$WorkBaseServer="$($env:COMPUTERNAME):1540"
    )
     
        function Filter-Service1C{
            param(
                [Parameter(Position=0)]
                [System.Array]$split_array=@(),
                [Parameter(Position=1)]
                [System.String]$filter=""
            )
            $element = $split_array | where {$_ -like "$filter *"} | Select -First 1
            $element.remove(0,$filter.length).replace('"','').Trim()
        }
     
    $WorkBaseServerName, $WorkBaseServerPort = $WorkBaseServer.Split(":")
    if(-not $WorkBaseServerPort){$WorkBaseServerPort = 1540}
    $SERVICE_1C = Get-WmiObject win32_service -ComputerName $WorkBaseServerName | Where-Object {$_.PathName -like '*\ragent.exe*' -and $_.PathName -match "-port $WorkBaseServerPort"} | Select -First 1
    $Server_Arch = (Get-WmiObject Win32_OperatingSystem -ComputerName $WorkBaseServerName).OSArchitecture
     
    $PathName_split = $SERVICE_1C.PathName.split('-')
 
    $Path_d = Filter-Service1C $PathName_split "d"
    $WorkBaseServerRegPort = Filter-Service1C $PathName_split "regport"
     
    $path = $null
    if ($PathName_split[0] -like "*\1cv82\*"){
        $path =  Join-Path -Path $Path_d -ChildPath "reg_$WorkBaseServerRegPort\1CV8Reg.lst"
    } elseif($PathName_split[0] -like "*\1cv8\*"){
        $path = Join-Path -Path $Path_d -ChildPath "reg_$WorkBaseServerRegPort\1CV8Clst.lst"
    }
     
    $bin_path = $PathName_split[0].split('\')
    $1c_arch = "32-bit"
    if($Server_Arch -match "64-\w+"){
        if($bin_path[1] -eq "Program Files"){
            $1c_arch = "64-bit"
        }
    }
     
    $1c_ver = $bin_path | Where{$_ -Match "\d+.\d+.\d+.\d+"} | Select -First 1
 
    return $1c_arch, $1c_ver, $path
}
 
$1c_arch, $1c_ver, $path_lst = Get-Service1C-Info $WorkBaseServer

$path_lst - понадобится позже (путь к файлу конфигурации кластера 1С)

 

1.2. Параметры кластера

Ранее мы уже получили объект $Cluster, содержащий требуемые нам параметры.

Однако помимо стандартных параметров кластера в систему мониторинга нам потребуется передавать сведения о сеансах кластера. Объект $Cluster соответствует типу System.__ComObject, нам потребуется конвертировать его в PSCustomObject, для этого используем командлеты ConvertTo-Json и ConvertFrom-Json:

$cluster_json = $Cluster | ConvertTo-Json | ConvertFrom-Json

Добавим параметры, соответствующие ранее полученным: Версию службы и Архитектуру

$cluster_json | Add-Member -MemberType NoteProperty -Name 'architecture' -Value $1c_arch
$cluster_json | Add-Member -MemberType NoteProperty -Name 'version' -Value $1c_ver

Отслеживаем следующие параметры кластера, которые уже присутствуют с в объекте $Cluster

  • Допустимый объем памяти

$cluster_json.MaxMemorySize
  • Записывать дамп процесса при превышении критического объема памяти

$cluster_json.KillByMemoryWithDump
  • Режим распределения нагрузки

$cluster_json.LoadBalancingMode
  • Уровень отказоустойчивости

$cluster_json.SessionFaultToleranceLevel
  • Проблемные процессы завершать через

$cluster_json.ExpirationTimeout
  • Интервал перезапуска

$cluster_json.LifeTimeLimit
  • Защищенное соединение

$cluster_json.SecurityLevel
  • IP порт

$cluster_json.MainPort
  • Принудительно завершать проблемные процессы

$cluster_json.KillProblemProcesses
  • Количество рабочих серверов

Получение данных о рабочих серверах кластера рассмотрим ниже, здесь-же просто опишу созданный элемент данных:

 

 

1.3. Сведения о сеансах кластера

Получаем сеансы кластера:

function Get-Sessions {
    param(
        $Cluster = $null,
        $AgentConnection = $null
    )
    if($AgentConnection -ne $null){
        $Sessions = $AgentConnection.GetSessions($Cluster)
        return $Sessions
    }
    return $null
}
 
$sessions = Get-Sessions $Cluster $AgentConnection

Получаем список сессий и пользователей кластера 1С:

$sessions_all = $sessions | Select-Object @{Label='infoBase'; Expression={$_.infoBase.Name}}, SessionID, AppID | Sort-Object -Property infoBase, SessionID -Unique
$users_all = $sessions | Where-Object{$_.License.LicenseType -ne $null} | Select-Object @{Label='infoBase'; Expression={$_.infoBase.Name}}, SessionID | Sort-Object -Property infoBase, SessionID -Unique
  • Количество сессий кластера

$cluster_json | Add-Member -MemberType NoteProperty -Name 'sessions_count' -Value $sessions_all.Count
  • Количество пользователей кластера

$cluster_json | Add-Member -MemberType NoteProperty -Name 'users_count' -Value $users_all.Count
  • Количество клиентов кластера

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

$cluster_json | Add-Member -MemberType NoteProperty -Name 'clients_count' -Value ($sessions_all | Where-Object{$_.AppID -like "1CV8" -or $_.AppID -like "1CV8C"} | Measure | Select -Expand Count)
  • Количество WEB-сервисов кластера

$cluster_json | Add-Member -MemberType NoteProperty -Name 'ws_count' -Value ($sessions_all | Where-Object{$_.AppID -like "WSConnection"} | Measure | Select -Expand Count)
  • Количество HTTP-сервисов кластера

$cluster_json | Add-Member -MemberType NoteProperty -Name 'http_count' -Value ($sessions_all | Where-Object{$_.AppID -like "HTTPServiceConnection"} | Measure | Select -Expand Count)
  • Количество фоновых заданий кластера

$cluster_json | Add-Member -MemberType NoteProperty -Name 'jobs_count' -Value ($sessions_all | Where-Object{$_.AppID -like "BackgroundJob"} | Measure | Select -Expand Count)
  • Количество COM+ подключений кластера

$cluster_json | Add-Member -MemberType NoteProperty -Name 'com_count' -Value ($sessions_all | Where-Object{$_.AppID -like "COMConnection"} | Measure | Select -Expand Count)
  • Количество веб-клиент кластера

$cluster_json | Add-Member -MemberType NoteProperty -Name 'web_count' -Value ($sessions_all | Where-Object{$_.AppID -like "WebServerExtension"} | Measure | Select -Expand Count)

 Отдельно хочется отметить проблему, возникшую после перехода с ПРОФ редакции на КОРП - это подключение пользователей к КОРП кластеру с клиентскими ПРОФ ключами. Ситуация такова, что часть клиентских ключей находилось в серверной, а часть на рабочих местах, либо "серверах" отделов. В результате при подключении более 10 таких пользователей, функциональность КОРП пропадала. На это необходимо было реагировать как можно быстрее и желательно до того, как кластер начнет деградировать.

В нашем случае ситуация упрощалась тем, что все КОРП ключи были на 500 пользователей, все прочие - ПРОФ.

  • Пользователи ПРО

Получаем список всех пользователей с ПРОФ лицензией:

$pro_license = $sessions | Select-Object @{Label='infoBase'; Expression={$_.infoBase.Name}}, userName, Host, AppID, @{Label='License'; Expression={$_.License.ShortPresentation}} | Where-Object{$_.License -ne $null -and $_.License -notmatch "ORG8B .{3} 500" -and $_.License -notmatch "ORGL8 .{3} 1"}
$cluster_json | Add-Member -MemberType NoteProperty -Name 'prolicense_users' -Value $pro_license
  • Количество лицензий ПРОФ

$cluster_json | Add-Member -MemberType NoteProperty -Name 'prolicense_count' -Value $pro_license.Count

 

2. Обнаружение всех рабочих серверов в кластере и сбор их параметров

Обнаружение всех рабочих серверов кластера:

function Get-WorkingServers {
    param(
        $Cluster = $null,
        $AgentConnection = $null
    )
    if($AgentConnection -ne $null){
        $WorkingServers = $AgentConnection.GetWorkingServers($Cluster)
         
        return $WorkingServers
    }
    return $null
}
 
$WorkingServers = Get-WorkingServers $Cluster $AgentConnection

Данные с рабочих серверов поместим в переменную:

$workingservers_json = @()

Сохраним количество ядер для каждого из рабочих серверов кластера в отдельную переменную:

$NumberOfCores = @{}

Ниже код, каким образом получаем данные со всех серверов:

Foreach($workingserver in $WorkingServers){
 
    $NumberOfCores[$workingserver.HostName] = (Get-WmiObject -Class Win32_Processor -ComputerName $workingserver.HostName | Measure-Object NumberOfCores -Sum).Sum
    $counter_processor_total = (Get-Counter "\\$($workingserver.HostName)\238(_Total)\6").CounterSamples.CookedValue
    $counter_processor_12 = 0
    foreach($i in @(0..12)){
        $counter_processor_12 += (Get-Counter "\\$($workingserver.HostName)\238($i)\6").CounterSamples.CookedValue / 12
    }
    $workingserver | Add-Member -MemberType NoteProperty -Name 'counter_processor_total' -Value ([math]::Round($counter_processor_total,2))
    $workingserver | Add-Member -MemberType NoteProperty -Name 'counter_processor_12' -Value ([math]::Round($counter_processor_12,2))
    $workingservers_json += $workingserver | ConvertTo-Json | ConvertFrom-Json
}

$counter_processor_total - общая нагрузка на процессор

$counter_processor_12 - нагрузка на первые 12 ядер процессора

Поскольку запрос значений счетчиков монитора ресурсов требует времени на выполнение, а именно по 1 секунде на каждый счетчик. Вроде не много для одного счетчика, но по 13 секунд на каждый из серверов в кластере, в нашем случае блок выше выполнялся 40 секунд. Следовательно надо оптимизировать:

$block = {
    Param([string] $Counter)
    (Get-Counter $Counter).CounterSamples.CookedValue
}
 
Foreach($workingserver in $WorkingServers){
 
    $NumberOfCores[$workingserver.HostName] = (Get-CimInstance Win32_ComputerSystem -ComputerName $workingserver.HostName).NumberOfLogicalProcessors
    $counter_processor_total = (Get-Counter "\\$($workingserver.HostName)\238(_Total)\6").CounterSamples.CookedValue
    $counter_processor_12 = 0
 
    #Remove all jobs
    Get-Job | Remove-Job
    $MaxThreads = 12
    #Start the jobs. Max 12 jobs running simultaneously.
    foreach($i in @(0..11)){
        While ($(Get-Job -state running).count -ge $MaxThreads){
            Start-Sleep -Milliseconds 10
        }
 
        Start-Job -Scriptblock $Block -ArgumentList "\\$($workingserver.HostName)\238($i)\6"
    }
    #Wait for all jobs to finish.
    While ($(Get-Job -State Running).count -gt 0){
        start-sleep 1
    }
    #Get information from each job.
    foreach($job in Get-Job){
        $counter_processor_12 += Receive-Job -Id ($job.Id)
    }
    #Remove all jobs created.
    Get-Job | Remove-Job
 
    $workingserver | Add-Member -MemberType NoteProperty -Name 'counter_processor_total' -Value $counter_processor_total
    $workingserver | Add-Member -MemberType NoteProperty -Name 'counter_processor_12' -Value ($counter_processor_12 / 12)
    $workingservers_json += $workingserver | ConvertTo-Json | ConvertFrom-Json
}

Оптимизация времени выполнения была выполнена за счет параллельного опроса всех счетчиков (комментарии оставил из исходного кода, взял https://code-examples.net/ru/q/29a9692). После оптимизации данный блок стал выполняться не более 10 секунд.

Почему мы не использовали стандартные счетчики Zabbix для получения загрузки процессора? Потому что требовалось создать универсальный шаблон. В этом шаблоне используются данные о загрузке первых 12 ядер и общая нагрузка на процессор, для создания триггера, который проверяет не пропал-ли функционал КОРП-лицензий кластера. На этапе старта проекта - данная проблема была очень актуальна.

 

3. Обнаружение всех рабочих процессов кластера и сбор их параметров

Обнаружение всех рабочих процессов кластера:

function Get-Processes {
    param(
        $Cluster = $null,
        $AgentConnection = $null
    )
    if($AgentConnection -ne $null){
        $WorkingProcesses = $AgentConnection.GetWorkingProcesses($Cluster)
        return $WorkingProcesses
    }
    return $null
}
 
$processes = Get-Processes $Cluster $AgentConnection

Поскольку лишние параметра рабочих процессов нам не нужны, оставим только то что собираемся мониторить:

[System.Array]$processes_clone = $processes | Select PID, MainPort, StartedAt, HostName, MemorySize, connections, Enable, Running, Use, IsEnable

Дополняем каждый из процессов интересующими нас данными:

$process_id = 0
foreach($process in $processes_clone){
    $sessions_PID = $sessions | Where-Object{$_.process.PID -eq $process.PID}
    $session_mem = $sessions_PID | Sort-Object MemoryCurrent -Descending | Select @{Label='infoBase'; Expression={$_.infoBase.Name}},SessionID, AppID, userName, MemoryCurrent, cpuTimeCurrent, dbProcInfo, dbProcTook -First 1
    $session_proc_took = $sessions_PID | Sort-Object dbProcTook -Descending | Select @{Label='infoBase'; Expression={$_.infoBase.Name}},SessionID, AppID, userName, MemoryCurrent, cpuTimeCurrent, dbProcInfo, dbProcTook -First 1
    $session_CPU = $sessions_PID | Sort-Object cpuTimeCurrent -Descending | Select @{Label='infoBase'; Expression={$_.infoBase.Name}},SessionID, AppID, userName, MemoryCurrent, cpuTimeCurrent, dbProcInfo, dbProcTook -First 1
    $counter_process = (Get-Counter "\\$($process.HostName)\230(rphost_$($process.PID))\6").CounterSamples.CookedValue
 
    $processes_clone[$process_id] | Add-Member -MemberType NoteProperty -Name 'session_mem' -Value $session_mem
    $processes_clone[$process_id] | Add-Member -MemberType NoteProperty -Name 'session_proc_took' -Value $session_proc_took
    $processes_clone[$process_id] | Add-Member -MemberType NoteProperty -Name 'session_CPU' -Value $session_CPU
    $processes_clone[$process_id] | Add-Member -MemberType NoteProperty -Name 'CPU_Usage' -Value ([math]::Round($counter_process / $NumberOfCores[$process.HostName],2))
    $process_users = $sessions_PID | Where-Object{$_.License.LicenseType -ne $null} | Select-Object @{Label='infoBase'; Expression={$_.infoBase.Name}}, SessionID | Sort-Object -Property infoBase, SessionID -Unique
    $process_sessions = $sessions_PID | Select-Object @{Label='infoBase'; Expression={$_.infoBase.Name}}, SessionID | Sort-Object -Property infoBase, SessionID -Unique
 
    $processes_clone[$process_id] | Add-Member -MemberType NoteProperty -Name 'users' -Value $process_users.Count
    $processes_clone[$process_id] | Add-Member -MemberType NoteProperty -Name 'sessions' -Value $process_sessions.Count
     
    $process_id += 1
}

$sessions_PID - PID процесса в операционной системе

$session_mem - Значения параметров сеанса, потребляющего максимальный объем оперативной памяти на данном рабочем процессе

$session_proc_took - Значения параметров сеанса, у которого максимальное время соединения с СУБД с момента захвата на данном рабочем процессе

$session_CPU - Значения параметров сеанса, потребляющего максимальные процессорные мощности на данном рабочем процессе

$counter_process / $NumberOfCores[$process.HostName] - % нагрузки  на процессор вызванный данным рабочим процессом

$process_users.Count - Количество сеансов пользователей  на данном рабочем процессе

$process_sessions.Count - Количество сессий на данном рабочем процессе

 

4. Обнаружение информационных баз кластера 1С и сбор их параметров

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

Нам понадобится значение переменной $path_lst, полученной ранее. Это путь к файлу конфигурации кластера 1С, содержащий в себе информацию обо всех информационных базах кластера. Получаем интересующие нас данные через регулярное выражение:

$content = Get-Content $path_lst | Select-String "^{\w{8}-\w{4}-\w{4}-\w{4}-\w{12},.*,.*,.*,.*,.*,.*,.*,"".+SQL.*"",\d*," -Context 0,1

Теперь данные об информационных базах надо структурировать:

$BasesInfo_content = @()
 
foreach($content_info in $content){
    $info = $content_info.Line.Split(',')[0,1,2,4,5,8] | %{$_ -replace ('"','') -replace ('{','')}
 
    $BaseInfo_content = @{
    "Path" = $info[0];
    "InfoBase" = $info[1];
    "Description" = $info[2];
    "DBServerName" = $info[3];
    "DBBaseName" = $info[4]
    }
    $BaseInfo_content += ($info[5] -replace (";","`n")) | ConvertFrom-StringData
 
    $info = $content_info.Context.PostContext[0].remove(0,1).Split(',')[0,1,2]
 
    $BaseInfo_content += @{
    "Blocked" = $info[0];
    "StartBlocking" = $info[1];
    "EndBlocking" = $info[2]
    }
     
    $BasesInfo_content += $BaseInfo_content
     
}

"Path" - Идентификатор
"InfoBase" - Информационная база
"Description" - Описание
"DBServerName" - Сервер баз данных
"DBBaseName" - База данных
"Blocked" - Блокировка начала сеансов включена
"StartBlocking" - Время до начала блокировки
"EndBlocking" - Время до окончания блокировки

Остальные данные получаем через "V83.COMConnector":

function Get-InfoBases {
    param(
        $Cluster = $null,
        $AgentConnection = $null
    )
    if($AgentConnection -ne $null){
        $InfoBases = $AgentConnection.GetInfoBases($Cluster)
        return $InfoBases
    }
    return $null
}
 
$InfoBases = Get-InfoBases $Cluster $AgentConnection

Объединяем информацию о всех ИБ:

$connections_json = @()
 
foreach($InfoBase in $InfoBases){
    $connection_json = @{}
    $connection_json.Add('BaseName',$InfoBase.Name)
    $connection_json.Add('sessions',($sessions_all | Where-Object{$_.infoBase -eq $InfoBase.Name} | Measure | Select -Expand Count) )
    $connection_json.Add('users',($users_all | Where-Object{$_.infoBase -eq $InfoBase.Name} | Measure | Select -Expand Count) )
     
    $RegCount_users = $sessions | Select @{Label='infoBase'; Expression={$_.infoBase.Name}}, SessionID, userName | Where-Object{$_.infoBase -eq $InfoBase.Name -and $_.userName -match "^reg[\d]{3}"} | Group-Object userName | Select-Object Name, Count
 
    $regList = @()
 
    foreach($RegCount_user in $RegCount_users){
    $regList+=@{"username" = $RegCount_user.Name;"count" = $RegCount_user.Count}
    }
    foreach($i in (1..8)){
        if(($RegCount_users -match "reg$($i.ToString(""000""))").count -eq 0){
            $regList += @{"username" = "reg$($i.ToString(""000""))";"count" = 0}
        }
    }
    $connection_json.Add('reglaments',$regList)
     
    $connection_json += $BasesInfo_content | Where-Object{$_.infoBase -eq $InfoBase.Name}
     
    $connections_json += $connection_json
}
 
$cluster_bases_json = @{}
$cluster_bases_json.Add('list',$connections_json)

"BaseName" - Название информационной базы

"Sessions" - Количество сессий на данной информационной базе

"Users" - Количество сеансов пользователей на данной информационной базе

"reglaments" - Количество сеансов пользователей регламентных заданий на данной информационной базе

Поскольку все регламентные задания выполняются под соответствующими пользователями, имя которых задано в формате "reg000", мы собираем количество сеансов регламентных заданий и создали триггеры для тех, которые не должны запускать пользователи в рабочее время.

Объединяем все полученные данные в блоках 1-4:

$cluster_data_json = @{}
$cluster_data_json.Add('cluster',$cluster_json)
$cluster_data_json.Add('workingservers',$workingservers_json)
$cluster_data_json.Add('bases',$cluster_bases_json)
$cluster_data_json.Add('processes',$processes_clone)

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

$cluster_data_json | ConvertTo-Json -Depth 7 -Compress | Out-File -FilePath "C:\Program Files\Zabbix Agent\Scripts\1c_server_data.json" -Force -Encoding UTF8

Детально описывать создание каждого элемента данных не будем, просто приложим "Zabbix template" и готовый скрипт PowerShell.

 

Описание шаблона

 

 

У шаблона 2 макроса с заданными значениями по умолчанию

 

 

Вся информация о кластере и его параметрах отнесена в группе элементов данных "Кластер 1С":


 

Созданы соответствующие триггеры:


 

В шаблоне создано 3 правила обнаружения для информационных баз, рабочих серверов и рабочих процессов:

 

 

Для сопровождения созданы дашборды в Zabbix. Примеры:


 

Для визуализации состояния КИС создан дашборд на Grafana:


 

Дашборд выводится на один из экранов обслуживающего подразделения. Так это выглядит у нас:


 

Планы по развитию

Наша система мониторинга продолжает развиваться, ровно, как и специалисты, ее развивающие и сопровождающие. В связи с этим в ближайшем будущем мы планируем перевод системы мониторинга с COM+ на RAS/RAC.

Zabbix Powershell Мониторинг

См. также

Мониторинг баз и серверов 1С

Журнал регистрации Мониторинг Платформа 1С v8.3 Платные (руб)

В сферу обязанностей при работе с клиентами входит контроль работы баз данных и серверов 1С. Нужно понимать что происходит в базах, есть ли ошибки, зависания у пользователей и фоновых задач, блокировки или какое-то необычное поведение системы, получение информации о причинах возникновения проблем и их оперативное устранение и т.д. В качестве источников информации использую консоль кластеров 1С, технологический журнал 1С, журналы регистрации базы 1С. Для автоматизации части операций мониторинга и анализа создал инструмент на основе 1С.

9000 руб.

28.08.2019    31380    15    21    

68

Конфигурация Session Monitor

Мониторинг Инструменты администратора БД Платформа 1С v8.3 Россия Платные (руб)

Конфигурация Session Monitor предназначена для мониторинга сервера 1С с целью отслеживания чрезмерной нагрузки от конкретных сеансов и скорости реакции рабочих процессов.

1500 руб.

01.12.2020    14577    36    0    

51

Исправление проблем Центра контроля качества

Мониторинг Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Расширение, в котором поправил несколько багов и неудобств, присутствующих в ЦКК. Пригодится для разработчиков, использующих ЦКК.

1 стартмани

13.05.2024    163    0    Дмитрий74Чел    0    

0

Yellow Watcher - Жёлтый наблюдатель за информационными базами

Мониторинг Платформа 1С v8.3 Абонемент ($m)

Программный комплекс мониторинга качества работы информационных баз. Статистика возникновения управляемых блокировок (тип, последняя строка контекста, контекст). Анализ длительных запросов по данным из технологического журнала. Анализ потребления ресурсов СУБД запросами и статистика ожиданий по данным из Query Store. Монитор информационной базы - получение плана запроса для сеанса 1С. Блокировки СУБД по данным block_report Extented Events, длительные запросы по данным из query_post_execution_showplan Extented Events.

1 стартмани

12.02.2024    3559    30    sdf1979    11    

54

Проверка доступа к интернет на сервере 1С

Мониторинг Платформа 1С v8.3 Конфигурации 1cv8 1С:Бухгалтерия 3.0 Абонемент ($m)

Инструмент для проверки интернет - соединения на сервере 1С

3 стартмани

23.11.2023    2003    6    1395969    4    

2

Магия преобразований Vector, часть 3: журнал регистрации + прямой экспорт ошибок в Sentry

Журнал регистрации Мониторинг Абонемент ($m)

Как легко и быстро с помощью специализированных решений собирать, парсить и передавать логи и метрики.

1 стартмани

19.11.2023    873    4    AlexSTAL    0    

8

Магия преобразований Vector, часть 2: технологический журнал

Технологический журнал Мониторинг Абонемент ($m)

Как легко и быстро с помощью специализированных решений собирать, парсить и передавать логи и метрики.

1 стартмани

15.11.2023    936    5    AlexSTAL    0    

8

Магия преобразований: ЖР, ТЖ, RAS/RAC, логи - универсальное решение Vector

Мониторинг Журнал регистрации Технологический журнал Абонемент ($m)

Как легко и быстро с помощью специализированных решений собирать, парсить и передавать логи и метрики.

1 стартмани

13.11.2023    3421    7    AlexSTAL    0    

46
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. quazare 3651 04.04.22 12:28 Сейчас в теме
хороший труд. почитаю на досуге)
2. ivanov660 4357 04.04.22 15:56 Сейчас в теме
Выгляди конечно здорово, но вопросы:
1. Как ответственный реагирует на инциденты? На мониторе 200 квадратиков (не много-ли) + еще и графики воткнули.
2. Как обрабатывают критические ситуации (какой-то скрипт)?
3. vitall924 83 04.04.22 19:52 Сейчас в теме
(2)
1. Дашборд настроен по системе светофор, т.е. Зеленый - все ОК, Желтый - Предупреждение, Красный - Тревога.
Ответственный увидев что какой-то из квадратиков пожелтел или покраснел - должен отреагировать.

2. Порядок отработки стандартно таков: открывает Zabbix и смотрит значения и историю изменений, после этого отправляет запрос в поддержку, чтобы отработали с пользователем, параллельно открывает в консоль кластера 1С.
Дальнейшие шаги зависят от конкретного случая: если проблема в пользователе/отчете - либо закрываем сеанс, либо ждем и просим пользователей потерпеть; если проблема требует расследования, то подключаем ТЖ, разработчиков и пр.
4. ivanov660 4357 04.04.22 21:11 Сейчас в теме
(3) по. п1, тогда достаточно 3х квадратиков. Именно светофора из трех квадратов, которые зажигаются по нарастающей проблематике. Зеленый горит пьешь кофе. Желтый напрягся. А если видишь красный, то нажал кнопку расшифровки и начал анализировать?
Четко видна проблема, не отвлекаешься на кучу разных ситуаций, не пропустишь новое событие, эмоциональное напряжение на минимуме и человек не устает. Или список активных инцидентов, видел и такую реализацию.

В АСУ ТП, к примеру (очень похожа идея реализации диспетчерской), стараются делать меньше и только основные параметры, делать надписи крупными. Если хочешь смотреть детально, кликаешь и переходишь на детализацию. Или мониторы - это так для руководства?
5. vitall924 83 05.04.22 07:03 Сейчас в теме
(4) По количеству квадратиков - личное предпочтение каждого.
Поскольку дашборд перед глазами всегда (висит на стене телевизор), быстро привыкаешь какой сегмент отвечает за ту или иную проблему, соответственно при изменении цвета на отличный от зеленого - специалисты идут смотреть подсистему, вызвавшую проблему. Это не первый и не последний вариант дашборда: выводили именно те параметры, которые пригождались при разборе инцидентов в предыдущие периоды.
Графики не интересны пока система работает стабильно, однако если происходит какой-то сбой, часто на них можно увидеть всплеск потребления ресурсов.
Список инцидентов также есть - правый верхний угол на дашборде.

Или мониторы - это так для руководства?

Поскольку я и есть руководство, то отчасти да, для меня в том числе.
6. user612295_death4321 05.04.22 16:42 Сейчас в теме
Почему COM, а не RAS?
IT_GG; Glebis; JohnyDeath; mip128; cosmo2004; +5 Ответить
8. vitall924 83 06.04.22 13:14 Сейчас в теме
(6)
На момент старта проекта первостепенной задачей было в максимально сжатые сроки запустить отказоустойчивый кластер высокой доступности VMWare vCenter, и произвести миграцию всех виртуальных машин с Microsoft Hyper-V.
В связи с тем, что данный проект совпал в внедрением системы мониторинга Zabbix, использовались имеющиеся наработки для мониторинга Кластера 1С
7. cdiamond 235 06.04.22 11:42 Сейчас в теме
Труд хороший, но COM категорически не одобряю. Клиентам на Linux всё поднимаю. Ну пусть бухгалтер не может привыкнуть, но всю серверную часть давно уже пора переводить. А как там народ собрался с Windows жить дальше я не понимаю.
9. vitall924 83 06.04.22 13:22 Сейчас в теме
(7)
COM категорически не одобряю

Все это понимали изначально, но причину COM написал чуть выше.
А как там народ собрался с Windows жить дальше я не понимаю.

Жить можно и с Windows (Debian, CentOS и и́же с ними не сильно лучше), однака по этой причине и написал, что есть "Планы по развитию"
10. cdiamond 235 06.04.22 14:04 Сейчас в теме
(9) Вы даже суть проблемы Windows до сих пор не осознали. Вопрос не в том что лучше или хуже, а на чём можно. У меня один клиент уже пытается через Казахстан мухлевать с лицензиями, но знаю что придет сдаваться.
11. vitall924 83 06.04.22 15:36 Сейчас в теме
(10)
Проблемы лицензирования в текущих реалиях - общая проблема, а не только Windows. Я говорю не только про покупку, поддержку, но и про доступ к репозиториям.
12. cdiamond 235 06.04.22 16:14 Сейчас в теме
(11) OSS репозитарии не закрывал никто еще, но согласен, в нынешней ситуации возможно всё. Но репы Астры и прочих отечественных остаются. Не хотелось бы до этого дойти конечно, но тот кто переходит на Дебиан сейчас потом на 100% будет готов и к такому исходу.
Кстати Grafana OSS из вашего решения всё ещё доступна, но энтерпрайз версия уже нет и не берусь прогнозировать, закроют они и OSS-версию или нет. И Ubuntu то же самое
vitall924; +1 Ответить
13. mixsture 07.04.22 14:40 Сейчас в теме
(12)
Но репы Астры и прочих отечественных остаются

Имхо. Debian-based дистрибутив. Закроют доступ к дебиан => перестанет обновляться и Астра. Сомневаюсь, что ребята из Астры смогут проводить параллельно такой же объем работ, как и в дебиане. Зачем будет нужен дистрибутив без обновлений и сколько он проживет?
14. cdiamond 235 07.04.22 17:16 Сейчас в теме
(13) Астра это и есть Дебиан 10 со своими дополнительными пакетами, даже репа дебиановская напрямую подключается и никак не конфликтует. Они свой штат в 10 раз увеличивают, видимо попёр бизнес
15. user1777367 25.04.22 11:09 Сейчас в теме
Спасибо большое. Очень информативно.
16. user1777367 05.05.22 13:55 Сейчас в теме
Попробовал взять ваш скрип и темплейт. На нескольких серверах отрабатывает с ошибкой
Хэш-таблицу можно добавить только к другой хэш-таблице.
get_cluster_data.ps1:297 знак:5
17. user1777367 05.05.22 14:41 Сейчас в теме
(16)так же для vfs.file.contents ругается на "File is too large for this check."
19. vitall924 83 06.05.22 08:39 Сейчас в теме
(17)
File is too large for this check.

у данного параметра есть ограничения на размер данных 64 Kbytes.
Если не хватает этого объема, потребуется переписать на сбор данных в разные файлы, либо через регулярные выражения собирать часть файла в промежуточные переменные
20. user1777367 06.05.22 09:10 Сейчас в теме
(19)через userparameter решил собирать, там ограничение 512 кб
vitall924; +1 Ответить
18. vitall924 83 06.05.22 08:28 Сейчас в теме
Добрый день!
Какая версия ОС и Powershell?

Я так понимаю, что проблема в одной из строк формата "$cluster_data_json.Add"
Можно к добавляемому в этой строке объекту попробовать механизм, который применяли к объекту $Cluster - "$Cluster | ConvertTo-Json | ConvertFrom-Json"
21. user1777367 06.05.22 13:28 Сейчас в теме
(18)можно еще узнать, почему не выгружаются все пользователи висящие на рабочем процессе, а только один?
22. vitall924 83 11.05.22 07:19 Сейчас в теме
(21)
Доброе утро!
Выгружаются данные пользователей - потребителей определенных ресурсов, например, памяти:
 $session_mem = $sessions_PID | Sort-Object MemoryCurrent -Descending | Select @{Label='infoBase'; Expression={$_.infoBase.Name}},SessionID, AppID, userName, MemoryCurrent, cpuTimeCurrent, dbProcInfo, dbProcTook -First 1

Если необходим не предполагаемый виновник деградации производительности, а 2-3, можно сметить ограничение в отборе на "-First N" и переделать правило обнаружения.
Всё будет зависеть от задачи, которую Вы хотите решить.
23. user1777367 11.05.22 13:48 Сейчас в теме
(22) Круто. Спасибо. Последний вопрос. JSON дашборда не поделитесь?)
24. vitall924 83 12.05.22 07:36 Сейчас в теме
(23)
От него большого толку не будет, поскольку присутствуют метрики не только, указанные в данной статье.
Если отдавать модель дашборда - необходимо полностью обезличить ее, т.е. удалить все отсылки к реальным серверам/адресам, а после этого совсем не реально запустить его.
25. user1777367 12.05.22 07:40 Сейчас в теме
(24)
Не совсем понятно просто как по рабочим процессам выборка идет, они постоянно меняются и старые удаляются.
Раз привязка идет к заббиксу, там идет привязка по айтемам, что вроде как не раскрывает ничего. В любом случае спасибо.
26. vitall924 83 12.05.22 15:06 Сейчас в теме
(25)

Выбираем визуализацию "Graph (old)"

Указываем Group и Host
Application: "/Рабочий процесс .*/"
Item: "/Захвачено СУБД .*/"

Включаем легенду как таблицу, отображаем Max, Avg и Current.
Непосредственно в визуализации сортируем по Current

Дополнительно настроил Алерты, срабатывает при превышении значения 1800.
Показать


Но тут все индивидуально. Большой вопрос надо это выносить на дашборд или нет.

Пример одной визуализации:
Захвачено СУБД
27. IT_GG 43 17.05.22 12:25 Сейчас в теме
Сделал по инструкции, все работает, очень нравится, вам большое спасибо за это))
НО есть вопрос по рабочим процессам. Если в наименование рабочего процесса использовать его pid то после перезапуска процесса появляется новый Элемент данных, как их в графике указывать, если они каждый раз новые? ))) Надеюсь понятен вопрос
28. vitall924 83 17.05.22 15:50 Сейчас в теме
(27)
На примере количества соединений на рабочих процессах
В классическом графике не получится, а в "современном":
Шаблон узла сети - Имя сервера с которого выполняется сбор данных (центральный сервер)
Шаблон элемента данных - "Рабочий процесс ServerName:*/*: Соединения", где ServerName - имя рабочего сервера. Если серверов несколько я разделяю на несколько графиков.

Если сервер один, то можно и так: "Рабочий процесс *:*/*: Соединения"
29. maksa2005 535 11.05.23 14:17 Сейчас в теме
Помогите решить проблему. Что значит эта ошибка?
Cannot open file: [2] No such file or directory
Прикрепленные файлы:
31. vitall924 83 23.05.23 13:13 Сейчас в теме
(29) Добрый день, Максим.
Видимо не может найти результирующий JSON файл со значениями

Результат сохраняем в файл, который в дальнейшем будет парсить сервер Zabbix:
$cluster_data_json | ConvertTo-Json -Depth 7 -Compress | Out-File -FilePath "C:\Program Files\Zabbix Agent\Scripts\1c_server_data.json" -Force -Encoding UTF8


Путь к папке с файлом данных 1c_server_data.json указывается на вкладке "Макросы" шаблона

В моём случае:
Макрос: "{$CLUSTER1C.SCRIPTPATH}"
Значение: "C:\Program Files\Zabbix Agent\scripts"
30. maksa2005 535 11.05.23 14:18 Сейчас в теме
И подскажите как вывести 1 в 1 как у Вас график? или надо самостоятельно добавлять его в панель zabbix?
32. vitall924 83 23.05.23 13:25 Сейчас в теме
(30) Графики и панели я не включал в шаблон, поэтому делать на свой вкус.
Я делал для панели у дежурных администраторов в Grafana, а для сопровождения различные дашборды в Zabbix

Для примера приложил настройки графика "PRHOST % загруженности процессора"

Набор данных - имя центрального сервера кластера, на котором вы осуществляете сбор.
шаблон элемента данных - метрика, значения которой надо вывести. я вывожу все метрики по шаблону "Рабочий процесс {SERVERNAME}:*/*: % загруженности процессора"
Прикрепленные файлы:
33. maksa2005 535 23.05.23 14:51 Сейчас в теме
(32)Долго ждал ответ, пришлось данные брать по api с разных баз, но где- то средствами zabbix)
Но путь по созданию графиков Вы мне дали, конечно не grafna, но можно увидеть то что хочу видеть + тригеры в телегу. Спасибо Вам, за статью и толчок) Много чего увидел, оптимизировал, усовершенствовал.
Прикрепленные файлы:
vitall924; +1 Ответить
34. Tiotimolin 27.03.24 12:46 Сейчас в теме
Добрый день, Виталий.
А как быть в случае, когда кластер требует авторизации?
Есть ли макросы, с помощью которых можно передать из Заббикса?
Эта ошибка говорит именно об этом?

Ошибка при сборе данных:
new-object : Не удалось получить фабрику класса COM для компонента с CLSID {181E893D-73A4-4722-B61D-D604B3D67D47} из-за следующей ошибки: 8000401a Процесс сервера не мож
ет быть запущен, так как указана неправильная идентификация. Проверьте правильность указания имени пользователя и пароля. (Исключение из HRESULT: 0x8000401A).
C:\Program Files\Zabbix Agent\scripts\get_cluster_data.ps1:17 знак:15
Прикрепленные файлы:
35. Tiotimolin 27.03.24 12:51 Сейчас в теме
Настраивал на сервере 1с без авторизации и столкнулся с ошибкой
ConvertFrom-StringData - Unrecognized escape sequence \C.
Пришлось немного изменить скрипт, экранировав "\"
Строка 263
$BaseInfo_content += ($info[5] -replace ";","`n" -replace "\\","\\\\") | ConvertFrom-StringData
После этого данные стали парситься правильно.
36. vitall924 83 28.03.24 07:20 Сейчас в теме
(34)
Доброе утро, Фёдор.
Есть 2 варианта:
1. Настроить запуск службы Заббикса от доменного/локального пользователя с правами администратора кластера.
2. Запускать скрипт Планировщиком Windows от имени доменного/локального пользователя с правами администратора кластера.

Мы пошли по 2 пути.
37. nick_salander 18.04.24 09:50 Сейчас в теме
 $NumberOfCores[$workingserver.HostName] = (Get-CimInstance Win32_ComputerSystem -ComputerName $workingserver.HostName).NumberOfLogicalProcessors


Данная конструкция при указании параметра -ComputerName организует сессию ws-managment, если у вас не настроен winrm то конструкция не сработает, далее по коду
$processes_clone[$process_id] | Add-Member -MemberType NoteProperty -Name 'CPU_Usage' -Value ([math]::Round($counter_process / $NumberOfCores[$process.HostName],2))
произойдет деление на непонятно что и итоговый JSON будет кривым, в результате не отработает LLD.
38. vechiy 35 26.04.24 12:33 Сейчас в теме
можно ли с помощью данного мониторинга смотреть (и оповещать) по условию - например, захваченоСУБД на одном из сеансов превысило 100.000?
39. vitall924 83 26.04.24 16:20 Сейчас в теме
(38) да, отдельно необходимо настроить соответствующий триггер
Оставьте свое сообщение