┌─────────┐
| Alerting| # mAlert https://github.com/Qedr1/malert
└────▲────┘
|
┌────────┐ ┌────┴──────┐
# Grafana │ VIEWER │ | QUEUE+KV | # NATS
└────▲───┘ └────▲──────┘
│ table + |
│ mat. view |
└▲────────────┘
|
┌────┴────┐
│ STORAGE │ # ClickHouse
└────▲────┘
│ insert (batch)
┌─────┴─────┐
│ COLLECTOR │ # vector.dev
└─────▲─────┘
│ events gRPC (batch)
┌───┴────┐
│ HOST │ # magent
└────────┘
magent собирает системные метрики: утилизация сетевых интерфейсов, CPU, RAM, disk, fs, netflow-пары, сетевой стек, ядро, процессы и т. д. Также собирает произвольные внешние метрики: выполняет скрипты, принимает через http_server или опрашивает через http_client.
Ключевые отличия:
- экономия трафика. Компактная структура данных без дублирования. Бинарный протокол между агентом и коллектором
- комплексный мониторинг сетевой активности хоста, включая сбор flow-телеметрии и метрики/состояние алгоритма управления перегрузкой сетевого стека (congestion control)
- эффективная фильтрация событий на стороне агента
- отказоустойчивость. Локальные очереди доставки и failover до коллектора
- эффективный коллектор. Произвольный препроцессинг и процессинг. Локальные очереди доставки в хранилище
- хранилище. Скорость записи/поиска почти не зависит от объема данных
Решение мониторит совокупную инфраструктуру на 21к хостов с приростом хранилища ~2TB в сутки.
magent
- file size: 3.7 MB (upx)
- vCPU:1
- RES mem: 21MB
- RAM total: 128MB
~1 719 event/s
~18 801 metrics/s
~97% load average
коллектор (vector)
- file size: 136 MB
- vCPU:2
- RES mem: 82MB
- RAM total: 512MB
~25 785 event/s
~282 015 metrics/s
~182% load average
-
потребляет минимум ресурсов и сетевой полосы пропускания. Реализует высокую автономность, надежность сбора и доставки данных через собственные очереди, failover и батчи отправки
-
метрики собираются один раз за период опроса и отправляются в локальный батч один раз за период отправки. Один период отправки может содержать 1..n периодов опроса
-
батч отправляется в коллектор при накопленном количестве событий либо по таймауту
-
каждая метрика собирается своим отдельным асинхронным воркером. Каждый воркер имеет свой период опроса метрики и свой период отправки. Если метрика не указана в конфиге, она не собирается, воркер не создается
-
отдельный тип воркера умеет запускать внешние скрипты и получать произвольные данные от него в строгом стандартном формате
-
периоды сбора/опроса и отправки задаются в конфиге и могут быть переопределены для каждой метрики
-
по каждой метрике собирается
last, а процентилиpXX(если включены) пересчитываются один раз за период отправки по выборкам периода опроса -
между агентом и коллектором (vector) события передаются в Vector Protocol v2 (gRPC over HTTP/2, бинарный protobuf). EventWrapper.log
-
обязательные теги: dc, project, role, host. Задаются в секции конфига [global]. Добавляются во все события и не могут переопределяться в секциях метрик. Метрика не может создавать собственные теги. Если host отсутствует/пустой — берётся
os.Hostname(). Отсутствие других тегов недопустимо -
dt — время опроса метрики агентом (uint64, миллисекунды).
-
dts — время отправки метрики в коллектор (секунды).
-
dtv — время обработки метрики в коллекторе (секунды).
-
реализует failover. Адрес коллектора — это массив в формате "адрес:порт". При недоступности одного адреса агент идёт в другой. Если недоступны все адреса — сохраняет в локальную очередь этого коллектора
-
отправляет одновременно в несколько коллекторов, если они определены конфигом
-
агент имеет собственную дисковую очередь на каждый коллектор по принципу first in, first out. При недоступности коллектора данные пишутся в очередь и хранятся в готовом для отправки формате
-
агент копит данные и отправляет в коллектор только батчами. Размер батча и очереди задается в конфиге коллектора
-
коллектор принимает массив событий. Каждое событие (log event) разворачивает в плоскую структуру.
data— объект (map) видаvar_name -> {last,pXX...}. При развороте в ClickHouse формируется N строк по числу пар (key × var × agg), гдеagg ∈ {last,pXX}из конфига. Запись в CH идёт батчами по 1000 шт. или по минутному интервалу. Это даёт универсальность схемы хранения и максимальную скорость поиска/записи в ClickHouse
- формат TOML
-configпринимает путь к одному TOML-файлу или к директории; для директории агент читает только*.tomlи объединяет их в лексикографическом порядке имён файлов- в
config dirодиночные таблицы ([global],[metrics],[log.*],[pprof],[db.*]) описывайте один раз; повторение таких секций в разных файлах приведёт к ошибке TOML - отдельная секция для каждой сущности: глобальные параметры вместе с тегами, коллектор, логи, метрики и т. д.
- метрику можно описать любое количество раз, и каждая секция генерирует собственное событие. Повтор задается как массив таблиц
[[metrics.<name>]] - теги используются как глобальные переменные и содержатся во всех метриках. Определяются в глобальной секции. Не могут быть переопределены в секции метрики
- значение переменных может быть получено из переменных окружения или systemd-сервиса. Формат
${VAR} - в глобальной секции должны быть определены обязательные теги dc (датацентр), project (подпроект в продукте), role (роль хоста в продукте)
- если тег host не задан или пустой — берем имя сервера (
os.Hostname()) - секция
[db.clickhouse]задаёт параметры подключения к ClickHouse дляdocs/teststooling:host,port,database,user,password,secure,dial_timeout - секция
[pprof]включает runtime-профилирование агента:enabled,listen(host:port, например127.0.0.1:6060) - hot reload конфига выполняется по
SIGHUP: агент перечитывает и валидирует путь из-config(файл или директория), затем полностью пересоздаёт runtime (все воркеры/коллекторы/listeners); при ошибке применения автоматически возвращает предыдущий рабочий runtime - при успешном hot reload окна агрегации сбрасываются и новые события начинают копиться заново по новым параметрам
- вывод в консоль цветной строкой
- кастомный пакет поверх стандартного slog. Содержит логику раскраски событий в консоли
- два режима логирования: консоль и файл. Сообщения в консоль раскрашиваются по уровню логов и паттернам текста (строка/ip-адрес/число)
- для каждого режима отдельный уровень логирования
- стандартные уровни логов: info/warn/error/panic/debug
- в файл или консоль пишем строкой или в JSON (задается в конфиге)
- если в консоль пишем строкой, применяется раскраска строк по уровню события
- info: события прикладной логики (не системной)
- warn: ошибка, не нарушающая прикладную логику приложения. Выполнение программы продолжается. Качество данных гарантируется
- error: ошибка, нарушающая прикладную или системную логику приложения. Выполнение программы продолжается. Качество данных не гарантируется
- panic: ошибка, нарушающая и прикладную, и системную логику приложения. Выполнение программы невозможно
- debug: отладочный режим. Пишем любую итерацию в программе
- в
collector.batch.max_eventsсобытием считается целый объект метрики (metric + key + data), а не отдельная параvar/value; разворот в строки (var,agg,value) выполняется уже в Vector. - по каждой метрике всегда фиксируется
last; процентилиpXXсчитаются только если они заданы в конфиге. - метрики собираются по периоду опроса (scrape), агрегируются и отправляются в батч по периоду отправки (send). Если процентили не указаны, период опроса метрики (scrape) равен периоду отправки метрики (send)
- процентили вычисляет сам агент на основе конфига.
- на выходе из агента все метрики нормализуются: все числовые непроцентные значения в
dataпреобразуются в uint64, процентные — в uint8. Округление математическое (0.5 и выше — вверх, ниже 0.5 — вниз) 0считается валидным значением выборки- если в периоде опроса нет значений,
last=0, а при включенных процентилях всеpXX=0 - процентили (если включены) агрегируются один раз за период (send) по измеренным значениям за периоды scrape.
dt,dtsне подчиняются этим правилам и передаются как есть- встроенные метрики отправляются в lower-case (
cpu,ram,swap,net,netflow,disk,fs,process) для прямого маппинга в lower-case таблицы ClickHouse
Универсальная структура пакета данных любой метрики
dt // дата и время опроса события. Один раз за период опроса, мсек
dts // дата и время отправки события. Один раз за период отправки, сек
metric // название метрики (по этому полю создается таблица CH)
dtv // формируется в коллекторе. Время обработки события
dc // локация сервера. Обязательный глобальный тег
host // имя хоста, на котором собрана метрика. Обязательный глобальный тег. Если не задан явно — берётся из ОС
project // название проекта. Обязательный глобальный тег
role // роль хоста в системной архитектуре (frontdb/back/db ...). Обязательный глобальный тег
host_ip // формируется агентом при отправке в коллектор из локального TCP адреса соединения
key // обязательный строковый ключ метрики
data // все метрики и их значения. Например ram_total, ram_used, cpu_total и т.д.
Принципы key
- key всегда строка и всегда присутствует
- если у метрики нет естественного ключа, используется
key="total" - если у метрики несколько сущностей, агент формирует отдельное событие на каждую сущность с собственным key
- при развороте в плоскую таблицу кол-во строк = кол-во key × кол-во элементов в data × кол-во элементов в agg.
т. е. в таблице для каждого key формируется набор строк: по одной строке на каждую пару (
data,agg) (строка содержитkey,var,agg,value).
Пример универсальной структуры
{
"metric": "cpu",
"dt": 1231231232,
"dts": 1231231254,
"dc": "DC1",
"host": "host1",
"project": "Infra",
"role": "DB_Postgres",
"key": "core0",
"data": {
"util": { "last": 67, "p90": 97, "p99": 98 }
}
}Пример метрики CPU в таблице ClickHouse:
|dc |host|project|role|host_ip |key |var |agg |value|
+---+----+-------+----+---------+-----+----+----+-----+
|dc1|dev |infra |soak|127.0.0.1|core0|util|last| 1|
|dc1|dev |infra |soak|127.0.0.1|core0|util|p50 | 1|
|dc1|dev |infra |soak|127.0.0.1|core0|util|p90 | 2|
|dc1|dev |infra |soak|127.0.0.1|core0|util|p99 | 2|
|dc1|dev |infra |soak|127.0.0.1|core1|util|last| 0|
|dc1|dev |infra |soak|127.0.0.1|core1|util|p50 | 1|
|dc1|dev |infra |soak|127.0.0.1|core1|util|p90 | 1|
|dc1|dev |infra |soak|127.0.0.1|core1|util|p99 | 1|
|dc1|dev |infra |soak|127.0.0.1|core2|util|last| 0|
|dc1|dev |infra |soak|127.0.0.1|core2|util|p50 | 1|
|dc1|dev |infra |soak|127.0.0.1|core2|util|p90 | 2|
|dc1|dev |infra |soak|127.0.0.1|core2|util|p99 | 2|
|dc1|dev |infra |soak|127.0.0.1|core3|util|last| 1|
|dc1|dev |infra |soak|127.0.0.1|core3|util|p50 | 1|
|dc1|dev |infra |soak|127.0.0.1|core3|util|p90 | 1|
|dc1|dev |infra |soak|127.0.0.1|core3|util|p99 | 1|
|dc1|dev |infra |soak|127.0.0.1|total|util|last| 1|
|dc1|dev |infra |soak|127.0.0.1|total|util|p50 | 1|
|dc1|dev |infra |soak|127.0.0.1|total|util|p90 | 1|
|dc1|dev |infra |soak|127.0.0.1|total|util|p99 | 1|
LowCardinality снижает накладные расходы на дублируемые строковые поля.
Системная метрика загрузки CPU по ядрам и в агрегате по хосту.
- секция конфига:
[[metrics.cpu]] - key: строковый идентификатор сущности метрики;
coreNдля отдельного ядра илиtotalдля агрегата по всем ядрам. - util: утилизация либо всех ядер либо конкретного ядра, uint8, %
Системная метрика использования оперативной памяти хоста.
- секция конфига:
[[metrics.ram]] - key: строковый идентификатор сущности метрики; всегда
total. - total: вся физическая память. uint64, bytes
- used: использованная память. uint64, bytes
- free: доступная память. uint64, bytes
- util: утилизация (used/total*100). uint8, %
Системная метрика использования swap-памяти хоста.
- секция конфига:
[[metrics.swap]] - key: строковый идентификатор сущности метрики; всегда
total. - total: размер свапа. uint64, bytes
- used: использовано. uint64, bytes
- util: утилизация. uint8, %
Системная метрика ядра Linux из /proc/loadavg и /proc/stat.
- секция конфига:
[[metrics.kernel]] - key: строковый идентификатор сущности метрики; всегда
total. - load1: средняя нагрузка за 1 минуту. uint64
- load5: средняя нагрузка за 5 минут. uint64
- load15: средняя нагрузка за 15 минут. uint64
- procs_running: количество runnable задач. uint64, количество
- procs_blocked: количество blocked задач. uint64, количество
- ctxt_per_sec: переключения контекста за интервал опроса (в сек). uint64, опер/сек
- intr_per_sec: аппаратные прерывания за интервал опроса (в сек). uint64, опер/сек
- softirq_per_sec: softirq за интервал опроса (в сек). uint64, опер/сек
- forks_per_sec: созданные процессы за интервал опроса (в сек). uint64, опер/сек
Системная метрика блочных устройств; собираются только базовые диски, партиции игнорируются (/dev/sda1, /dev/sda2, /dev/nvme0n1p1, /dev/mmcblk0p1).
- секция конфига:
[[metrics.disk]] - key: строковый идентификатор сущности метрики; путь к базовому блочному устройству (
/dev/...). - rx_io: операций чтения в секунду. uint64, операций/сек
- tx_io: операций записи в секунду. uint64, операций/сек
- rx_bytes: прочитано байт за интервал опроса. uint64, bytes
- tx_bytes: записано байт за интервал опроса. uint64, bytes
- rx_bytes_per_sec: скорость чтения. uint64, bytes/сек
- tx_bytes_per_sec: скорость записи. uint64, bytes/сек
- rx_await: общее среднее время ожидания ввода-вывода за чтение. uint64, мс
- tx_await: общее среднее время ожидания ввода-вывода на запись. uint64, мс
- await: общее среднее время ожидания ввода-вывода. uint64, мс
- qdepth: глубина очереди запросов к устройству. uint64, количество
- util: утилизация устройства по IOPS. uint8, %
- inflight: количество запросов в полёте (отправлены, не завершены). uint64, количество
Системная метрика файловых систем по точкам монтирования.
- секция конфига:
[[metrics.fs]] - key: строковый идентификатор сущности метрики; точка монтирования
<mpoint>. - total: общий размер файловой системы. uint64, bytes
- used: использовано. uint64, bytes
- free: свободно. uint64, bytes
- avail: доступно (с учётом reserved). uint64, bytes
- util: утилизация файловой системы. uint8, %
- inodes_total: общее количество inodes. uint64, количество
- inodes_used: использовано inodes. uint64, количество
- inodes_free: свободно inodes. uint64, количество
- inodes_util: утилизация inodes. uint8, %
- readonly: файловая система в режиме только чтения (0/1). uint8
Системная метрика сети: интерфейсные счетчики + host-level TCP/UDP стек + TCP congestion snapshot.
- секция конфига:
[[metrics.net]] - key: строковый идентификатор сущности метрики; используется в трёх режимах:
<iface>(напримерeth0) для интерфейсных vartotalдля host-level TCP/UDP varcc:<algo>(напримерcc:cubic) для TCP congestion snapshot
- для key=
<iface>:- tx_bytes: отправлено байт за интервал опроса. uint64, bytes
- rx_bytes: получено байт за интервал опроса. uint64, bytes
- tx_bytes_per_sec: скорость отправки. uint64, bytes/сек
- rx_bytes_per_sec: скорость приема. uint64, bytes/сек
- tx_pkt: отправлено пакетов в секунду. uint64, пакетов/сек
- rx_pkt: получено пакетов в секунду. uint64, пакетов/сек
- rx_err: ошибки приёма. uint64, количество
- tx_err: ошибки отправки. uint64, количество
- rx_drop: отброшено при приёме. uint64, количество
- tx_drop: отброшено при отправке. uint64, количество
- для key=
total:- tcp_active_opens: новые active TCP opens за интервал опроса. uint64, количество
- tcp_passive_opens: новые passive TCP opens за интервал опроса. uint64, количество
- tcp_retrans_segs: TCP ретрансмит-сегменты за интервал опроса. uint64, количество
- tcp_timeouts: TCP timeouts за интервал опроса. uint64, количество
- tcp_out_rsts: TCP reset-пакеты за интервал опроса. uint64, количество
- udp_in_datagrams: входящие UDP datagrams за интервал опроса. uint64, количество
- udp_out_datagrams: исходящие UDP datagrams за интервал опроса. uint64, количество
- udp_in_errors: UDP ошибки приёма за интервал опроса. uint64, количество
- udp_no_ports: UDP пакеты на закрытые порты за интервал опроса. uint64, количество
- udp_rcvbuf_errors: UDP recv-buffer ошибки за интервал опроса. uint64, количество
- udp_sndbuf_errors: UDP send-buffer ошибки за интервал опроса. uint64, количество
- для key=
cc:<algo>:- tcp_sockets: число TCP socket-сэмплов (после top-N). uint64, количество
- tcp_tx_queue_bytes: сумма TCP tx-queue (bytes) по сэмплам. uint64, bytes
- tcp_rx_queue_bytes: сумма TCP rx-queue (bytes) по сэмплам. uint64, bytes
- tcp_retrans_pending: сумма pending retransmits по сэмплам. uint64, количество
- tcp_cwnd_segs: средний cwnd (segments) по сэмплам. uint64, количество
tcp_cc_top_n: лимит TCP socket-сэмплов для key=cc:<algo>;0отключаетcc:*
Системная pull-метрика top-N сетевых flow-пар по интерфейсам (без cgo).
- секция конфига:
[[metrics.netflow]] - использует ту же кодовую базу доставки, что и другие pull-метрики:
scrape -> window aggregate -> collector batch/queue/failover -> Vector -> ClickHouse. materialized view разворачивает значения составного ключа в отдельную таблицуnetflow_pairs - key: строковый идентификатор сущности метрики; составной ключ
iface|proto|src_ip|src_port|dst_ip|dst_port. - vars:
bytes,packets,flows - все счетчики считаются за окно
scrapeи сбрасываются после каждого опроса (не монотонные):bytes: сумма байт пакетов потока за окноpackets: количество пакетов потока за окноflows: количество новых flow за окно
- правило
flows:- TCP: +1 только на пакете с флагами
SYN && !ACK(новое соединение) - UDP: +1 при первом пакете tuple или после простоя tuple не меньше
flow_idle_timeout(по умолчанию10s)
- TCP: +1 только на пакете с флагами
- поддерживаются несколько интерфейсов через маски
ifaces = ["eth*","enp*","lo"] top_nограничивает число flow-ключей, отправляемых за окно- для raw-capture нужны привилегии: запуск агента от
root(или capabilityCAP_NET_RAW) - рекомендуемый режим:
percentiles = [](last-only)
Системная метрика процессов с отбором по порогам cpu_util/ram_util/iops (логика ИЛИ, достаточно одного порога за окно отправки).
- секция конфига:
[[metrics.process]] - key: строковый идентификатор сущности метрики; имя процесса (
proc.Name, без pid/cmdline). - cpu_util: утилизация CPU процессом. uint8, %
- ram_util: утилизация RAM процессом =
rss_process/ram_total_host*100. uint8, % - iops: операции чтения и записи процессом с блочного устройства. uint64, опер/сек
Пользовательская pull-метрика из внешнего скрипта [[metrics.script.<name>]], где stdout содержит format=json ({key,data}) или format=prometheus (text exposition).
- секция конфига:
[[metrics.script.<name>]] - key: строковый идентификатор сущности метрики; для
jsonберётся из поляkey, дляprometheusфиксированtotal(labels игнорируются). - для
format=prometheus: принимаются толькоgauge/counter,var_mode=full|short; отбор переменных делается стандартнымиfilter_var/drop_var/drop_event. - при ненулевом exit code скрипта данные не отправляются
- для каждого скрипта создаётся отдельная таблица в ClickHouse (
<name>) - схема хранения для script-метрик полностью совпадает с остальными:
dt,dts,dtv, теги,key,var,agg,value - пользователь самостоятельно создаёт стандартную схему таблицы ClickHouse под конкретный скрипт с обязательным полем
key.
Пользовательская push-метрика: агент поднимает HTTP endpoint, принимает внешние данные и отправляет их по общим правилам.
- секция конфига:
[[metrics.http_server.<name>]] - key: строковый идентификатор сущности метрики; для
jsonберётся из поляkey, дляprometheusфиксированtotal(labels игнорируются). - HTTP:
POST http://<listen><path>; тело запроса в форматеjsonилиprometheus(поformatв конфиге); успешный приём:204 - для
format=prometheus: принимаются толькоgauge/counter,var_mode=full|short; отбор переменных делается стандартнымиfilter_var/drop_var/drop_event. - нет периода
scrape(данные приходят извне); используется толькоsend(период агрегации/отправки) max_pendingограничивает буфер принятых пакетов; при переполнении политика фиксированная: сохраняем старое, дропаем новое (503)
Пользовательская pull-метрика: агент делает GET по URL, парсит ответ в json или prometheus и отправляет данные по общим правилам.
- секция конфига:
[[metrics.http_client.<name>]] - key: строковый идентификатор сущности метрики; для
jsonберётся из поляkey, дляprometheusфиксированtotal(labels игнорируются). - поддерживаемые форматы ответа:
format=json(контракт{key,data}) иformat=prometheus(text exposition, только gauge/counter) - для
format=prometheus:var_mode=full|short; отбор переменных делается стандартнымиfilter_var/drop_var/drop_event - HTTP:
GET(пока только GET); формат ответа определяется полемformat urlподдерживает переменные в пути (path-escaped):{dc},{host},{project},{role},{metric},{instance}instance= имя воркера (nameв конфиге или автогенерированное), используется только для URL и логов (в событие/БД не попадает)
- отдельный тип метрик, формируемый внешним скриптом или приложением
- применяются те же правила доставки и агрегации, что и для обычных метрик
- общие поля события (
dt,dts, глобальные теги,metric) формируются агентом, а не внешним источником format=json: один и тот же JSON-контракт для stdout скрипта, body HTTP-SERVER, response HTTP-CLIENT- root: объект или массив объектов; каждый объект = 1 сущность метрики (1
key) - минимальный пример:
{"key":"total","data":{"util":{"last":67}}}data.<var>: число, bool (0/1) или объект{last: <number>, kind?: "percent"|"number"}format=prometheus: text exposition; принимаются толькоgauge/counter;keyфиксированtotalformat=prometheus: labels игнорируются; если для одногоvarпришло несколько series (разные labels), агент суммирует их значения в рамках одного scrapelast/pXXсчитает агент и уже их сохраняет/отправляет- общий лимит payload для
jsonиprometheus:16 MiB(больше — отклоняется) - для внешних метрик (
script/http_server/http_client) без данных в окне событие не отправляется (synthetic zero не генерируется)
- раздел
[metrics]: параметры по умолчанию для всех метрик.[[metrics.<name>]]— раздел конкретной метрики.[[metrics.script.<name>]]— метрика, собираемая внешним скриптом.[[metrics.http_server.<name>]]— push HTTP-метрика.[[metrics.http_client.<name>]]— pull HTTP-метрика - для внешних метрик (
script,http_server,http_client):formatпо умолчаниюjson; дляprometheusиспользуетсяvar_mode=full|short, а отбор — черезfilter_var/drop_var/drop_event percentiles— агрегаты значений раз в период отправки по периодам опроса. Массив целых значений (например[50,90,99]); ключи в JSON формируются какpXX- если
percentilesне заданы ни глобально, ни в метрике, агрегации нет. Сохраняется только последнее измеренное значение за период отправкиlast(безpXX) - если глобальные
percentilesзаданы, метрика наследует их по умолчанию - если в конкретной метрике указать
percentiles = [], процентили для этой метрики отключаются (толькоlast) - интервалы scrape/send задаются с суффиксами времени (например 5s, 1m). Задаются глобально и могут быть переопределены в каждой метрике
- для
[[metrics.net]]доступен параметрtcp_cc_top_n(по умолчанию2000);0отключает key=cc:<algo> - исключение по умолчанию: для
[[metrics.process]]при отсутствии явногоscrapeиспользуется20s - drop_var и filter_var фильтруют поля (переменные) метрики, а не их значения. Задаются только в
[[metrics.<name>]]. drop_var удаляет перечисленные переменные метрики. filter_var оставляет только перечисленные переменные. Можно использовать wildcard-маску*. Действия опциональны. Применяются только к переменным, не к тегам - drop_event дропает событие целиком, если одно или несколько условий выполнены. Формат условия:
<field><op><value>, гдеopin=,!=,>,<. - для строк с
=и!=поддерживается wildcard*(пример:cmd=*postgres*,key!=core*) - пример:
drop_event = ["iops>10000","key!=core*","var=rx_*"] - пример фильтрации по DISK ключам:
[[metrics.disk]]
name = "disk-main"
drop_event = ["key=/dev/loop*", "key=/dev/ram*"]
[[metrics.disk]]
name = "disk-nvme-only"
drop_event = ["key!=/dev/nvme*"]
filter_var = ["util", "*_bytes", "*_bytes_per_sec"]- теги не попадают под drop_var/filter_var/drop_event
- таймаут выполнения скриптов в секундах (по умолчанию 5s), опционально
- путь к скрипту для метрик из внешних скриптов, обязателен только в секции вызова скриптов
- для
[[metrics.process]]доступны порогиcpu_util,ram_util,iops. Если указаны — берём события выше или равные хотя бы одному порогу (логика ИЛИ). Если все три порога отсутствуют в конфиге, метрика не собирается
- Transport: Vector Protocol v2 (gRPC over HTTP/2, бинарный protobuf).
- Семантика события: отправляем как log-event (структурированный payload), чтобы сохранять “пакет” 1:1 и не дробить на множество metric-events.
- Отправлять батчами как PushEventsRequest с events: [EventWrapper, ...] (100..300/1000 шт), одним RPC.
- конфиг коллекторов задаётся массивом
[[collector]] - внутри одного
[[collector]]полеaddr = ["host1:port","host2:port"]используется в режиме failover (по очереди) - если задано несколько
[[collector]], отправка выполняется во все коллекторы независимо - на подключение устанавливаются timeout, retry_interval
- при временном переполнении внутреннего буфера отправки применяется backpressure: запись в буфер ждёт освобождения места или отмены context (без немедленного дропа события)
- отдельная дисковая очередь на каждый коллектор.
- сохраняет сообщения по принципу «первый пришёл, первый ушёл», если все адреса коллектора недоступны. Пытается отправить раз в N секунд бесконечно. Очередь копится по количеству событий и/или по времени, что наступит раньше
- хранит данные в нативном protobuf формате vector (тот же формат что и при отправке)
- запись — только append в конец файла. Редактирование и удаление отдельных записей не поддерживается
- чтение — последовательное, с хранением текущего offset в самой очереди и кэшированием в памяти
- при отправке: читаем из файла батчами, отправляем. Если связь пропала — offset остаётся на месте, продолжаем при восстановлении
- offset синхронизируется батчами/по таймеру (не на каждый ack), при корректной остановке принудительно flush
- после полной отправки всего содержимого файла — файл очищается (
truncate), offset сбрасывается в0 - путь к директории хранения очередей задаётся в конфиге (
collector.queue.dir, обязательный параметр приenabled=true)
- addr принимает массив значений в формате адрес:порт
[[collector.queue]]по умолчаниюenabled=false.dir— путь до очереди,max_events— максимальное количество событий,max_age— время хранения в очереди. Работает то, что наступит раньше. Если указано что-то одно — работает только оно. При достижении лимитов старые события остаются, а новые не принимаются- данные для отправки копятся в батчи по количеству событий или по времени. Что наступит раньше
[[collector.batch]]:max_events— количество событий в батче,max_age— период накопления батча. Работает то, что наступит раньше- очередь и батчи ведутся отдельно для каждого коллектора, независимо от количества адресов в нём
- Vector обрабатывает пришедшее событие log-event Vector Protocol v2
- разворачивает одно событие в N. Количество строк = сумма по всем переменным в data. Например:
disk— имя таблицы,rx_io—var,last/p90—agg,value— конкретные значения - для keyed полей (например core): каждый ключ × каждый агрегат = отдельная строка
- роутинг в таблицу по имени метрики:
table = {metric_name} - трансформация выполняется средствами VRL (Vector Remap Language): remap (разворот в массив событий); отдельный route не используется
- результаты
[[metrics.script.<name>]]направляются в таблицу<name> - стандартное поле времени события (.timestamp) переименовывается в dtv
- host_ip берём из локального TCP адреса отправителя (агент добавляет поле перед PushEvents)
- одна таблица на каждое имя метрики
- для script-метрик имя таблицы равно
<name> - для netflow аналитики используется связка:
- raw-таблица
netflow(универсальная схемаdt,dts,dtv,tags,key,var,agg,value, в ней хранятся входные агрегаты потока) - materialized view
mv_netflow_pairs(парсит составнойkeyиз raw-события и формирует аналитические поля пары) - итоговая таблица
netflow_pairs(парыiface/proto/src_ip/src_port/dst_ip/dst_port+bytes/packets/flows)
- raw-таблица
Имя таблицы задается по имени метрики
dt: DateTime64(3) CODEC(DoubleDelta) // дата и время опроса события. один раз за период опроса, мсек
dts: DateTime CODEC(DoubleDelta) // дата и время отправки события. один раз за период отправки, сек
dtv: DateTime DEFAULT now() CODEC(DoubleDelta) // время обработки события в Vector, сек
dc: LowCardinality(String) // хостер или площадка сервера, с которого пришла метрика. обязательный тег
host: LowCardinality(String) // имя хоста, с которого пришла метрика. обязательный тег
project: LowCardinality(String) // название проекта или часть системной архитектуры (frontdb/back)
role: LowCardinality(String) // роль хоста в системной архитектуре (frontdb/back/db ...)
host_ip: IPv6 // внешний IP-адрес хоста, с которого пришла метрика
key: LowCardinality(String) // обязательный ключ метрики
var: LowCardinality(String) // конкретная переменная метрики. total, used, util и т.д.
agg: LowCardinality(String) // название агрегата переменной метрики. last, p90, p99 и т.д.
value: UInt64 // конкретное значение агрегата agg
ORDER BY: (dt, host, key)
Партиционирование toYYYYMMDD(dt)
TTL: dt + INTERVAL 4 MONTH
dt: DateTime64(3) CODEC(DoubleDelta) // время окна агрегации в агенте
dts: DateTime CODEC(DoubleDelta) // время отправки в коллектор
dtv: DateTime CODEC(DoubleDelta) // время вставки в итоговую таблицу
dc: LowCardinality(String) // глобальный тег
host: LowCardinality(String) // глобальный тег
project: LowCardinality(String) // глобальный тег
role: LowCardinality(String) // глобальный тег
host_ip: IPv6 // IP отправителя события
iface: LowCardinality(String) // интерфейс
proto: LowCardinality(String) // протокол (tcp/udp/...)
src_ip: IPv6 // source IP
src_port: UInt16 // source port
dst_ip: IPv6 // destination IP
dst_port: UInt16 // destination port
bytes: UInt64 // байты за окно
packets: UInt64 // пакеты за окно
flows: UInt64 // количество flow-записей за окно
ORDER BY: (dt, host, iface)
PARTITION BY: toYYYYMMDD(dt)
TTL: dt + INTERVAL 4 MONTH
https://github.com/Qedr1/malert
- snmp trap