Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 47 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
# Преобразование логов http accesslog в метрики с vector.dev

В данном каталоге лежат файлы описывающий подход, позволяющий генерировать метрики из логов без переписывания кода трансформов под каждый сервис.
В данном каталоге лежат файлы описывающий подход, позволяющий генерировать [метрики из логов](https://vector.dev/docs/reference/configuration/transforms/log_to_metric/) без переписывания кода трансформов [vector.dev](https://vector.dev/) под каждый сервис.

**Внимание!** [Версия v1](https://github.com/vseinstrumentiru/vector.dev-metrics-to-logs-helper/tree/1.0.0) содержала [баг #1](/../../issues/1) который проявлялся, только если вы добавляли разные определения метрик (разные лейблы, разные фильтры). В текущей версии это исправлено (см. [новый граф обработки](docs/vector_topology-separate-metric-fileters.svg)).
**Описание:**

1. Полагаемся на то, что все сервисы пишут логи в фиксированном формате JSON и имеют одинаковый набор обязательных полей. См. [example_logs]
2. Для кодогенерации использован Ansible и jinja2 шаблоны. Генерируем toml файлы конфигурации vector.dev и тесты к ним, где нужно.
3. Метрики определяются в файле [ansible-playbook/vars/metrics-catalog.<env>.yml], после этого запускаем генерацию через ansible. См пример в Makefile. По умолчанию генерируется для `env=testing`, чтобы генерировать для production запускать `VECTOR_ENV=production make <команда>`
4. Отдельной задачей конфигурации выгружаются на серверы с агрегаторами vector.dev, и для применения новой конфигурации выполняется перезапуск процесса vector
4. Отдельной задачей конфигурации выгружаются на серверы с агрегаторами vector.dev, и для применения новой конфигурации выполняется перезапуск процесса vector (здесь не приведены).


## Как было раньше

Каждый раз под новый источник мы писали новый код VRL, часто делая copy/paste с незначительными правками. Это могло занимать с отладкой и тестами весь рабочий день.
Потому в 2023 нас это перестало устраивать и мы придумали это подход. Подробно читайте https://habr.com/ru/articles/809801/ и https://habr.com/ru/articles/864614/.

## Что нам дал рефакторинг

* Мы вместо 5 часов теперь тратим 10-30 минут на добавление/изменение метрик с учетом выкатки на прод
* Появилась автоматическая валидация по схеме, теперь ошибку при описании метрки допустить сложнее
* Теперь для добавления новой метрки не нужно знать как это закодировать на языку VRL - достаточно YAML девелопера )
* Теперь для добавления новой метрки не нужно знать как это закодировать на языке VRL - достаточно YAML девелопера )


## Ограничения
Expand All @@ -31,6 +37,43 @@
4. Выполните сборку и тесты `VECTOR_ENV=<env> make test-vector-transforms`, если не указать VECTOR_ENV, то используется `VECTOR_ENV=testing`
5. Созданные файлы смотрите в каталоге [.generated/vector_config]

## Граф компонентов vector.dev

В приведенной конфигурации создается следующий граф компонентов:

![Граф компонентов vector.dev](docs/vector_topology-v1.2.svg)


## Как писать фильтры в metric-catalog.yml правлиьно

* При описании указывайте фильтры по полям с наименьшим количеством значений и сравниваемых через простое сравнение без регулярных выражений - это улучшит производительнсоть обработки.
* В последнию очередь добавляйте условия с регулярными выржениями re/nre, т.к. чем позже они в выражении, тем больше шанс, что простые условия отсеят событие раньше.
* Старайтесь всегда сначала обходиться простыми условиями, и лишь при невозможности их применения переходить на условия с регулярными выржениями re/nre.

Пример более тяжелого для вычисления фильтра (плохой пример):

- selector: Исключаем из метрик логи канарееченого релиза, которые получен для запросов из внутренней сети. Чтобы это не попадало SLO
filter:
service_name:
re: "^.*-canary(-.*)?$"
namespace:
re: ".*-production"
is_internal_traffic:
eq: "1"


Тот же фильтр с измененным порядокм полей будет вычисляться быстрее (хороший пример):

