From 91e281fd32b10385b5bbfa3b42c3dfcfc716d149 Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Fri, 21 Aug 2026 14:00:05 -0400 Subject: [PATCH] =?UTF-8?q?docs(monitoring):=20=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=20=D0=B7=D0=BE=D0=BD=D1=8B?= =?UTF-8?q?=20=D1=80=D0=B0=D0=B7=D1=80=D0=B5=D0=B7=D0=B0=D0=BD=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B0=D0=B1=D0=BE=D1=80=20=D0=B4=D0=BE=D0=BA?= =?UTF-8?q?=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Зачем: - половина справочника была про один дашборд «Данные», а этап приносит ещё два дашборда и правила оповещения: описание самой зоны утонуло бы. - Что: - заведён набор docs/architecture/monitoring/ по ADR 0011: README.md — зона и каталог дашбордов, data.md — устройство дашборда «Данные». - обе входящие ссылки перенацелены: README.md репозитория и ADR 0002. - Проверка: - make config-test; ссылки из README.md и ADR 0002 открываются. --- README.md | 5 +- docs/adr/0002-monitoring-scope.md | 2 +- docs/architecture/monitoring.md | 205 ------------------------- docs/architecture/monitoring/README.md | 116 ++++++++++++++ docs/architecture/monitoring/data.md | 94 ++++++++++++ 5 files changed, 214 insertions(+), 208 deletions(-) delete mode 100644 docs/architecture/monitoring.md create mode 100644 docs/architecture/monitoring/README.md create mode 100644 docs/architecture/monitoring/data.md diff --git a/README.md b/README.md index b7cf56a..f2c3822 100644 --- a/README.md +++ b/README.md @@ -353,8 +353,9 @@ docker compose up --force-recreate --wait clickhouse-01 clickhouse-02 Prometheus собирает встроенные метрики двух серверов и keeper, а через `kafka-exporter` — состояние Kafka. Поверх этого в Grafana поднимается дашборд «Данные»: свежесть, поток, брак, сходимость Kafka с ClickHouse, отставание -чтения и дневной слепок заказов. Устройство зоны и разбор панелей — в -[справочнике мониторинга](docs/architecture/monitoring.md); правил оповещения +чтения и дневной слепок заказов. Устройство зоны — в [справочнике +мониторинга](docs/architecture/monitoring/README.md), разбор панелей — в +[описании дашборда](docs/architecture/monitoring/data.md); правил оповещения пока нет. Airflow закреплён на 3.3.0. Состав обязательных процессов, LocalExecutor, diff --git a/docs/adr/0002-monitoring-scope.md b/docs/adr/0002-monitoring-scope.md index 6debe50..41c6ee3 100644 --- a/docs/adr/0002-monitoring-scope.md +++ b/docs/adr/0002-monitoring-scope.md @@ -120,4 +120,4 @@ ClickHouse, Kafka и Airflow, 17 — в дашборде генератора, 1 модельные сутки значит записать ускорение мира в JSON дашборда — ровно ту пометку, от которой этот же ADR отговаривает выше, — а реальные сутки на стенде не с чем сравнивать. Довод целиком и остальное устройство дашборда — -[docs/architecture/monitoring.md](../architecture/monitoring.md). +[docs/architecture/monitoring/data.md](../architecture/monitoring/data.md). diff --git a/docs/architecture/monitoring.md b/docs/architecture/monitoring.md deleted file mode 100644 index e8cb677..0000000 --- a/docs/architecture/monitoring.md +++ /dev/null @@ -1,205 +0,0 @@ -# Мониторинг: из чего собран и что скребёт - -Документ описывает зону мониторинга: какие сервисы в неё входят, что собирает -Prometheus, какие источники данных подготовлены в Grafana, каким пользователем -она ходит в ClickHouse и что показывают собранные дашборды. Зачем зоне именно -такой состав и какие дашборды на нём задуманы — [ADR -0002](../adr/0002-monitoring-scope.md); устройство доступа — [ADR -0007](../adr/0007-clickhouse-access.md). - -**Что здесь есть и чего ещё нет.** Собран пол: свой образ Grafana с плагином -ClickHouse, два подготовленных источника данных, экспортёр метрик Kafka и цель -для него у Prometheus. Поверх пола стоит главный дашборд — «Данные»; «Кластер» -и «Запросы» приносят отдельные тикеты. Правил оповещения и серверного журнала -`system.text_log` тоже пока нет. - -## Состав - -| Сервис | Образ | Что делает | -|---|---|---| -| `prometheus` | `prom/prometheus:v3.13.2` | опрашивает цели раз в 15 секунд, порт стенда `29090` | -| `grafana` | `clickstream-grafana:local` | интерфейс мониторинга; собирается из `infra/grafana/`, порт стенда `23000` | -| `kafka-exporter` | `danielqsj/kafka-exporter:v1.9.0` | переводит состояние брокера в метрики Prometheus, порт `9308` | - -Плагин ClickHouse 4.20.0 входит в образ Grafana. Фоновая установка плагинов -при запуске отключена. - -## Что скребёт Prometheus - -| Цель | Задание | Метка `role` | Откуда метрики | -|---|---|---|---| -| `clickhouse-01:9363` | `clickhouse` | `server` | встроенный экспортёр ноды | -| `clickhouse-02:9363` | `clickhouse` | `server` | встроенный экспортёр ноды | -| `clickhouse-keeper:9363` | `clickhouse-keeper` | `keeper` | встроенный экспортёр keeper | -| `kafka-exporter:9308` | `kafka` | `exporter` | внешний экспортёр | - -Ровно эти четыре цели пересчитывает `check_prometheus_targets` в -`scripts/stand-smoke.sh` — и по значению `up`, и по списку адресов. Пятая цель -красит смоук; это и есть способ заметить, что состав пола поменяли молча. - -## Источники данных Grafana - -Оба источника подготовлены файлами в `infra/grafana/provisioning/datasources/` -и объявлены `editable: false`: править их через интерфейс нельзя, источник -истины — репозиторий. - -- `prometheus` — основной по умолчанию, ходит на `http://prometheus:9090`. -- `clickhouse` — плагин `grafana-clickhouse-datasource`, нативный протокол, - `clickhouse-01:9000`, пользователь `grafana`, пароль из `.env`. - -Источник ClickHouse смотрит на `clickhouse-01`. Системные таблицы обеих нод -панели читают через `clusterAllReplicas`, как принято в ADR 0002. - -## Доступ к ClickHouse - -Grafana ходит пользователем `grafana` с ролью `monitoring_reader`: читает слои, -таблицы базы `dic` и системные таблицы. `REMOTE` разрешает -`clusterAllReplicas`, `CLUSTER` — запросы `ON CLUSTER`. Решение о своей роли -записано в [ADR 0007](../adr/0007-clickhouse-access.md). Пароль задаётся -переменной `CLICKHOUSE_GRAFANA_PASSWORD`. - -## Куда кладутся дашборды - -Каталог `infra/grafana/provisioning/dashboards/` смонтирован в контейнер и -объявлен провайдером в `provider.yml`: Grafana подхватывает оттуда файлы -дашбордов, удалять и править их через интерфейс запрещено. Новый дашборд — это -новый файл в каталоге и больше ничего: в `compose.yaml` заходить не нужно, ради -этого каталог и заведён заранее. - -Файлы каталога разбирает `make config-test`, рядом с файлами дагов и по тому же -доводу ([testing.md](testing.md)). - -## Дашборд «Данные» - -`infra/grafana/provisioning/dashboards/data.json` — шесть панелей на один -экран. Вопрос у экрана один: с потоком всё в порядке? Состав панелей и довод за -каждую — [ADR 0002](../adr/0002-monitoring-scope.md). - -Порогов и цветовых вердиктов на панелях нет: на дашборд смотрят глазами, -красное и зелёное живёт в проверках и дагах DQ. - -| Панель | Откуда берёт | О чём отвечает | -|---|---|---| -| Свежесть | `ods.event_dist`, `ods.order_dist` | сколько прошло с последней доехавшей строки | -| Поток | `stg.hits_raw_dist`, `stg.orders_raw_dist` | сколько строк приезжает в слой сырья | -| Брак | те же и `ods.*_errors_dist` | сколько приехавшего не разобралось и какая это доля | -| Сходимость | экспортёр Kafka и `stg.hits_raw_dist` | произведённое против приземлившегося | -| Отставание | `kafka_consumergroup_lag` | сколько сообщений не прочитано | -| Дневной слепок | `stg.orders_raw_dist` | какой слепок доехал, когда и после какой паузы | - -### Почему слои у панелей разные - -Свежесть спрашивают у ODS. Это слой, который читают, и у заказов дорога до него -длиннее: сырьё привозит забор, а типизированную строку кладёт разбор. Встань -разбор — свежесть ODS это покажет, свежесть сырья нет. - -Читает свежесть физическую `_dist`, а не каноническое `ods.*_v`. Представление -прячет за собой `FINAL` и отвечает про текущее состояние сущностей, а вопрос -здесь про доставку: местом диагностики доставленных версий физическая таблица -названа там же, где заведено представление (`sql/ddl/30-ods-views.sql`). - -Поток и брак считаются по слою сырья. Сырьё записывает каждую доставку и ничего -не схлопывает, а `ReplacingMergeTree` в ODS схлопнет и повтор доставки события, -и все версии одного заказа. Считай мы поток по ODS — он занизился бы, и тем -сильнее, чем дольше живёт стенд. - -Доля брака берётся от приехавшего, а не от суммы «годные плюс брак»: брак не -отдельная куча, а часть сырья, которая не прошла разбор. - -Окно у панели брака — окно дашборда, и это не косметика. Сырьё живёт трое -суток, а брак — месяц: доля за всё время делила бы месяц брака на трое суток -приехавшего и однажды перевалила бы за сотню процентов. - -Панель дневного слепка, наоборот, окна не знает. Её вопрос про состояние, а не -про отрезок, и последние десять слепков она показывает всегда. - -Отдельного ряда «против вчерашнего» на панели потока нет, и это решение, а не -пропуск. Реальное «вчера» на стенде чаще всего приходится на время, когда -стенда ещё не было. А сдвинуть ряд на модельные сутки значит записать в JSON -дашборда ускорение мира — ровно ту пометку про тик, которую [ADR -0002](../adr/0002-monitoring-scope.md) в дашборде держать не велит: поменяют -ускорение, и панель молча соврёт. Сравнение остаётся глазу: модельные сутки -укладываются в минуты реального времени, и соседние дни мира помещаются в одно -окно панели сами. - -### Чтецов Kafka панели не читают - -`stg.hits_raw_kafka` и `stg.orders_raw_kafka` — таблицы движка Kafka, а не -хранилище: запрос из панели у второго забрал бы слепок себе и сдвинул офсеты -(`kafka_commit_on_select`, см. `sql/ddl/10-stg-tables.sql`), а даг приёма -приехал бы к пустому топику. Приземлившееся панели считают по `stg.*_raw_dist`, -произведённое — по метрикам экспортёра. - -### Как считается сходимость - -Произведённое живёт в Kafka, приземлившееся — в ClickHouse, и со своей стороны -ни одна из них не видит другую. Поэтому панель смешанная: ряд «произведено в -Kafka» приходит из Prometheus, ряд «приземлилось в ClickHouse» — из ClickHouse. -Единицы общие — сообщений за интервал панели. Со стороны Kafka это разность -офсетов топика, «сейчас минус интервал назад», с суммой по обеим партициям; со -стороны ClickHouse — `count()` строк сырья по тому же интервалу. - -Два соседних способа отвергнуты, и оба по замеру на живом стенде. `increase` -растягивает приращение на всё окно и на минутном интервале промахивается на -проценты: здоровый стенд выглядел бы расходящимся. Накопленный итог от начала -окна точнее обоих приростов, но отсчитывать его надо от края окна — а на -свежем стенде окно начинается раньше, чем появился экспортёр, и ряд пропадает -целиком. - -Столбцы ClickHouse подписаны правым краем, а не левым. Точка Prometheus — это -прирост к моменту времени, а `count()` по интервалу — сумма, которая набирается -к его концу; подпиши мы её началом, здоровые ряды разъехались бы ровно на один -столбец. Шаг панели при этом не мельче минуты: экспортёр опрашивают раз в -пятнадцать секунд, и на более мелком шаге ряд Kafka пошёл бы ступеньками там, -где ряд ClickHouse идёт гладко. - -Точка в точку ряды всё равно не совпадут, и ждать этого не надо: опрос -экспортёра не попадает на границы столбцов, поэтому на разгоне потока линия -Kafka идёт чуть выше. Читается устойчивый разрыв между линиями, а не разница в -один столбец. - -Панель смотрит на топик событий. У него приём непрерывный, и разрыв виден -сразу. Слепок заказов уезжает пачкой раз в модельные сутки, и вопрос к нему -другой — не «сходится ли поток», а «доехала ли выгрузка и вовремя ли». На него -отвечает своя панель, и модельный день она берёт из самого сообщения: в сырьё -он приезжает полем `snapshot_date`. - -## Что проверено - -Права роли `monitoring_reader` сверены 21 августа 2026 года по документации -ClickHouse через MCP Context7; разбор — в -[ADR 0007](../adr/0007-clickhouse-access.md), раздел «Что проверено». - -Сам состав проверен на живом стенде 21 августа 2026 года, собранном заново -после `make clean`. - -- Grafana видит плагин `grafana-clickhouse-datasource` 4.20.0 - (`/api/plugins?type=datasource`), оба подготовленных источника здоровы. -- Запрос источника ClickHouse к `system.one` через `clusterAllReplicas` вернул - 2 — с одной ноды видны обе. -- Prometheus видит ровно четыре цели, все со значением `up = 1`; запрос - `kafka_consumergroup_lag` вернул ряды по группам `clickstream_*`. -- `make smoke` 21/21, `make check-clickhouse` 10/10, `make check-services` 7/7. - -Дашборд «Данные» проверен на живом стенде в тот же день, `world_live` снят с -паузы. - -- Дашборд поднимается из каталога сам: файл положен, панели появились без - ручного импорта. Сохранение и удаление через API отвергнуты («Cannot save - provisioned dashboard», «provisioned dashboard cannot be deleted»). -- Все шесть панелей отвечают через `/api/ds/query` — и в окне часа по - умолчанию, и в окне на шесть часов, которое начинается раньше, чем поднялся - экспортёр. Пустых нет ни при идущем потоке, ни при остановленном. -- Брак: подсунутое в топик `hits` негодное сообщение легло в - `ods.event_errors` с классом `keyset_mismatch`; панель показала единицу и - долю 0,039 % в десятиминутном окне. Строка убрана мутациями из - `stg.hits_raw_rep` и `ods.event_errors_rep`, обе таблицы вернулись к нулю. -- Сходимость: на живом потоке за двадцать пять минут медиана расхождения между - рядами 3 %, худший столбец 11 % — на переломе потока, как и описано выше. - Отказы тоже по замеру: `increase` расходился сильнее, а накопленный итог - пропадал целиком, стоило окну начаться раньше экспортёра. -- Свежесть реагирует на остановленный поток и возвращается. Через пять минут - после конца модельного дня панель показала 305 с у событий и 288 с у - заказов; стоило пустить следующий день, события вернулись к секунде. - Свежесть заказов при этом растёт до конца дня и садится, когда доедет его - слепок, — так и устроен второй источник. diff --git a/docs/architecture/monitoring/README.md b/docs/architecture/monitoring/README.md new file mode 100644 index 0000000..278b103 --- /dev/null +++ b/docs/architecture/monitoring/README.md @@ -0,0 +1,116 @@ +# Мониторинг: из чего собран и что скребёт + +Набор описывает зону мониторинга: какие сервисы в неё входят, что собирает +Prometheus, какие источники данных подготовлены в Grafana, каким пользователем +она ходит в ClickHouse и куда кладутся дашборды. Устройство каждого дашборда — +отдельным файлом, указатели ниже. Зачем зоне именно такой состав и какие +дашборды на нём задуманы — [ADR 0002](../../adr/0002-monitoring-scope.md); +устройство доступа — [ADR 0007](../../adr/0007-clickhouse-access.md). + +**Что здесь есть и чего ещё нет.** Собран пол: свой образ Grafana с плагином +ClickHouse, два подготовленных источника данных, экспортёр метрик Kafka и цель +для него у Prometheus. Поверх пола стоит главный дашборд — «Данные»; «Кластер» +и «Запросы» приносят отдельные тикеты. Правил оповещения и серверного журнала +`system.text_log` тоже пока нет. + +## Состав + +| Сервис | Образ | Что делает | +|---|---|---| +| `prometheus` | `prom/prometheus:v3.13.2` | опрашивает цели раз в 15 секунд, порт стенда `29090` | +| `grafana` | `clickstream-grafana:local` | интерфейс мониторинга; собирается из `infra/grafana/`, порт стенда `23000` | +| `kafka-exporter` | `danielqsj/kafka-exporter:v1.9.0` | переводит состояние брокера в метрики Prometheus, порт `9308` | + +Плагин ClickHouse 4.20.0 входит в образ Grafana. Фоновая установка плагинов +при запуске отключена. + +## Что скребёт Prometheus + +| Цель | Задание | Метка `role` | Откуда метрики | +|---|---|---|---| +| `clickhouse-01:9363` | `clickhouse` | `server` | встроенный экспортёр ноды | +| `clickhouse-02:9363` | `clickhouse` | `server` | встроенный экспортёр ноды | +| `clickhouse-keeper:9363` | `clickhouse-keeper` | `keeper` | встроенный экспортёр keeper | +| `kafka-exporter:9308` | `kafka` | `exporter` | внешний экспортёр | + +Ровно эти четыре цели пересчитывает `check_prometheus_targets` в +`scripts/stand-smoke.sh` — и по значению `up`, и по списку адресов. Пятая цель +красит смоук; это и есть способ заметить, что состав пола поменяли молча. + +## Источники данных Grafana + +Оба источника подготовлены файлами в `infra/grafana/provisioning/datasources/` +и объявлены `editable: false`: править их через интерфейс нельзя, источник +истины — репозиторий. + +- `prometheus` — основной по умолчанию, ходит на `http://prometheus:9090`. +- `clickhouse` — плагин `grafana-clickhouse-datasource`, нативный протокол, + `clickhouse-01:9000`, пользователь `grafana`, пароль из `.env`. + +Источник ClickHouse смотрит на `clickhouse-01`. Системные таблицы обеих нод +панели читают через `clusterAllReplicas`, как принято в ADR 0002. + +## Доступ к ClickHouse + +Grafana ходит пользователем `grafana` с ролью `monitoring_reader`: читает слои, +таблицы базы `dic` и системные таблицы. `REMOTE` разрешает +`clusterAllReplicas`, `CLUSTER` — запросы `ON CLUSTER`. Решение о своей роли +записано в [ADR 0007](../../adr/0007-clickhouse-access.md). Пароль задаётся +переменной `CLICKHOUSE_GRAFANA_PASSWORD`. + +## Дашборды + +Каталог `infra/grafana/provisioning/dashboards/` смонтирован в контейнер и +объявлен провайдером в `provider.yml`: Grafana подхватывает оттуда файлы +дашбордов, удалять и править их через интерфейс запрещено. Новый дашборд — это +новый файл в каталоге и больше ничего: в `compose.yaml` заходить не нужно, ради +этого каталог и заведён заранее. + +Файлы каталога разбирает `make config-test`, рядом с файлами дагов и по тому же +доводу ([testing.md](../testing.md)). + +Собран один: + +- **«Данные»** (`data.json`) — с потоком всё в порядке: свежесть, поток, брак, + сходимость Kafka с ClickHouse, отставание чтения и дневной слепок заказов. + Устройство и разбор панелей — [data.md](data.md). + +## Что проверено + +Права роли `monitoring_reader` сверены 21 августа 2026 года по документации +ClickHouse через MCP Context7; разбор — в +[ADR 0007](../../adr/0007-clickhouse-access.md), раздел «Что проверено». + +Сам состав проверен на живом стенде 21 августа 2026 года, собранном заново +после `make clean`. + +- Grafana видит плагин `grafana-clickhouse-datasource` 4.20.0 + (`/api/plugins?type=datasource`), оба подготовленных источника здоровы. +- Запрос источника ClickHouse к `system.one` через `clusterAllReplicas` вернул + 2 — с одной ноды видны обе. +- Prometheus видит ровно четыре цели, все со значением `up = 1`; запрос + `kafka_consumergroup_lag` вернул ряды по группам `clickstream_*`. +- `make smoke` 21/21, `make check-clickhouse` 10/10, `make check-services` 7/7. + +Дашборд «Данные» проверен на живом стенде в тот же день, `world_live` снят с +паузы. + +- Дашборд поднимается из каталога сам: файл положен, панели появились без + ручного импорта. Сохранение и удаление через API отвергнуты («Cannot save + provisioned dashboard», «provisioned dashboard cannot be deleted»). +- Все шесть панелей отвечают через `/api/ds/query` — и в окне часа по + умолчанию, и в окне на шесть часов, которое начинается раньше, чем поднялся + экспортёр. Пустых нет ни при идущем потоке, ни при остановленном. +- Брак: подсунутое в топик `hits` негодное сообщение легло в + `ods.event_errors` с классом `keyset_mismatch`; панель показала единицу и + долю 0,039 % в десятиминутном окне. Строка убрана мутациями из + `stg.hits_raw_rep` и `ods.event_errors_rep`, обе таблицы вернулись к нулю. +- Сходимость: на живом потоке за двадцать пять минут медиана расхождения между + рядами 3 %, худший столбец 11 % — на переломе потока, как и описано в + [data.md](data.md). Отказы тоже по замеру: `increase` расходился сильнее, а + накопленный итог пропадал целиком, стоило окну начаться раньше экспортёра. +- Свежесть реагирует на остановленный поток и возвращается. Через пять минут + после конца модельного дня панель показала 305 с у событий и 288 с у + заказов; стоило пустить следующий день, события вернулись к секунде. + Свежесть заказов при этом растёт до конца дня и садится, когда доедет его + слепок, — так и устроен второй источник. diff --git a/docs/architecture/monitoring/data.md b/docs/architecture/monitoring/data.md new file mode 100644 index 0000000..f493713 --- /dev/null +++ b/docs/architecture/monitoring/data.md @@ -0,0 +1,94 @@ +# Дашборд «Данные» + +`infra/grafana/provisioning/dashboards/data.json` — шесть панелей на один +экран. Вопрос у экрана один: с потоком всё в порядке? Состав панелей и довод за +каждую — [ADR 0002](../../adr/0002-monitoring-scope.md). + +Порогов и цветовых вердиктов на панелях нет: на дашборд смотрят глазами, +красное и зелёное живёт в проверках и дагах DQ. + +| Панель | Откуда берёт | О чём отвечает | +|---|---|---| +| Свежесть | `ods.event_dist`, `ods.order_dist` | сколько прошло с последней доехавшей строки | +| Поток | `stg.hits_raw_dist`, `stg.orders_raw_dist` | сколько строк приезжает в слой сырья | +| Брак | те же и `ods.*_errors_dist` | сколько приехавшего не разобралось и какая это доля | +| Сходимость | экспортёр Kafka и `stg.hits_raw_dist` | произведённое против приземлившегося | +| Отставание | `kafka_consumergroup_lag` | сколько сообщений не прочитано | +| Дневной слепок | `stg.orders_raw_dist` | какой слепок доехал, когда и после какой паузы | + +## Почему слои у панелей разные + +Свежесть спрашивают у ODS. Это слой, который читают, и у заказов дорога до него +длиннее: сырьё привозит забор, а типизированную строку кладёт разбор. Встань +разбор — свежесть ODS это покажет, свежесть сырья нет. + +Читает свежесть физическую `_dist`, а не каноническое `ods.*_v`. Представление +прячет за собой `FINAL` и отвечает про текущее состояние сущностей, а вопрос +здесь про доставку: местом диагностики доставленных версий физическая таблица +названа там же, где заведено представление (`sql/ddl/30-ods-views.sql`). + +Поток и брак считаются по слою сырья. Сырьё записывает каждую доставку и ничего +не схлопывает, а `ReplacingMergeTree` в ODS схлопнет и повтор доставки события, +и все версии одного заказа. Считай мы поток по ODS — он занизился бы, и тем +сильнее, чем дольше живёт стенд. + +Доля брака берётся от приехавшего, а не от суммы «годные плюс брак»: брак не +отдельная куча, а часть сырья, которая не прошла разбор. + +Окно у панели брака — окно дашборда, и это не косметика. Сырьё живёт трое +суток, а брак — месяц: доля за всё время делила бы месяц брака на трое суток +приехавшего и однажды перевалила бы за сотню процентов. + +Панель дневного слепка, наоборот, окна не знает. Её вопрос про состояние, а не +про отрезок, и последние десять слепков она показывает всегда. + +Отдельного ряда «против вчерашнего» на панели потока нет, и это решение, а не +пропуск. Реальное «вчера» на стенде чаще всего приходится на время, когда +стенда ещё не было. А сдвинуть ряд на модельные сутки значит записать в JSON +дашборда ускорение мира — ровно ту пометку про тик, которую [ADR +0002](../../adr/0002-monitoring-scope.md) в дашборде держать не велит: поменяют +ускорение, и панель молча соврёт. Сравнение остаётся глазу: модельные сутки +укладываются в минуты реального времени, и соседние дни мира помещаются в одно +окно панели сами. + +## Чтецов Kafka панели не читают + +`stg.hits_raw_kafka` и `stg.orders_raw_kafka` — таблицы движка Kafka, а не +хранилище: запрос из панели у второго забрал бы слепок себе и сдвинул офсеты +(`kafka_commit_on_select`, см. `sql/ddl/10-stg-tables.sql`), а даг приёма +приехал бы к пустому топику. Приземлившееся панели считают по `stg.*_raw_dist`, +произведённое — по метрикам экспортёра. + +## Как считается сходимость + +Произведённое живёт в Kafka, приземлившееся — в ClickHouse, и со своей стороны +ни одна из них не видит другую. Поэтому панель смешанная: ряд «произведено в +Kafka» приходит из Prometheus, ряд «приземлилось в ClickHouse» — из ClickHouse. +Единицы общие — сообщений за интервал панели. Со стороны Kafka это разность +офсетов топика, «сейчас минус интервал назад», с суммой по обеим партициям; со +стороны ClickHouse — `count()` строк сырья по тому же интервалу. + +Два соседних способа отвергнуты, и оба по замеру на живом стенде. `increase` +растягивает приращение на всё окно и на минутном интервале промахивается на +проценты: здоровый стенд выглядел бы расходящимся. Накопленный итог от начала +окна точнее обоих приростов, но отсчитывать его надо от края окна — а на +свежем стенде окно начинается раньше, чем появился экспортёр, и ряд пропадает +целиком. + +Столбцы ClickHouse подписаны правым краем, а не левым. Точка Prometheus — это +прирост к моменту времени, а `count()` по интервалу — сумма, которая набирается +к его концу; подпиши мы её началом, здоровые ряды разъехались бы ровно на один +столбец. Шаг панели при этом не мельче минуты: экспортёр опрашивают раз в +пятнадцать секунд, и на более мелком шаге ряд Kafka пошёл бы ступеньками там, +где ряд ClickHouse идёт гладко. + +Точка в точку ряды всё равно не совпадут, и ждать этого не надо: опрос +экспортёра не попадает на границы столбцов, поэтому на разгоне потока линия +Kafka идёт чуть выше. Читается устойчивый разрыв между линиями, а не разница в +один столбец. + +Панель смотрит на топик событий. У него приём непрерывный, и разрыв виден +сразу. Слепок заказов уезжает пачкой раз в модельные сутки, и вопрос к нему +другой — не «сходится ли поток», а «доехала ли выгрузка и вовремя ли». На него +отвечает своя панель, и модельный день она берёт из самого сообщения: в сырьё +он приезжает полем `snapshot_date`.