VictoriaLogs – відносно нова система для збору та аналізу логів, схожа на Grafana Loki, але – як і VictoriaMetrics в порівнянні з “ванільним” Prometheus – менш вибаглива до ресурсів CPU/Memory.
Особисто я користуюсь Grafana Loki років 5, але до неї іноді буває дуже багато питань – і по документації, і по загальній складності системи, бо багато компонентів, і по перформансу – бо як я її не тюнив (див. Grafana Loki: оптимізація роботи – Recording Rules, кешування та паралельні запити), але іноді на відносно невеликих запитах Grafana повертає 504 від Loki Gateway, і я, якщо чесно, вже втомився з цим розбиратись.
Ну а оскільки у нас сам моніторинг побудований на VictoriaMetrics, і до VictoriaLogs вже “завезли” підтримку Grafana data source – то прийшов час спробувати її в роботі, і порівняти з Grafana Loki.
Чого у VictoriaLogs поки що нема:
- підтримки AWS S3 бекенду – але обіцяють зробити в листопаді 2024 (до того, ж якоюсь “магічною” автоматизацією – коли старі дані з локального диску автоматично будуть перенесені до відповідного S3)
- поки що нема аналога Loki RecordingRules – коли з логів створюємо звичайні метрики, їх записуємо в VictoriaMetrics/Prometheus, а потім робимо алерти в VMAlert та дашборди в Grafana, але знов-таки скоро має бути – жовтень-листопад 2024
- Grafana data source теж ще в Beta, тому є складності з побудовою графіків в Grafana
І прям біда з всякими ChatGPT для генерації запитів – але про це поговоримо далі.
Документація – як завжди у VictoriaMetrcis чудова – VictoriaLogs.
Ще про останні апдейти VictoriaLogs говорили на мітапі VictoriaMetrics Meetup June 2024 – VictoriaLogs Update.
Цікаві скріншоти з бенчмарками VictoriaLogs vs ELK vs Grafana Loki – Benchmark for VictoriaLogs.
Roadmap по VictoriaLogs – тут>>>.
Тож що будемо сьогодні робити:
- запустимо VictoriaLogs в Kubernetes
- подивимось на можливості її LogsQL
- підключимо Grafana data source
- подивимось, як можна створити дашборду в Grafana
Зміст
VictoriaLogs Helm chart
Деплоїти будемо з Helm-чарта vm/victoria-logs-single.
Такоє є підтримка в VictoriaMetrics Operator (див. VLogs).
Ми на проекті використовуємо власний чарт для нашого моніторингу (див. VictoriaMetrics: створення Kubernetes monitoring stack з власним Helm-чартом), в якому через Helm dependency встановлюється чарт victoria-metrics-k8s-stack + всякі додаткові сервіси типу Promtail, k8s-event-logger etc. В цей же чарт додамо victoria-logs-single.
Для початку зробимо все руками, спочатку з якимись дефолтними values, потім подивимось, що воно нам встановить в Kubernetes і як воно працює – а потім будемо додавати в автоматизацію.
В чарті VictoriaLogs є можливість відразу запустити Fluetbit DaemonSet, але в нас вже є Promtail, тому будемо використовувати його.
Всі values
є в документації до чарту, а з того, що може бути цікаве зараз:
extraVolumeMounts
таextraVolumes
: можемо створити власний окремийpersistentVolume
з AWS EBS, та підключати його до VictoriaLogspersistentVolume.enabled
таpersistentVolume.storageClassName
: або можемо просто вказати, що його треба створювати, і при потребі задати власнийstorageClass
з RelaimPolicyretain
ingress
: в моєму випадку частина логів пишеться з AWS Lambda, тому потрібно буде створювати AWS ALB з типом Internal
Встановлення чарту
Додаємо репозиторій:
$ helm repo add vm https://victoriametrics.github.io/helm-charts/ $ helm repo update
Встановлюємо чарт в окремий Kubernetes Namespace ops-test-vmlogs-ns
:
$ helm -n ops-test-vmlogs-ns upgrade --install vlsingle vm/victoria-logs-single
Перевіряємо Kubernetes Pod:
$ kk get pod NAME READY STATUS RESTARTS AGE vlsingle-victoria-logs-single-server-0 1/1 Running 0 36s
І глянемо на ресурси:
$ kk top pod NAME CPU(cores) MEMORY(bytes) vlsingle-victoria-logs-single-server-0 1m 3Mi
3 мегабайти пам’яті 🙂
Забігаючи наперед – після підключення запису логів з Promtail до VictoriaLogs ресурсів буде використовуватись не набагато більше.
Відкриваємо доступ до UI:
$ kk -n ops-test-vmlogs-ns port-forward svc/vlsingle-victoria-logs-single-server 9428
В браузері заходимо на http://localhost:9428.
Як і інші сервіси від VictoriaMetrics – попадаємо на сторінку з усіма необхідними посиланнями:
Переходимо на http://localhost:9428/select/vmui/ – поки що тут пусто:
Додамо відправку логів з Promtail.
Налаштування Promtail
До VictoriaLogs можна писати логи в форматі Elasticsearch, ndjson або Loki – див. Data ingestion.
Власне нас цікавить саме Loki, і логи ми пишемо з Promtail. Приклад конфігурації Promtail для VictoriaLogs див. у Promtail setup.
У нас Promtail встановлюється з його власного чарту, який створює Kubernetes Secret з promtail.yml
.
Оновлюємо values чарту, в config.clients
додаємо ще один URL – в моєму випадку він буде неймспейсом з ops-test-vmlogs-ns.svc
, бо VictoriaLogs запущена в іншому неймспейсі, ніж Loki:
... promtail: config: clients: - url: http://atlas-victoriametrics-loki-gateway/loki/api/v1/push - url: http://vlsingle-victoria-logs-single-server.ops-test-vmlogs-ns.svc:9428/insert/loki/api/v1/push ...
Деплоїмо зміни, чекаємо рестарту подів з Promtail, і ще раз перевіряємо логи в VictoriaLogs:
VictoriaLogs Log Streams
Під час запису логів до VicrotiaLogs ми можемо задати додаткові параметри – див. HTTP parameters.
З того, що може бути цікавим зараз – це спробувати створити власні Log Stream, аби по ним потім робити фільтрацію логів для більш швидкої їх обробки. див. Stream fields.
Якщо лог-стрім не заданий – то VictoriaLogs пише все в один дефолтний стрім {}
, як ми бачили на скріні вище.
Наприклад, у нас в кластері всі аплікейшени розбиті по власним Kubernetes Namespaces – dev-backend-api-ns, prod-backend-api-ns, ops-monitoring-ns і т.д.
Давайте створимо окремий стрім на кожен неймспейс – до url
додаємо ?_stream_fields=namespace
:
... config: clients: - url: http://atlas-victoriametrics-loki-gateway/loki/api/v1/push - url: http://vlsingle-victoria-logs-single-server.ops-test-vmlogs-ns.svc:9428/insert/loki/api/v1/push?_stream_fields=namespace ...
Деплоїмо, і тепер маємо окремі стріми на кожен неймспейс:
VicrotiaLogs vs Loki: ресурси CPU/Memory
Давайте просто глянемо на ресурси, які зараз в мене споживають всі поди для роботи Loki::
$ kk -n ops-monitoring-ns top pod | grep loki atlas-victoriametrics-loki-chunks-cache-0 2m 824Mi atlas-victoriametrics-loki-gateway-6bd7d496f5-9c2fh 1m 12Mi atlas-victoriametrics-loki-results-cache-0 1m 32Mi loki-backend-0 50m 202Mi loki-backend-1 8m 214Mi loki-backend-2 12m 248Mi loki-canary-gzjxh 1m 15Mi loki-canary-h9d6s 1m 17Mi loki-canary-hkh4f 2m 17Mi loki-canary-nh9mf 2m 16Mi loki-canary-pbs4x 1m 17Mi loki-read-55bcffc9fb-7j4tg 12m 255Mi loki-read-55bcffc9fb-7qtns 45m 248Mi loki-read-55bcffc9fb-s7rpq 10m 244Mi loki-write-0 42m 262Mi loki-write-1 27m 261Mi loki-write-2 26m 258Mi
Та ресурси VictoriaLogs:
$ kk top pod NAME CPU(cores) MEMORY(bytes) vlsingle-victoria-logs-single-server-0 2m 14Mi
При тому, що пишеться однакова кількість логів.
Так – в Loki зараз є пачка RecordingRules, так – є пара дашборд в Grafana, які виконують запити напряму до Loki для графіків, але ж ну камон! Це небо і земля!
Можливо, це ще й мої криві руки, які не змогли нормально затюнити Loki – проте VictoriaLogs зараз запущена взагалі без всякого тюнингу.
LogsQL
Окей – маємо інстанс VictoriaLogs, маємо логи, які в неї пишуться.
Давайте спробуємо “покверяти” і розібратися з LogsQL взагалі, та трохи порівняти з LogQL від Loki.
Документація по LogsQL для VictoriaLogs – тут>>>.
Запити ми можемо робити з VM UI, з CLI та з Grafana – див. Querying.
Запити з HTTP API
У VictoriaLogs дуже приємний API, з яким можна отримати всі необхідні дані.
Наприклад, для пошуку по логам за допомогою curl
можемо зробити запит до /select/logsql/query
, а потім через unix pipe передати до jq
.
Все ще маємо запущений kubectl port-forward
, робимо запит з пошуком всіх логів зі словом “error“:
$ curl -s localhost:9428/select/logsql/query -d 'query=error' | head | jq { "_time": "2024-09-02T12:23:40.890465823Z", "_stream_id": "0000000000000000195443555522d86dcbf56363e06426e2", "_stream": "{namespace=\"staging-backend-api-ns\"}", "_msg": "[2024-09-02 12:23:40,890: WARNING/ForkPoolWorker-6] {\"message\": \"Could not execute transaction\", \"error\": \"TransactionCanceledException('An error occurred (TransactionCanceledException) when calling the TransactWriteItems operation: Transaction cancelled, please refer cancellation reasons for specific reasons [None, None, ConditionalCheckFailed]')\", \"logger\": \"core.storage.engines.dynamodb_transactions\", \"level\": \"warning\", \"lineno\": 124, \"func_name\": \"_commit_transaction\", \"filename\": \"dynamodb_transactions.py\", \"pid\": 2660, \"timestamp\": \"2024-09-02T12:23:40.890294\"}", "app": "backend-celery-workers", "component": "backend", "container": "backend-celery-workers-container", "filename": "/var/log/pods/staging-backend-api-ns_backend-celery-workers-deployment-66b879bfcc-8pw52_46eaf32d-8956-4d44-8914-7f2afeda41ad/backend-celery-workers-container/0.log", "hostname": "ip-10-0-42-56.ec2.internal", "job": "staging-backend-api-ns/backend-celery-workers", "logtype": "kubernetes", "namespace": "staging-backend-api-ns", "node_name": "ip-10-0-42-56.ec2.internal", "pod": "backend-celery-workers-deployment-66b879bfcc-8pw52", "stream": "stderr" } ...
І в результаті маємо всі поля та Log Stream, який задали вище – по полю Namespace.
Ще з цікавих ендпоінтів – можливість отримати всі стріми, в логах яких є ключове слово, наприклад:
$ curl -s localhost:9428/select/logsql/streams -d "query=error" | jq { "values": [ { "value": "{namespace=\"ops-monitoring-ns\"}", "hits": 5012 }, { "value": "{namespace=\"staging-backend-api-ns\"}", "hits": 542 }, ...
Запити з VM UI
Тут все просто – пишемо запит в полі Log queiry, отримуємо результат.
Результат можемо сформувати в форматі Group by, Table та JSON – його ми вже бачили в HTTP API.
В форматі Group by результат виводиться по кожному стріму:
А в форматі Table – колонками по іменам полей з логів:
Синтаксис LogsQL
Взагалі, можливостей прям дуже багато – див. всі в документації LogsQL.
Але давайте глянемо хоча б основні, аби мати уяву що ми можемо робити.
Самий простий приклад запитів з LogsQL ми вже бачили – просто по слову “error“.
Аби виконати пошук по фразі – “загортаємо” її в лапки:
Сортування
Важливий нюанс – результати повертаються у довільному порядку з метою покращення перформансу, тому рекомендується використовувати sort
pipe по полю _time
:
_time:5m error | sort by (_time)
Comments
Дуже прикольно, що ми в запити можемо додавати коментарі, наприклад:
_time:5m | app:="backend-api" AND namespace:="prod-backend-api-ns" # this is a comment | unpack_json | keep path, duration, _msg, _time # and an another one comment | stats by(path) avg(duration) avg_duration | path:!"" | limit 10
Оператори
В LogsQL вони називаються Logical filter – AND
, OR
, NOT
.
Наприклад, використати AND можемо так – шукаємо запис, в якому є строка “Received request” та ID “dada85f9246d4e788205ee1670cfbc6f“:
"Received request" AND "dada85f9246d4e788205ee1670cfbc6f"
Або зробити пошук по “Received request” тільки зі стриму namespace="prod-backend-api-ns"
:
"Received request" AND _stream:{namespace="prod-backend-api-ns"}
Або по полю pod
:
"Received request" AND pod:="backend-api-deployment-98fcb6bcb-w9j26"
При чому оператор AND
можна не задавати явно, тото запит:
"Received request" pod:="backend-api-deployment-98fcb6bcb-w9j26"
Буде відпрацьований аналогічно попередньому.
Але в прикладах далі я все ж буду додавати AND
для ясності.
Фільтри
Будь-який запит LogsQL має містити хоча б один фільтр.
Коли ми робимо запит на кшталт “Received request” – то фактично ми використовуємо фільтр Phrase filter, який за замовченням застосовується до поля _msg
.
А в запиті _stream:{namespace="prod-backend-api-ns"}
ми використовуємо Stream filter.
Інші цікаві фільтри:
- Time filter – можна задати проміжок часу в хвилинах/годинах або датах
- Day та Week range filter – або виконати пошук по конкретним датам чи дням тижня
- Prefix filter – пошук по неповному слову або фразі
- Case-insensitive filter – пошук без урахування регістру
- Regexp filter – регулярні вирази в пошуку
- IPv4 range filter – це прям кілер-фіча – готовий фільтрі для IP-адрес
Давайте швиденько глянемо кілька прикладів.
Time filter
Вибрати всі записи за останню хвилину:
"Received request" AND _time:1m
Або за 1.09.2024:
"Received request" AND _time:2024-09-01
Або за проміжок часу – 30-го серпня по 2 вересня включно:
"Received request" AND _time:[2024-08-30, 2024-09-02]
Або без записів за 2024-08-30 – тобто, починаючи з 31-го числа – міняємо [
на (
:
"Received request" AND _time:(2024-08-30, 2024-09-02]
Day range filter
Фільтри по годинам дня.
Наприклад, всі записи між 14:00 і 18:00 сьогодні:
"Received request" AND _time:day_range[14:00, 18:00]
Аналогічно до Time filter – використовуємо ()
та []
аби включити або виключити початок чи кінець range.
Week range filter
Подібний до Day range filter, але по днях тижня:
"Received request" AND _time:week_range[Mon, Fri]
Prefix filter
За допомогою “*
” вказуємо, що нам потрібні всі логи, які починаються з фрази “ForkPoolWorker-1” – тобто, всі воркери з 1, 12, 19 і т.д:
"ForkPoolWorker-1"*
Аналогічно можемо використовувати цей фільтр для значень в полях записів.
Наприклад, вибрати всі записи, де поле container
має значення “backend-celery“:
app:"backend-celery-"*
Або ж використати Substring filter:
app:~"backend-celery"
Regexp filter
Пошук з регуляркою, також можна комбінувати з Substring filter.
Наприклад, знайти всі записи з “Received request” АБО “ForkPoolWorker“:
~"Received request|ForkPoolWorker"
Pipes
Ще цікава можливість в LogsQL – використання pipes, через які можна виконувати додаткові операції.
Наприклад, в Grafana мені доволі часто потрібно було робити перейменування імені поля з метрики або лога.
З LogsQL це можна зробити за допомогою | copy
або | rename
:
- є поле
logtype: kubernetes
- хочемо його зробити
source: kubernetes
Виконуємо такий запит:
~"ForkPoolWorker" | rename logtype as source
Інші цікаві pipes:
delete
pipe: видалити поле з результатівextract
pipe: створити нове поле зі значенням із записів в логахfield_names
pipe: поверне всі поля з додавання кількості записівfields
pipe: повернути в результатах тільки обрані поляfilter
pipe: фільтрувати результати з додатковими умовамиlimit
pipe: вивести тільки зазначені кількість результатів (див. такожtop
)math
pipe: виконати математичні операціїoffset
pipe: теж прикольна штука – зробити “зміщення” на кількість результатівpack_json
pipe: “запакувати” всі поля з результатів в JSON (див. такожpack_logfmt
таunpack_json
)replace
pipe: замінити слово/фразу в результатах на інше (маскувати паролі)sort
pipe: операції сортування в результатахstats
pipe: вивести статистику
Я вже не буду тут описувати приклади, бо в цілому вони – і багато іншого – є в документації, але давайте глянемо приклад запиту для Loki, і спробуємо переписати його для VictoriaLogs – і там як раз спробуємо pipes в ділі.
Приклад: Loki to VictoriaLogs query
Є у нас такий запит для Loki RecordingRules:
- record: eks:pod:backend:api:path_duration:avg expr: | topk (10, avg_over_time ( {app="backend-api"} | json | regexp "https?://(?P<domain>([^/]+))" | line_format "{{.path}}: {{.duration}}" | unwrap duration [5m] ) by (domain, path, node_name) )
З логів Kubernetes Pods нашого бекенду створює метрику eks:pod:backend:api:path_duration:avg
, в якій відображає середній час відповіді по ендпоінтам.
В ньому маємо:
- вибираємо логи з лог-стріма
app="backend-api"
- логи пишуться в JSON, тому використовуємо
json
парсер - потім з
regex
parser створюємо полеdomain
зі значенням після “https://“ - з
line_format
отримуємо поляpath
таduration
- з
unwrap
“витягуємо” значення зduration
- рахуємо середнє значення з
duration
за допомогою оператораavg_over_time()
за останні 5 хвилин, групуючи по полямdomain
,path
,node_name
– вони потім використовуються в алертах і графіках Grafana - збираємо інформацію по топ-10 записів
Як ми можемо щось схоже зробити з VictoriaLogs та LogsQL?
Почнемо з фільтра по полю:
app:="backend-api"
Отримуємо всі записи з подів цієї апки.
Пам’ятаємо, що можемо використати тут регулярку, і задати фільтр як app:~"backend"
– тоді будуть результати з app="backend-celery-workers"
, app="backend-api"
і т.д.
Можна додати фільтр по стріму – тільки з продакшена:
_stream:{namespace="prod-backend-api-ns"} AND app:="backend-api"
Або просто:
namespace:="prod-backend-api-ns" AND app:="backend-api"
В наших метриках Loki неймспейс не використовується, бо фільтри в алертах і Grafana використовують ім’я домену з поля domain
, але тут для приклада най буде.
Далі нам треба створити поля domain
, path
та duration
.
Тут можна використати або unpack_json
– або extract
.
unpack_json
розпарсить JSON, і створить поля для запису з кожного ключа в JSON:
- в документації до
unpack_json
говориться, що краще використовуватиextract
pipe - якщо використовувати його, то запит був би
| extract '"duration": <duration>,'
Але нам всі поля не потрібні – тому можемо дропнути всі, і з фільтром keep
залишити тільки duration
, _msg
та _time
:
Далі, нам потрібно створити поле domain
. Але просто взяти key url
який створив unpack_json
із {"url": "http://api.app.example.co/coach/notifications?limit=0" ...}
нам не підходить, бо потрібен тільки домен – без строки “/coach/notifications?limit=0“.
Можемо додати фільтр extract_regexp
– extract_regexp "https?://(?P<domain>([^/]+))"
:
Тепер, маючи всі три поля, можемо використати stats by()
і avg
по полю duration
:
А аби прибрати з результатів {"path":"","domain":"","avg(duration)":"NaN"}
– додаємо фільтр path:!""
.
Тепер весь запит буде:
app:="backend-api" | unpack_json | keep path, duration, _msg, _time | extract_regexp "https?://(?P<domain>([^/]+))" | stats by(path, domain) avg(duration) | path:!""
Останнім додаємо ліміт в останні 5 хвилин – _time:5m
, і виводимо тільки топ-10 результатів.
Я тут приберу domain
і додам фільтр по namespace
, аби простіше було порівняти з результатами в Loki.
Результат avg(duration)
будемо писати в нове поле avg_duration
.
Тепер весь запит буде таким:
_time:5m | app:="backend-api" AND namespace:="prod-backend-api-ns" | unpack_json | keep path, duration, _msg, _time | stats by(path) avg(duration) avg_duration | path:!"" | limit 10
Результат:
Замість limit
можна використати top
pipe – бо limit
просто обмежує кількість запитів, а top
обмежує саме по значенню поля:
_time:5m | app:="backend-api" AND namespace:="prod-backend-api-ns" | unpack_json | keep path, duration, _msg, _time | stats by(path) avg(duration) avg_duration | path:!"" | top 10 by (path, duration)
І можемо додати sort()
, а умову path:!""
винести перед викликом stats()
, аби швидше оброблювався запит:
_time:5m | app:="backend-api" AND namespace:="prod-backend-api-ns" | unpack_json | keep path, duration, _msg, _time | path:!"" | stats by(path) avg(duration) avg_duration | sort by (_time, avg_duration) | top 10 by (path, avg_duration)
Порівняємо його з результатом з Loki, наприклад – API-ендпоінт /sprint-planning/backlog/challenges
в результатах VictoriaLogs у нас тут має значення 160.464981 мілісекунд.
Виконуємо аналогічний запит в Loki:
topk (10, avg_over_time ( {app="backend-api", namespace="prod-backend-api-ns"} | __error__="" | json | line_format "{{.path}}: {{.duration}}" | unwrap duration [5m] ) by (path) )
Все сходиться.
ChatGPT, Gemini, Claude та LogsQL (але Perplexity!)
Спробував з ними переписувати запити з Loki LogQL на VictoriaMetrics LogsQL – тут все дуже пєчально.
ChatGPT взагалі прям дуже глючить, і видає оператори типу SELECT
, яких взагалі нема:
Gemini трохи краще, принаймні з більш-менш реальними операторами – але все одного не той випадок, коли можна просто скопіювати і використати:
І Claude – аналогічно до ChatGPT, нічого не знає – але пропонує “щось подібне”:
А от Perplexity відповів майже вірно:
Тільки спутав порядок – by()
має бути після stats()
.
Helm, VictoriaLogs та Grafana data source
Репозиторій та документація – victorialogs-datasource.
VictoriaLogs sub-chart installation
Давайте відразу вже сюди додамо VictoriaLogs. Нагадаю, що у нас весь стек моніторинг встановлюється з нашого власного чарту, в якому через Helm dependency додаються victoria-metrics-k8s-stack
, k8s-event-logger
, aws-xray
і т.д.
Видаляємо встановлений вручну чарт:
$ helm -n ops-test-vmlogs-ns uninstall vlsingle
В файлі Chart.yaml
описуємо ще один dependency
:
apiVersion: v2 name: atlas-victoriametrics description: A Helm chart for Atlas Victoria Metrics kubernetes monitoring stack type: application version: 0.1.1 appVersion: "1.17.0" dependencies: - name: victoria-metrics-k8s-stack version: ~0.25.0 repository: https://victoriametrics.github.io/helm-charts - name: victoria-metrics-auth version: ~0.6.0 repository: https://victoriametrics.github.io/helm-charts - name: victoria-logs-single version: ~0.6.0 repository: https://victoriametrics.github.io/helm-charts ...
Оновлюємо сабчарти:
$ helm dependency build
Оновлюємо свої values – додамо постійний сторейдж:
... victoria-logs-single: server: persistentVolume: enabled: true storageClassName: gp2-retain size: 3Gi # default value, to update later ...
Деплоїмо, і перевіряємо сервіс для VictoriaLogs:
$ kk get svc | grep logs atlas-victoriametrics-victoria-logs-single-server ClusterIP None <none> 9428/TCP 2m32s
Редагуємо конфіг Promtail – задаємо новий URL:
... promtail: config: clients: - url: http://atlas-victoriametrics-loki-gateway/loki/api/v1/push - url: http://atlas-victoriametrics-victoria-logs-single-server:9428/insert/loki/api/v1/push?_stream_fields=namespace ...
Підключення Grafana data source
Трохи довелось повозитись з values для Grafana, але в результаті вийшло так:
... grafana: enabled: true env: GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: "victorialogs-datasource" ... plugins: - grafana-sentry-datasource - grafana-clock-panel - grafana-redshift-datasource - https://github.com/VictoriaMetrics/victorialogs-datasource/releases/download/v0.4.0/victorialogs-datasource-v0.4.0.zip;victorialogs-datasource additionalDataSources: - name: Loki type: loki access: proxy url: http://atlas-victoriametrics-loki-gateway:80 jsonData: maxLines: 1000 timeout: 3m - name: VictoriaLogs type: victorialogs-datasource access: proxy url: http://atlas-victoriametrics-victoria-logs-single-server:9428
Версію шукаємо на сторінці Releases, зараз остання v0.4.0
.
І зверніть увагу, що версія в URL задається два рази – /releases/download/v0.4.0/victorialogs-datasource-v0.4.0.zip
.
Деплоїмо, при необхідності рестартимо поди з Grafana (якщо не використовуємо щось по типу Reloader), і перевіряємо датасорси:
Пробуємо з Explore:
Все працює.
Grafana dashboards на Time series visualization
З візуалізацією в Grafana поки що не все чудово, бо потрібно додавати transformations, аби Grafana panel коректно відобразила дані.
Довелось додавати їх як мінімум три:
- Extract fields: результат від VictoriaLogs ми отримуємо в JSON, і з цією трансформацією з нього витягуємо всі поля
- Convert field type: поле ‘duration’ в JSON приходить в string, тому його треба змінити на Number
- Sort by: сортуємо по полю ‘avg_duration’
- Prepare time series: для конвертації результатів в формат, який зрозуміє Time series visualization panel
Без цього будемо мати помилки типу “Data is missing a number field“, “Data is missing a time field” або “Data outside time range“.
Налаштування трансформацій:
Запит для графіка такий:
app:="backend-api" namespace:="prod-backend-api-ns" | unpack_json | keep path, duration, _msg, _time | path:!"" | stats by(_time:1m, path) avg(duration) avg_duration
Зверніть увагу, що тут _time
переміщено у виклик stats()
– робити статистку по останній хвилині для кожного path
.
І результат такий:
Крім того, Data source поки не дає можливості переписати Options > Legend.
Висновки
Складно робити якісь висновки отак одразу, але в цілому – система подобається, і однозначно варта того, аби її спробувати.
До LogsQL треба звикнути та навчитись з ним працювати, але можливостей дає більше.
По ресурсам CPU/Memory – тут взагалі жодних питань.
Grafana data source працює, чекаємо на його реліз.
Ну і чекаємо, коли завезуть підтримку AWS S3 та аналог Loki RecordingRules, бо на сьогодні VictoriaLogs можна використовувати виключно як систему для роботи з логами – але не для графіків чи алертів.
Біда, що всякі ChatGPT толком не можуть допомогти з запитами LogsQL, бо для Loki я ними користувався доволі часто, але згодом і вони цьому навчаться. Проте Perplexity відповідає майже без помилок.
Отже, з плюсів:
- працює дійсно швидше, і дійсно НАБАГАТО менше споживає ресурсів
- LogsQL приємний, багато можливостей
- документація у VictoriaMetrics завжди досить детальна, з прикладами, добре структурована
- підтримка у VictoriaMetrics теж чудова – і в GitHub Issues, і в Slack, і в Telegram – завжди можна поставити питання, і досить швидко отримати відповідь
- на відміну від Grafana Loki – VictoriaLogs має власний Web UI, і як на мене – то це жирний плюс
З відносних мінусів:
- і VictoriaLogs і Grafana data source все ще в Beta – тому можливі і якісь неочікувані проблеми, і не всі можливості поки що реалізовані
- але знаючи команду VictoriaMetrics – вони досить швидко все роблять
- відсутність RecordingRules та підтримки AWS S3 – це наразі те, що блокує особисто мене від того, аби повністю видалити Grafana Loki
- але всі основні плюшки мають завезти до кінця 2024
- ChatGPT/Gemini/Claude прям зовсім погано знають LogsQL, тому на їх допомогу очікувати не треба
- але є допомога в Slack, і в Telegram самої VictoriaMetrics – і від комьюніті, і від команди розробників, ну і Perplexity непогано справляється