- selector: Исключаем из метрик логи канарееченого релиза, которые получен для запросов из внутренней сети. Чтобы это не попадало SLO
filter:
is_internal_traffic: # << поставили на первое место простой фильтр
eq: "1"
namespace:
re: ".*-production"
service_name:
re: "^.*-canary(-.*)?$"


## Контакты

Если вам интересны подробности вы можете писать нам, см. сайт https://vitech.team/ ("По вопросам сотрудничества") или приходите работать к нам.
Expand Down
54 changes: 42 additions & 12 deletions ansible-playbook/vars/metrics-catalog.testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ metrics_catalog:
exclude_events:
- selector: Исключаем из метрик логи канарееченого релиза, которые получен для запросов из внутренней сети. Чтобы это не попадало SLO
filter:
is_internal_traffic:
eq: "1"
namespace:
eq: "webshop-production"
is_internal_traffic:
eq: "1"
service_name:
re: "^.*-canary(-.*)?$"
- selector: Исключаем /health(z)
filter:
http_path:
re: "/healthz?"

metrics:
vi_http:
Expand All @@ -33,33 +37,33 @@ metrics_catalog:
##
- selector: "Запросы к главной странице интернет магазина"
filter:
http_path: # имя поля в событии лога (входящие данные трансформа vector.dev)
# возможные условия отбора: eq -> ==, neq -> !=, re -> match_any(), nre -> !match_any.
# Порядок вычисления условий в группе: neq, nre, eq, re, (oneOfRe - не реализован)
eq: "/" # оператор и значение для сравнениея
namespace:
eq: "webshop-production"
service_name:
re: "^webshop(?:-canary)?$"
http_path: # имя поля в событии лога (входящие данные трансформа vector.dev)
# возможные условия отбора: eq -> ==, neq -> !=, re -> match_any(), nre -> !match_any.
# Порядок вычисления условий в группе: neq, nre, eq, re, (oneOfRe - не реализован)
eq: "/" # оператор и значение для сравнениея
http_method:
eq: "GET"
- selector: "Запросы на создание заказа в интернет магазине"
filter:
http_path:
re: "^/order$|^/order-fast$"
namespace:
eq: "webshop-production"
service_name:
re: "^webshop(?:-canary)?$"
http_path:
re: "^/order$|^/order-fast$"
- selector: "Открытие страницы производителя в интернет магазине"
filter:
http_path:
re: "^/vendor/(?P<name>([^/]+/)+)$"
label_override: "/vendor/:name"
namespace:
eq: "webshop-production"
service_name:
re: "^webshop(?:-canary)?$"
http_path:
re: "^/vendor/(?P<name>([^/]+/)+)$"
label_override: "/vendor/:name"
testdata: # указывать в ключах имена полей на выходе из transforms.http_accesslog-k8s
- test:
input_values:
Expand All @@ -83,12 +87,12 @@ metrics_catalog:
- test: canary
input_values:
service_name: "webshop-canary"
namespace: "webshop-production"
container_name: "frontend"
cluster_name: "test::dc2-old"
http_path: "/vendor/gigant-2/"
http_method: "GET"
http_status_code: "200"
namespace: "webshop-production"
duration_sec: "0.3"
kubernetes.pod_node_name: "ox2-kub-prod18"
expect:
Expand All @@ -99,6 +103,32 @@ metrics_catalog:
cluster_name: "test::dc2-old"
container_name: "frontend"
service_name: "webshop-canary"
- selector: "Все запросы на Webshop Circuit Breaker"
filter:
service_name:
eq: "webshop-cb"
http_path:
re: ".*"
label_override: ":url_path"
testdata: # указывать в ключах имена полей на выходе из transforms.http_accesslog-k8s
- test:
input_values:
http_path: "/brand/abc-123/sub-1234/"
http_method: "GET"
http_status_code: "200"
duration_sec: "2.1"
cluster_name: "any_dc"
container_name: "any_cn"
kubernetes.pod_node_name: "ox2-kub-prod18"
service_name: "webshop-cb"
expect:
label_values:
path: ":url_path"
method: "GET"
status: "200"
cluster_name: "any_dc"
container_name: "any_cn"
service_name: "webshop-cb"
# Метрика vi_http_request_duration_seconds
request_duration_seconds: # требуется для transforms.metrics-http-accesslog-k8s - бакеты определены там
metric_type: histogram
Expand Down
Loading