
Есть популярная утилита мониторинга видеокарты и FPS в играх — MSI Afterburner. С её помощью удобно не только разгонять видеокарту, но и мониторить параметры как видеокарты, так и системы. И можно даже писать данные мониторинга в лог. И здесь раскрывается хорошая возможность передавать данные из Afterburner в Zabbix.
Изначальные условия таковы: ОС Windows 10, Zabbix 6.0, Zabbix agent 2 v.7 (windows), MSI Afterburner 4.6.5
Формат файла лога — csv, имеет следующую структуру
00, <дата>, Hardware monitoring log v1.6
01, <дата>, NVIDIA GeForce GTX 1070 Ti
02, <дата>, GPU temperature ,GPU usage, ...и другие параметры, которые можно включить на вкладке Мониторинг.
80, <дата>, 53.000 ,4.000 , ...остальные параметры
Ранее, я делал простой способ парсинга этих данных — в заббиксе для итема использовал встроенную функцию log() и в аргументах указывал регулярку для поиска нужного значения, то есть что-то типа
log[{$AB_FILE_DATA},".{46}(.{6}).*",,,,\1]
, где $AB_FILE_DATA путь к файлу лога, указывается в макросах шаблона
оно всё находило нужное, но если я в MSI Afterburner выберу другие данные системы для мониторинга, то придётся все регулярки переписывать заново. Неудобно. Поэтому пока я настроил и забыл.
Однако пришли нейронки и появилась идея спросить у них, в данном случае — Qwen.
В процессе борьбы с глюками поиска нейронка сначала выдала вполне работающий скрипт на PowerShell, а вот с шаблонами для заббикса пошли косяки — квен упорно выдавал то шаблоны с ненужными UID, то с лишними полями, видимо подразумевая, что у меня 7 версия заббикс-сервера, даже если ему прямо сказать версию. В итоге плюнул, создал свой базовый шаблон, подсунул квену, и тот что-то «понял».
По итогу решено было делать мониторинг через внешний скрипт на PowerShell. Плюсы — можно в Afterburner менять данные и парсинг не поломается, минусы — работает внешний скрипт, парсит много данных, время на ответ больше, требуется увеличение таймаутов в заббиксе. Так-то не критично, но неприятно.
Для этого необходимо подготовить систему к запуску скрипта сервисом заббикс агента.
Подготовка системы
1. Добавьте в конфигурацию заббикс-агента следующие строки
UserParameter=afterburner.metric[*],powershell -nologo -noprofile -ExecutionPolicy Bypass -File "C:\zabbix\ab_parse.ps1" "$1" "$2"
, где -nologo -noprofile немного ускоряет запуск оболочки PowerShell,
ExecutionPolicy Bypass - разрешает выполнение скриптов, не изменяя настройки политики запуска в Windows.
2. Перезапустите сервис агента
3. Положите в удобное место скрипт ab_parse.ps1 со следующим содержимым:
# ab_parse_fast.ps1
# Usage: .\ab_parse_fast.ps1 "C:\log.txt" "gpu_temp"
param(
[Parameter(Mandatory=$true)][string]$LogPath,
[Parameter(Mandatory=$true)][string]$Metric
)
$lookup = @{
gpu_temp = 'GPU temperature'
gpu_usage = 'GPU usage'
gpu_mem_usage = 'Memory usage' # VRAM
gpu_core_clock = 'Core clock'
fan_speed = 'Fan speed'
cpu_temp = 'CPU temperature'
cpu_usage = 'CPU usage'
cpu_clock = 'CPU clock'
cpu_power = 'CPU power'
ram_usage = 'RAM usage'
}
$headerTarget = $lookup[$Metric]
if (-not $headerTarget) {
[Console]::Error.WriteLine("ERR: Unknown metric '$Metric'")
exit 1
}
if (-not (Test-Path -LiteralPath $LogPath)) {
[Console]::Error.WriteLine("ERR: File not found: $LogPath")
exit 1
}
try {
$headerLine = $null
$dataLine = $null
$lineNum = 0
# Читаем файл построчно — экономим память
# $reader = [System.IO.File]::OpenText($LogPath)
$stream = New-Object System.IO.FileStream($LogPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$reader = New-Object System.IO.StreamReader($stream)
try {
while (-not $reader.EndOfStream) {
$line = $reader.ReadLine()
$lineNum++
# Пропускаем пустые строки
if ([string]::IsNullOrWhiteSpace($line)) { continue }
# Ищем заголовок: 02, или старый формат (без префикса, но с GPU temperature)
if (-not $headerLine) {
if ($line -match '^02,\s*\d{2}-\d{2}-\d{4}') {
$headerLine = $line
continue
}
# Старый формат: первая строка — заголовки, содержит "GPU temperature"
if ($lineNum -eq 1 -and $line -like '*GPU temperature*') {
$headerLine = $line
continue
}
}
# Ищем последнюю строку данных: 80, или старый формат (начинается с цифры+запятая или цифры+точка)
if ($line -match '^80,\s*\d{2}-\d{2}-\d{4}') {
$dataLine = $line # перезаписываем — останется последняя
} elseif (-not $dataLine -and $lineNum -gt 1 -and $line -match '^\d{1,2},\s*\d{2}-\d{2}-\d{4}|^\d{1,3}\.\d{3}') {
# Старый формат: 80 без даты или просто данные
$dataLine = $line
}
}
} finally {
$reader.Dispose()
$stream.Dispose()
}
if (-not $headerLine -or -not $dataLine) {
# Если не нашли — попытка fallback: взять последнюю непустую строку как данные
if (-not $dataLine) {
$lastLines = Get-Content $LogPath -Tail 10 | Where-Object { $_ -match '\d' } | Select-Object -Last 1
if ($lastLines) { $dataLine = $lastLines }
}
if (-not $dataLine) {
Write-Host "0"
exit 0
}
# Заголовок — первая строка (fallback)
if (-not $headerLine) {
$headerLine = Get-Content $LogPath -TotalCount 1
}
}
# Разбор заголовков: split по запятой + trim
$headers = $headerLine.Split(',') | ForEach-Object { $_.Trim() }
$data = $dataLine.Split(',') | ForEach-Object { $_.Trim() }
# Поиск индекса (case-insensitive partial match)
$idx = -1
for ($i = 0; $i -lt $headers.Count; $i++) {
if ($headers[$i] -like "*$headerTarget*") {
$idx = $i
break
}
}
if ($idx -lt 0 -or $idx -ge $data.Count) {
Write-Host "0"
exit 0
}
$rawVal = $data[$idx]
# Оптимизированная очистка: убираем всё, кроме цифр, точки и минуса
# Используем .NET — быстрее регулярок
$cleanVal = [System.Text.RegularExpressions.Regex]::Replace($rawVal, '[^\d\.\-]', '')
# Проверка числа
if ([string]::IsNullOrWhiteSpace($cleanVal) -or -not ($cleanVal -match '^-?\d+(\.\d+)?$')) {
Write-Host "0"
exit 0
}
Write-Host $cleanVal
} catch {
# Минимум вывода — только в stderr, stdout — 0
[Console]::Error.WriteLine("ERR: $($_.Exception.Message.Substring(0, [Math]::Min(100, $_.Exception.Message.Length)))")
Write-Host "0"
exit 0
}
Изначально при генерации этого скрипта не было двух строк, из-за которых чтение лога сопровождалось, видимо, исключением в Afterburner и отключением логирования. Опять же квен помог выявить проблему. Чтение теперь происходит не в режиме
[System.IO.File]::OpenText($LogPath) а в режиме New-Object System.IO.FileStream
что не мешает Afterburner писать логи в файл.
4. Импортируйте шаблон (ссылка будет ниже) или создайте новый примерно такого содержания
Name: CPU Clock
Type: Zabbix agent (active)
Key: afterburner.metric[{$AB_LOG_PATH},cpu_clock]
Type of information: Numeric (float)
Теперь всё готово. Цепляем шаблон к хосту, проверяем с заббикс сервера доступность
zabbix_get -s GPU-Host -k "afterburner.metric[C:\Program Files (x86)\MSI Afterburner\HardwareMonitoring.csv,cpu_temp]"
и если ответ получился через полсекунды, то всё настроено верно.
На этом всё. О наёденных ошибках, огрехах и неточностях сообщайте.
