[КРИТИЧНО] МЕРА слепа: за всю историю не отправлено ни одного уведомления — в GlitchTip нет ни правил, ни получателей #2673

Closed
opened 2026-08-05 19:11:40 +00:00 by bot-backend · 7 comments
Collaborator

Найдено системным поиском кода, который написан и ни разу не сработал (47 находок, сводка в #2674). Это — корневая, потому что объясняет, почему выжили остальные сорок шесть.

Ни одного уведомления. Никогда

Все алерты МЕРЫ упираются в GlitchTip. В проекте нет ни одного правила и ни одного получателя: таблица уведомлений пуста при том, что события копятся с 30 мая. То есть за всю историю продукта наружу не ушло ни одного сообщения о сбое.

Всё, что мы весь вечер чинили — «алерт стоял в недостижимой ветке», «уровень warning не долетает», — чинилось внутри системы, которая в любом случае никому не пишет.

Три способа не заметить аварию, каждый работает

Алерт срабатывает ровно один раз за аварию. Условие требует точной серии: три последних прогона неуспешны и четвёртый успешен. Как только серия длиннее, наступает тишина. Проверено на 14 сериях в проде: 31 подряд провальный прогон avito_full_load за месяц дал одно событие.

Зависшие прогоны не считаются. Статус zombie вырезан из обоих стрик-алертов — 30 подряд зависших прогонов listing_source_snapshot за месяц дали ноль событий.

Смерти процесса нет в принципе. У МЕРЫ нет ни одного монитора живости. Если контейнер скрапера встанет, не появится ни строки в базе, ни события — это состояние невыразимо имеющимися средствами. Мониторы заводили под ПТИЦУ, трейд-ин в них не добавляли ни разу.

Чем это обошлось — вот эти четыре пункта не гипотетические

СберИндекс протух 1 июня. Монитор устаревания честно сработал 9 раз. Все девять — уровнем warning, а событиями становятся только записи уровня error. Ноль событий. Данные внешнего бенчмарка цен стоят два месяца.

Оценка Циана — седьмой источник эстиматора — умерла 29 июня. Куки протухли, с тех пор ни одной новой строки 37 дней. Ни алерта, ни следа в статусах: оценки просто лишились источника, и никто не узнал.

house_imv_backfill не умеет падать. 31 прогон подряд: сохранено ноль, ошибок около 35 из 50 попыток — и все помечены «успешно». 34 дня ежедневных прогонов без единой сохранённой оценки.

domclick_detail_backfill: за всю жизнь обогащено 0 объявлений из 494 попыток, все 30 прогонов отчитались «успешно». Алерт нулевого результата для него недостижим по построению.

Что делать, по порядку

  1. Завести в GlitchTip правило и получателя. Без этого остальные пункты бессмысленны — мы будем чинить доставку в никуда. Это шаг на владельце: нужен адрес или канал, куда писать.
  2. Монитор живости: отдельный сигнал «скрапер жив», который гаснет сам, если процесс встал. Сейчас единственный способ узнать — заметить, что данные не обновляются.
  3. Повторное напоминание вместо разового: сломанный источник должен напоминать о себе с разрежением, а не замолкать навсегда (#2670).
  4. Вернуть zombie в стрик-алерты — зависший прогон это авария, а не нейтральное состояние.
  5. Сводка «что сейчас сломано» вместо потока «что сломалось только что». Она отвечает на вопрос, который реально задают, и не зависит от того, поймали ли мы момент поломки.

Почему это важнее, чем кажется

Сегодня четыре разных дефекта нашлись случайно — при разборе не связанных с ними задач. Каждый жил месяцами. Общее у них не техническое: система не умеет сказать, что ей плохо, поэтому единственный способ узнать о поломке — наткнуться на неё.

P0 #2574 («скраперы отрабатывают вхолостую, данные не обновляются 5–18 дней») — это не отдельная авария. Это то, как выглядит месяц работы системы без обратной связи.

Связано: #2674, #2670, #2625, #2574, #2658.

Найдено системным поиском кода, который написан и ни разу не сработал (47 находок, сводка в #2674). Это — корневая, потому что объясняет, почему выжили остальные сорок шесть. ## Ни одного уведомления. Никогда Все алерты МЕРЫ упираются в GlitchTip. В проекте **нет ни одного правила и ни одного получателя**: таблица уведомлений пуста при том, что события копятся с 30 мая. То есть за всю историю продукта наружу не ушло **ни одного** сообщения о сбое. Всё, что мы весь вечер чинили — «алерт стоял в недостижимой ветке», «уровень warning не долетает», — чинилось внутри системы, которая в любом случае никому не пишет. ## Три способа не заметить аварию, каждый работает **Алерт срабатывает ровно один раз за аварию.** Условие требует точной серии: три последних прогона неуспешны **и** четвёртый успешен. Как только серия длиннее, наступает тишина. Проверено на 14 сериях в проде: 31 подряд провальный прогон `avito_full_load` за месяц дал **одно** событие. **Зависшие прогоны не считаются.** Статус `zombie` вырезан из обоих стрик-алертов — 30 подряд зависших прогонов `listing_source_snapshot` за месяц дали **ноль** событий. **Смерти процесса нет в принципе.** У МЕРЫ нет ни одного монитора живости. Если контейнер скрапера встанет, не появится ни строки в базе, ни события — это состояние **невыразимо** имеющимися средствами. Мониторы заводили под ПТИЦУ, трейд-ин в них не добавляли ни разу. ## Чем это обошлось — вот эти четыре пункта не гипотетические **СберИндекс протух 1 июня.** Монитор устаревания честно сработал **9 раз**. Все девять — уровнем `warning`, а событиями становятся только записи уровня `error`. Ноль событий. Данные внешнего бенчмарка цен стоят два месяца. **Оценка Циана — седьмой источник эстиматора — умерла 29 июня.** Куки протухли, с тех пор **ни одной новой строки 37 дней**. Ни алерта, ни следа в статусах: оценки просто лишились источника, и никто не узнал. **`house_imv_backfill` не умеет падать.** 31 прогон подряд: сохранено ноль, ошибок около 35 из 50 попыток — и все помечены «успешно». 34 дня ежедневных прогонов без единой сохранённой оценки. **`domclick_detail_backfill`:** за всю жизнь обогащено **0 объявлений из 494 попыток**, все 30 прогонов отчитались «успешно». Алерт нулевого результата для него недостижим по построению. ## Что делать, по порядку 1. **Завести в GlitchTip правило и получателя.** Без этого остальные пункты бессмысленны — мы будем чинить доставку в никуда. Это шаг на владельце: нужен адрес или канал, куда писать. 2. **Монитор живости**: отдельный сигнал «скрапер жив», который гаснет сам, если процесс встал. Сейчас единственный способ узнать — заметить, что данные не обновляются. 3. **Повторное напоминание** вместо разового: сломанный источник должен напоминать о себе с разрежением, а не замолкать навсегда (#2670). 4. **Вернуть `zombie` в стрик-алерты** — зависший прогон это авария, а не нейтральное состояние. 5. **Сводка «что сейчас сломано»** вместо потока «что сломалось только что». Она отвечает на вопрос, который реально задают, и не зависит от того, поймали ли мы момент поломки. ## Почему это важнее, чем кажется Сегодня четыре разных дефекта нашлись **случайно** — при разборе не связанных с ними задач. Каждый жил месяцами. Общее у них не техническое: **система не умеет сказать, что ей плохо**, поэтому единственный способ узнать о поломке — наткнуться на неё. P0 #2574 («скраперы отрабатывают вхолостую, данные не обновляются 5–18 дней») — это не отдельная авария. Это то, как выглядит месяц работы системы без обратной связи. Связано: #2674, #2670, #2625, #2574, #2658.
Author
Collaborator

Проверено в самой базе GlitchTip: события приходят, некому доставить

Ключевая развилка была неясна — «уведомлений нет, потому что нечего слать» или «есть что слать, но некуда». Ответ однозначный.

проект     групп ошибок   последняя
backend           3 661   2026-08-06 06:25
trade-in          2 861   2026-08-06 06:28
frontend              7   2026-06-04 05:14
правил оповещения (alerts_projectalert):   0
получателей (alerts_alertrecipient):        0
отправленных уведомлений (alerts_notification): 0

2 861 группа ошибок по trade-in накопилась и ни одна не привела ни к одному уведомлению. За последние сутки — 77 живых групп, 909 событий. Данные шли всё это время; отсутствовал только адресат.

Что именно лежало в этой непрочитанной почте

Верх списка по trade-in:

событий что последнее
10 571 TimeoutError 03.08
1 794 ReadTimeout 26.06
1 635 TimeoutError 03.07
921 503 от tradein-browser:3000/fetch-json 01.08
559 500 от tradein-browser:3000/… 06.08 04:12
389 dadata: HTTP 403 — auth/secret rejected 12.07
161 avito page=1 sidecar error budget exhausted (status=503) 03.08
123 dadata: HTTP 403 — услуга CLEAN выключена на аккаунте 06.08 06:28
73 tg client: getUpdates — HTTP 502 после 4 попыток 05.08

Две строки здесь особенно неприятны.

Первая — 500/503 от нашего браузерного сайдкара. Это ровно тот отказ, из-за которого домовая оценка Авито мертва 34 дня (#2698), и ровно тот, который заставил прочитать статус «забанен» буквально и замедлить сбор вдвое по ложному основанию (#2686). Система знала и называла причину — с точным URL — с самого начала.

Вторая — DaData. Стандартизация адресов сломана с 30 мая, и в двух последовательных формах:

30.05 → 12.07   389 событий   HTTP 403 — auth/secret rejected. Проверь DADATA_API_TOKEN/SECRET.
12.07 → 06.08   123 события   HTTP 403 — услуга CLEAN (Стандартизация) ВЫКЛЮЧЕНА на аккаунте
                              (токен валиден, НЕ отклонён)

Смена формулировки 12 июля означает, что кто-то тогда обновил токен — и остановился на полпути: токен стал валидным, а услуга на аккаунте так и осталась выключенной. Ошибка сама называет, что делать, дословно, по-русски, и повторяется 25-й день.

Вывод, который меняет формулировку задачи

Это не «мониторинг не настроен». Это исправно работающая диагностика, пишущая в ящик, который никто не открывал ни разу. Продукт всё это время точно знал, что у него сломано, и умел сказать это словами.

Отсюда следует и приоритет: любой сторож, который мы чиним в эпике #2674 (#2695, #2703, #2625, #2681), после починки будет срабатывать в пустоту, пока не задан получатель. Сначала адресат, потом сторожа — иначе мы улучшаем качество писем, которые не отправляются.

Что нужно

  1. Завести получателя и хотя бы одно правило на проекты trade-in и backend. Это действие владельца, вынесено в сводку #2704.
  2. Разобрать накопленное — верх списка выше уже указывает на три открытые задачи (#2698, #2686, и DaData, которую я добавляю в #2704 отдельным пунктом).
  3. Правило должно быть таким, чтобы 10 571 TimeoutError не утопил остальное. Иначе первый же настроенный адресат отпишется, и мы вернёмся в исходную точку другим путём.
## Проверено в самой базе GlitchTip: события приходят, некому доставить Ключевая развилка была неясна — «уведомлений нет, потому что нечего слать» или «есть что слать, но некуда». Ответ однозначный. ``` проект групп ошибок последняя backend 3 661 2026-08-06 06:25 trade-in 2 861 2026-08-06 06:28 frontend 7 2026-06-04 05:14 ``` ``` правил оповещения (alerts_projectalert): 0 получателей (alerts_alertrecipient): 0 отправленных уведомлений (alerts_notification): 0 ``` **2 861 группа ошибок по trade-in накопилась и ни одна не привела ни к одному уведомлению.** За последние сутки — 77 живых групп, 909 событий. Данные шли всё это время; отсутствовал только адресат. ## Что именно лежало в этой непрочитанной почте Верх списка по trade-in: | событий | что | последнее | |---:|---|---| | 10 571 | `TimeoutError` | 03.08 | | 1 794 | `ReadTimeout` | 26.06 | | 1 635 | `TimeoutError` | 03.07 | | 921 | `503` от `tradein-browser:3000/fetch-json` | 01.08 | | 559 | `500` от `tradein-browser:3000/…` | **06.08 04:12** | | 389 | `dadata: HTTP 403 — auth/secret rejected` | 12.07 | | 161 | `avito page=1 sidecar error budget exhausted (status=503)` | 03.08 | | 123 | `dadata: HTTP 403 — услуга CLEAN выключена на аккаунте` | **06.08 06:28** | | 73 | `tg client: getUpdates — HTTP 502 после 4 попыток` | 05.08 | Две строки здесь особенно неприятны. **Первая — 500/503 от нашего браузерного сайдкара.** Это ровно тот отказ, из-за которого домовая оценка Авито мертва 34 дня (#2698), и ровно тот, который заставил прочитать статус «забанен» буквально и замедлить сбор вдвое по ложному основанию (#2686). Система знала и называла причину — с точным URL — с самого начала. **Вторая — DaData.** Стандартизация адресов сломана **с 30 мая**, и в двух последовательных формах: ``` 30.05 → 12.07 389 событий HTTP 403 — auth/secret rejected. Проверь DADATA_API_TOKEN/SECRET. 12.07 → 06.08 123 события HTTP 403 — услуга CLEAN (Стандартизация) ВЫКЛЮЧЕНА на аккаунте (токен валиден, НЕ отклонён) ``` Смена формулировки 12 июля означает, что кто-то тогда обновил токен — и остановился на полпути: токен стал валидным, а услуга на аккаунте так и осталась выключенной. Ошибка **сама называет, что делать**, дословно, по-русски, и повторяется 25-й день. ## Вывод, который меняет формулировку задачи Это не «мониторинг не настроен». Это **исправно работающая диагностика, пишущая в ящик, который никто не открывал ни разу**. Продукт всё это время точно знал, что у него сломано, и умел сказать это словами. Отсюда следует и приоритет: любой сторож, который мы чиним в эпике #2674 (#2695, #2703, #2625, #2681), после починки будет срабатывать **в пустоту**, пока не задан получатель. Сначала адресат, потом сторожа — иначе мы улучшаем качество писем, которые не отправляются. ## Что нужно 1. **Завести получателя и хотя бы одно правило** на проекты `trade-in` и `backend`. Это действие владельца, вынесено в сводку #2704. 2. Разобрать накопленное — верх списка выше уже указывает на три открытые задачи (#2698, #2686, и DaData, которую я добавляю в #2704 отдельным пунктом). 3. Правило должно быть таким, чтобы 10 571 `TimeoutError` не утопил остальное. Иначе первый же настроенный адресат отпишется, и мы вернёмся в исходную точку другим путём.
Author
Collaborator

Сверка чисел 2026-08-07 11:5x MSK: ничего не изменилось, цифры в задаче можно освежить

Задача владельцу — не закрываю. Проверил, не устарели ли числа. Замер прямо в базе GlitchTip:

правил оповещения (alerts_projectalert):          0
получателей (alerts_alertrecipient):              0
отправленных уведомлений (alerts_notification):   0

Все три по-прежнему нули. За сутки со времени вашего замера не отправлено ни одного
уведомления
— как и за все предыдущие 69 дней.

Группы ошибок подросли:

проект было (06.08 06:2x) стало (07.08 08:1x) последняя
backend 3 661 3 707 2026-08-07 08:19
trade-in 2 861 2 882 2026-08-07 08:15
frontend 7 7 2026-06-04

За последние сутки: backend — 81 живая группа / 886 событий, trade-in — 21 группа / 331 событие.

Верх списка по trade-in не изменился по составу; из живого стоит отметить одну строку:

141 события   dadata: HTTP 403 — услуга CLEAN (Стандартизация) выключена на аккаунте
              (токен валиден, НЕ отклонён)          последнее — 2026-08-07 08:15

Было 123, стало 141 — ошибка, которая дословно называет, что сделать, повторяется 26-й день.

Оговорка про правило («10 571 TimeoutError не должен утопить остальное») в силе: эта группа
по-прежнему крупнейшая, хотя её последнее событие — 03.08.

Отдельно по приоритету, который вы вывели: за сутки в эпике починены ещё два сторожа
(#2670 — лестница напоминаний вместо разового; #2703 — «не измерено» больше не читается как ноль).
Оба, как и предыдущие шесть, будут срабатывать в пустоту, пока получателя нет.

## Сверка чисел 2026-08-07 11:5x MSK: ничего не изменилось, цифры в задаче можно освежить Задача владельцу — не закрываю. Проверил, не устарели ли числа. Замер прямо в базе GlitchTip: ``` правил оповещения (alerts_projectalert): 0 получателей (alerts_alertrecipient): 0 отправленных уведомлений (alerts_notification): 0 ``` Все три по-прежнему нули. **За сутки со времени вашего замера не отправлено ни одного уведомления** — как и за все предыдущие 69 дней. Группы ошибок подросли: | проект | было (06.08 06:2x) | стало (07.08 08:1x) | последняя | |---|---:|---:|---| | backend | 3 661 | **3 707** | 2026-08-07 08:19 | | trade-in | 2 861 | **2 882** | 2026-08-07 08:15 | | frontend | 7 | 7 | 2026-06-04 | За последние сутки: backend — 81 живая группа / 886 событий, trade-in — 21 группа / 331 событие. Верх списка по trade-in не изменился по составу; из живого стоит отметить одну строку: ``` 141 события dadata: HTTP 403 — услуга CLEAN (Стандартизация) выключена на аккаунте (токен валиден, НЕ отклонён) последнее — 2026-08-07 08:15 ``` Было 123, стало 141 — ошибка, которая **дословно называет, что сделать**, повторяется 26-й день. Оговорка про правило («10 571 `TimeoutError` не должен утопить остальное») в силе: эта группа по-прежнему крупнейшая, хотя её последнее событие — 03.08. Отдельно по приоритету, который вы вывели: за сутки в эпике починены ещё два сторожа (#2670 — лестница напоминаний вместо разового; #2703 — «не измерено» больше не читается как ноль). Оба, как и предыдущие шесть, будут срабатывать в пустоту, пока получателя нет.
lekss361 added the
observability
priority/p0
scope/devops
tradein
labels 2026-08-16 10:25:13 +00:00
Owner

Разбор 16.08.2026: задача НЕ закрыта, хотя часть работы сделана

Проверял на закрытие — не подтвердилось. Фиксирую, что именно сделано и что осталось, чтобы следующий читатель не принял одно за другое.

Сделано (смержено 15–16.08):

  • #2914 — почтовые переменные GlitchTip вынесены в окружение, и, что важнее, добавлены на glitchtip-worker: письма шлёт celery, а у него этих переменных не было вовсе, поэтому настройка одного web-сервиса не дала бы ни одного письма;
  • #2915 — приёмник вебхуков GlitchTip → Telegram-тема, glitchtip-worker добавлен в общую сеть (проверено живьём: worker → tradein-backend доступен);
  • мониторы переведены с Ping на GET с ожидаемым статусом — раньше проверка засчитывала успех за сам факт соединения, поэтому 401 и 405 читались как «сервис жив»; добавлен монитор публичной страницы «Меры».

Не сделано — и без этого предмет задачи жив. Замер на проде сегодня:

alerts_projectalert    → 0 строк
alerts_alertrecipient  → 0 строк
EMAIL_URL (worker)     → consolemail://

То есть правил оповещения не заведено ни одного, а почтовый транспорт по-прежнему печатает письмо в консоль. «Мера» сейчас так же не может отправить ни одного уведомления, как и в день заведения задачи — смерженные PR построили проводку, но не включили её.

Что осталось, по шагам:

  1. Положить в файл окружения на сервере реальный адрес SMTP: схема обязательно smtp+ssl:// для порта 465 — интуитивно похожая smtps:// включает STARTTLS, с которым Beget рвёт соединение.
  2. Создать в интерфейсе GlitchTip правило оповещения — по проекту, не по организации. У правила есть флаг uptime, он направляет через тех же получателей и падения мониторов.
  3. Добавить получателя типа webhook с адресом моста — тогда алерты пойдут в Telegram независимо от почты.

Пока не сделан хотя бы один из трёх шагов, задача открыта по существу, а не по формальности.

## Разбор 16.08.2026: задача НЕ закрыта, хотя часть работы сделана Проверял на закрытие — не подтвердилось. Фиксирую, что именно сделано и что осталось, чтобы следующий читатель не принял одно за другое. **Сделано (смержено 15–16.08):** - #2914 — почтовые переменные GlitchTip вынесены в окружение, и, что важнее, добавлены на `glitchtip-worker`: письма шлёт celery, а у него этих переменных не было вовсе, поэтому настройка одного web-сервиса не дала бы ни одного письма; - #2915 — приёмник вебхуков GlitchTip → Telegram-тема, `glitchtip-worker` добавлен в общую сеть (проверено живьём: `worker → tradein-backend` доступен); - мониторы переведены с `Ping` на `GET` с ожидаемым статусом — раньше проверка засчитывала успех за сам факт соединения, поэтому 401 и 405 читались как «сервис жив»; добавлен монитор публичной страницы «Меры». **Не сделано — и без этого предмет задачи жив.** Замер на проде сегодня: ``` alerts_projectalert → 0 строк alerts_alertrecipient → 0 строк EMAIL_URL (worker) → consolemail:// ``` То есть правил оповещения не заведено ни одного, а почтовый транспорт по-прежнему печатает письмо в консоль. **«Мера» сейчас так же не может отправить ни одного уведомления, как и в день заведения задачи** — смерженные PR построили проводку, но не включили её. **Что осталось, по шагам:** 1. Положить в файл окружения на сервере реальный адрес SMTP: схема обязательно `smtp+ssl://` для порта 465 — интуитивно похожая `smtps://` включает STARTTLS, с которым Beget рвёт соединение. 2. Создать в интерфейсе GlitchTip правило оповещения — по проекту, не по организации. У правила есть флаг `uptime`, он направляет через тех же получателей и падения мониторов. 3. Добавить получателя типа webhook с адресом моста — тогда алерты пойдут в Telegram независимо от почты. Пока не сделан хотя бы один из трёх шагов, задача открыта по существу, а не по формальности.
Author
Collaborator

Перепроверено 19.08 на живом GlitchTip: состояние не изменилось

alerts_projectalert        строк = 0     правил уведомления нет
alerts_alertrecipient      строк = 0     получателей нет
alerts_notification        строк = 0     ни одного отправленного
alerts_notification_issues строк = 0

При этом событий накопилось:

issue всего            7 596
период            16.05 .. 19.08   (95 суток)

То есть за девяносто пять суток внутрь записано семь с половиной тысяч issue и наружу не ушло ни одного сообщения. Задача открыта, и её формулировка по-прежнему точна.

Это шире, чем МЕРА

Заголовок говорит «МЕРА слепа», но в топе за последние семь суток — сигналы обоих продуктов:

NspdLiteWafError: HTTP 403 (WAF/rate-limit)                         14
scheduler: 4 источников не собирают дольше 3× своего такта          13
Data freshness alert (overall=failed): 3 failed, 1 stale — kn ...    7
scrape_freshness_check: Data freshness alert (overall=failed) ...    7
basic_auth 401 — GET /wp-admin/install.php (сканеры)                 9 + 6

Строки про freshness — это ПТИЦА. Сегодня я отдельно проверял её монитор свежести: он работает исправно, срабатывает ровно в 09:00 МСК, честно считает возраст (kn [failed, 51.58d]) и пишет в GlitchTip каждый день. И каждый день это никому не уходит.

То есть сторож не сломан — сломан канал за ним. Ровно тот случай, когда «защита промолчала» неотличимо от «защиты нет», и отличить их можно только заглянув в базу уведомлений.

Что могу и чего не могу

Правило и получателя завожу не я: адрес доставки (почта, вебхук, телеграм-канал) — решение владельца, а создание учётной записи или настройка внешнего сервиса за него выходит за рамки того, что мне уместно делать.

Что могу и уже сделал — измерить масштаб и назвать конкретные потери: из тринадцати событий «источники не собирают дольше 3× такта» за неделю не увидел никто.

Отдельно: две трети шума в топе — сканеры

basic_auth 401 — GET /wp-admin/install.php — это боты, стучащиеся в чужой CMS-путь. Пятнадцать событий за неделю из общего топа. Когда получатель появится, такие события стоит отсечь на входе, иначе первое же уведомление придёт про сканер, а не про сбор данных, и канал обесценится за неделю.

### Перепроверено 19.08 на живом GlitchTip: состояние не изменилось ``` alerts_projectalert строк = 0 правил уведомления нет alerts_alertrecipient строк = 0 получателей нет alerts_notification строк = 0 ни одного отправленного alerts_notification_issues строк = 0 ``` При этом событий накопилось: ``` issue всего 7 596 период 16.05 .. 19.08 (95 суток) ``` То есть за девяносто пять суток внутрь записано семь с половиной тысяч issue и наружу не ушло **ни одного** сообщения. Задача открыта, и её формулировка по-прежнему точна. ### Это шире, чем МЕРА Заголовок говорит «МЕРА слепа», но в топе за последние семь суток — сигналы обоих продуктов: ``` NspdLiteWafError: HTTP 403 (WAF/rate-limit) 14 scheduler: 4 источников не собирают дольше 3× своего такта 13 Data freshness alert (overall=failed): 3 failed, 1 stale — kn ... 7 scrape_freshness_check: Data freshness alert (overall=failed) ... 7 basic_auth 401 — GET /wp-admin/install.php (сканеры) 9 + 6 ``` Строки про freshness — это ПТИЦА. Сегодня я отдельно проверял её монитор свежести: он работает исправно, срабатывает ровно в 09:00 МСК, честно считает возраст (`kn [failed, 51.58d]`) и пишет в GlitchTip **каждый день**. И каждый день это никому не уходит. То есть сторож не сломан — сломан канал за ним. Ровно тот случай, когда «защита промолчала» неотличимо от «защиты нет», и отличить их можно только заглянув в базу уведомлений. ### Что могу и чего не могу Правило и получателя завожу не я: адрес доставки (почта, вебхук, телеграм-канал) — решение владельца, а создание учётной записи или настройка внешнего сервиса за него выходит за рамки того, что мне уместно делать. Что могу и уже сделал — измерить масштаб и назвать конкретные потери: из тринадцати событий «источники не собирают дольше 3× такта» за неделю не увидел никто. ### Отдельно: две трети шума в топе — сканеры `basic_auth 401 — GET /wp-admin/install.php` — это боты, стучащиеся в чужой CMS-путь. Пятнадцать событий за неделю из общего топа. Когда получатель появится, такие события стоит отсечь на входе, иначе первое же уведомление придёт про сканер, а не про сбор данных, и канал обесценится за неделю.
Author
Collaborator

Цена этой конфигурации на 20.08.2026

Issue до сих пор верен — проверил заново:

alerts_projectalert   0     правил
alerts_alertrecipient 0     адресатов
alerts_notification   0     отправлено за всю историю

Ниже — что именно за эту тишину не было услышано.

Сторож работает и сигналит ежедневно

События в GlitchTip за последние двое суток:

20.08  Data freshness alert (overall=failed): 3 failed, 1 stale — kn [failed, …
20.08  6 scraper sources are stale (no successful run for more than 3× their …
20.08  deals freshness: max(deal_date)=2026-01-01 — новый квартал просрочен
19.08  Data freshness alert (overall=failed): 3 failed, 1 stale — kn [failed, …

То есть механизм не сломан. Сообщения формируются и складываются в GlitchTip. Их просто некому отдать.

Что показывает сторож прямо сейчас

compute_freshness изнутри gendesign-backend-1, 20.08:

источник статус критичный возраст, дней последний успех
kn failed да 52.7 2026-06-28
kn_flats failed да 52.7 2026-06-28
objective ok да 0.5 2026-08-19
nspd stale нет 24.3 2026-07-27
nspd_geo stale нет 46.9 2026-07-04
cadastre failed нет 61.8 2026-06-19
gisogd_permits ok нет 9.2 2026-08-11

overall = failed.

Пять источников из семи протухли или упали, два из них помечены критичными. Самый старый молчит 62 дня.

Из них разобраны отдельно: НСПД — #2956 (с 27.07, WAF 403 на IP), каталог DOM.РФ — #2443 (с 19.05, страница «Доступ заблокирован» с капчей). kn/kn_flats (DOM.РФ KN-API, с 28.06) и cadastre (с 19.06) отдельного разбора пока не имеют — по датам они попадают в то же окно, что и остальные отказы DOM.РФ, но утверждать общую причину без проверки не буду.

Что здесь важно

Каждый из этих отказов по отдельности мог бы быть замечен за сутки: сторож их видит и называет по именам. Ни один не был замечен за два месяца — потому что последнее звено цепочки отсутствует.

Правило и адресата не создаю сам: это настройка внешнего сервиса и решение владельца. Но теперь у решения есть цена в цифрах, а не только формулировка «уведомления не настроены».

## Цена этой конфигурации на 20.08.2026 Issue до сих пор верен — проверил заново: ``` alerts_projectalert 0 правил alerts_alertrecipient 0 адресатов alerts_notification 0 отправлено за всю историю ``` Ниже — что именно за эту тишину не было услышано. ## Сторож работает и сигналит ежедневно События в GlitchTip за последние двое суток: ``` 20.08 Data freshness alert (overall=failed): 3 failed, 1 stale — kn [failed, … 20.08 6 scraper sources are stale (no successful run for more than 3× their … 20.08 deals freshness: max(deal_date)=2026-01-01 — новый квартал просрочен 19.08 Data freshness alert (overall=failed): 3 failed, 1 stale — kn [failed, … ``` То есть механизм не сломан. Сообщения формируются и складываются в GlitchTip. Их просто некому отдать. ## Что показывает сторож прямо сейчас `compute_freshness` изнутри `gendesign-backend-1`, 20.08: | источник | статус | критичный | возраст, дней | последний успех | |---|---|---|---|---| | **kn** | **failed** | **да** | **52.7** | 2026-06-28 | | **kn_flats** | **failed** | **да** | **52.7** | 2026-06-28 | | objective | ok | да | 0.5 | 2026-08-19 | | nspd | stale | нет | 24.3 | 2026-07-27 | | nspd_geo | stale | нет | 46.9 | 2026-07-04 | | **cadastre** | **failed** | нет | **61.8** | 2026-06-19 | | gisogd_permits | ok | нет | 9.2 | 2026-08-11 | `overall = failed`. **Пять источников из семи** протухли или упали, два из них помечены критичными. Самый старый молчит 62 дня. Из них разобраны отдельно: НСПД — #2956 (с 27.07, WAF 403 на IP), каталог DOM.РФ — #2443 (с 19.05, страница «Доступ заблокирован» с капчей). `kn`/`kn_flats` (DOM.РФ KN-API, с 28.06) и `cadastre` (с 19.06) отдельного разбора пока не имеют — по датам они попадают в то же окно, что и остальные отказы DOM.РФ, но утверждать общую причину без проверки не буду. ## Что здесь важно Каждый из этих отказов по отдельности мог бы быть замечен за сутки: сторож их видит и называет по именам. Ни один не был замечен за два месяца — потому что последнее звено цепочки отсутствует. Правило и адресата не создаю сам: это настройка внешнего сервиса и решение владельца. Но теперь у решения есть цена в цифрах, а не только формулировка «уведомления не настроены».
Author
Collaborator

Канал уведомлений работает сквозным путём — проверено доставкой, а не конфигом

Владелец дописал TELEGRAM_ALERTS_CHAT_ID / TELEGRAM_ALERTS_TOPIC_ID в рантайм-конфиг, tradein-backend пересоздан.

Что проверено, в порядке возрастания длины пути

проба путь результат
1 localhost внутри tradein-backend, пустое тело HTTP 200, в теме сообщение «неизвестный формат payload, пересылаю как есть» — сработала fallback-ветка форматирования
2 localhost внутри tradein-backend, issue-подобный payload HTTP 200, в теме разобранное сообщение с проектом, заголовком, текстом и ссылкой
3 из glitchtip-worker по НАСТОЯЩЕМУ URL получателя HTTP 200

Третья проба — важная. Модульный докстринг glitchtip.py описывает связность по имени контейнера в общей докер-сети, а после переезда GlitchTip остался на Beget, а tradein-backend уехал на Poincare — по имени он оттуда не резолвится. Получатели, однако, прописаны публичным URL (https://gendsgn.ru/trade-in/api/v1/trade-in/ops/glitchtip-webhook?secret=…), то есть путь идёт через Caddy по сети и переезд переживает. Проба выполнена изнутри того самого контейнера, который шлёт алерты, и вернула 200.

Итого в логе tradein-backend: 3 доставки, статус 200, ни одной ошибки Telegram (502 при отказе Telegram — отдельная ветка, не сработала ни разу).

Состояние правил

alert 1  backend    · окно 5 мин · порог 1 · uptime вкл · получатель webhook
alert 2  frontend   · окно 5 мин · порог 1 · uptime вкл · получатель webhook
alert 3  Trade-In   · окно 5 мин · порог 1 · uptime вкл · получатель webhook

Тестовые сообщения из проб удалять из темы не стал — это ваша тема, решайте сами.

Побочная находка, которую я же и создал — вынесена в отдельный issue

Секрет едет query-параметром (иначе никак: GlitchTip не добавляет заголовков — см. докстринг модуля), и uvicorn пишет полный URL в access-log, а лог уезжает в Loki. Проверил запросом к Loki: строки с secret=<значение> лежат там незамаскированными — скруббер из #3115 ловит только ://user:pass@, query-параметр под его выражение не подходит.

До сегодня этих строк в логах не было (вебхук отвечал 503 и до логирования URL дело не доходило), так что засветка новая и пока состоит из 3 строк — моих проб. Но она будет копиться на каждом настоящем алерте. Детали и варианты починки — в новом issue.

Закрываю: механизм проверен доставкой на всю длину пути.

## Канал уведомлений работает сквозным путём — проверено доставкой, а не конфигом Владелец дописал `TELEGRAM_ALERTS_CHAT_ID` / `TELEGRAM_ALERTS_TOPIC_ID` в рантайм-конфиг, `tradein-backend` пересоздан. ### Что проверено, в порядке возрастания длины пути | проба | путь | результат | |---|---|---| | 1 | `localhost` внутри `tradein-backend`, пустое тело | HTTP 200, в теме сообщение «неизвестный формат payload, пересылаю как есть» — сработала fallback-ветка форматирования | | 2 | `localhost` внутри `tradein-backend`, issue-подобный payload | HTTP 200, в теме разобранное сообщение с проектом, заголовком, текстом и ссылкой | | 3 | **из `glitchtip-worker` по НАСТОЯЩЕМУ URL получателя** | HTTP 200 | Третья проба — важная. Модульный докстринг `glitchtip.py` описывает связность по имени контейнера в общей докер-сети, а после переезда **GlitchTip остался на Beget, а `tradein-backend` уехал на Poincare** — по имени он оттуда не резолвится. Получатели, однако, прописаны публичным URL (`https://gendsgn.ru/trade-in/api/v1/trade-in/ops/glitchtip-webhook?secret=…`), то есть путь идёт через Caddy по сети и переезд переживает. Проба выполнена изнутри того самого контейнера, который шлёт алерты, и вернула 200. Итого в логе `tradein-backend`: **3 доставки, статус 200, ни одной ошибки Telegram** (502 при отказе Telegram — отдельная ветка, не сработала ни разу). ### Состояние правил ``` alert 1 backend · окно 5 мин · порог 1 · uptime вкл · получатель webhook alert 2 frontend · окно 5 мин · порог 1 · uptime вкл · получатель webhook alert 3 Trade-In · окно 5 мин · порог 1 · uptime вкл · получатель webhook ``` Тестовые сообщения из проб удалять из темы не стал — это ваша тема, решайте сами. ### Побочная находка, которую я же и создал — вынесена в отдельный issue Секрет едет **query-параметром** (иначе никак: GlitchTip не добавляет заголовков — см. докстринг модуля), и uvicorn пишет полный URL в access-log, а лог уезжает в Loki. Проверил запросом к Loki: строки с `secret=<значение>` лежат там **незамаскированными** — скруббер из #3115 ловит только `://user:pass@`, query-параметр под его выражение не подходит. До сегодня этих строк в логах не было (вебхук отвечал 503 и до логирования URL дело не доходило), так что засветка новая и пока состоит из 3 строк — моих проб. Но она будет копиться на каждом настоящем алерте. Детали и варианты починки — в новом issue. Закрываю: механизм проверен доставкой на всю длину пути.
Author
Collaborator

Закрываю: канал проверен от вебхука до Telegram

Что было. Эндпоинт /api/v1/trade-in/ops/glitchtip-webhook отвечал 503 (_alerts_configured() → false): в рантайм-конфиге backend'а на Poincare не было TELEGRAM_ALERTS_CHAT_ID / TELEGRAM_ALERTS_TOPIC_ID. Все реальные отправки GlitchTip 27.08 — 15:06, 15:37, 16:15, 16:48 UTC — получили 503 и не дошли никуда.

Что сделано. Переменные добавлены в рантайм-конфиг, backend пересоздан (16:50 UTC).

Чем доказано.

  1. Эндпоинт отвечает 200 вместо 503.
  2. Три пробы доехали в Telegram-топик, две из них подтверждены владельцем глазами.
  3. Одна проба отправлена изнутри glitchtip-worker по реальному публичному URL — это существенно: после переезда GlitchTip живёт на Beget, а backend на Poincare, и разрешение по имени контейнера больше не работает. Проверять «из соседнего контейнера» после миграции значило бы проверять не тот путь.

Чего доказательства НЕ покрывают. Органического события GlitchTip после фикса не случилось (наблюдал 55 минут — тишина). Ждать его — значит ждать инцидента на проде; сквозная проба по боевому URL закрывает тот же путь.

Остаточные дыры вынесены отдельно, здесь не чинятся:

  • #3157is_sent=True ставится безусловно, так что «доставлено» по этой колонке считать нельзя; наблюдаемость нужна на нашей стороне;
  • #3159 — почта GlitchTip = consolemail:// (заглушка), uptime-мониторы шлют в никуда;
  • #3155 — второй, независимый канал (Prometheus → Alertmanager) не работал по своей причине; чинится сейчас.
## Закрываю: канал проверен от вебхука до Telegram **Что было.** Эндпоинт `/api/v1/trade-in/ops/glitchtip-webhook` отвечал 503 (`_alerts_configured()` → false): в рантайм-конфиге backend'а на Poincare не было `TELEGRAM_ALERTS_CHAT_ID` / `TELEGRAM_ALERTS_TOPIC_ID`. Все реальные отправки GlitchTip 27.08 — 15:06, 15:37, 16:15, 16:48 UTC — получили 503 и не дошли никуда. **Что сделано.** Переменные добавлены в рантайм-конфиг, backend пересоздан (16:50 UTC). **Чем доказано.** 1. Эндпоинт отвечает 200 вместо 503. 2. Три пробы доехали в Telegram-топик, две из них подтверждены владельцем глазами. 3. Одна проба отправлена **изнутри `glitchtip-worker` по реальному публичному URL** — это существенно: после переезда GlitchTip живёт на Beget, а backend на Poincare, и разрешение по имени контейнера больше не работает. Проверять «из соседнего контейнера» после миграции значило бы проверять не тот путь. **Чего доказательства НЕ покрывают.** Органического события GlitchTip после фикса не случилось (наблюдал 55 минут — тишина). Ждать его — значит ждать инцидента на проде; сквозная проба по боевому URL закрывает тот же путь. **Остаточные дыры вынесены отдельно, здесь не чинятся:** - #3157 — `is_sent=True` ставится безусловно, так что «доставлено» по этой колонке считать нельзя; наблюдаемость нужна на нашей стороне; - #3159 — почта GlitchTip = `consolemail://` (заглушка), uptime-мониторы шлют в никуда; - #3155 — второй, независимый канал (Prometheus → Alertmanager) не работал по своей причине; чинится сейчас.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2673
No description provided.