All checks were successful
CI Trade-In / changes (pull_request) Successful in 17s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 21s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 3m53s
CI Trade-In / backend-tests (pull_request) Successful in 6m56s
CI / backend-tests (pull_request) Successful in 8m25s
#1971, два невыполненных пункта DoD. 1. Уведомления не было. Заявка с результата оценки только ложилась в trade_in_leads (docstring прямо называл уведомление «вне scope»). На проде 17.09: 4 заявки, notified_at пуст у всех, последняя 12.07. Теперь после ответа клиенту фоновая задача шлёт сообщение в support-топик тем же ботом, что и веб-чат поддержки, и при успехе ставит notified_at. Отказ Telegram не меняет ни ответ (200), ни сохранённый лид — только лог. Телефона в сообщении нет: копию в Telegram не стирает механизм удаления ПДн, поэтому туда идут id заявки, пользователь и id оценки. 2. Доли заявок от оценок не было нигде. Панель на продуктовом дашборде: лиды за 7 суток / успешные оценки за 7 суток (знаменатель — только outcome=ok: форма заявки показывается только при посчитанной оценке). Выражение проверено на боевом Prometheus 17.09: 0 / 91.008 = 0. Closes #1971 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
184 lines
10 KiB
JSON
184 lines
10 KiB
JSON
{
|
||
"uid": "gendesign-product",
|
||
"title": "Продуктовые метрики",
|
||
"description": "Числа бизнеса, а не процесса: сколько людей реально что-то сделали в «Мере» и «Птице» (#3471). Источник — те же счётчики Prometheus, что и на дашборде «Приложения», только считают не HTTP-статусы, а продуктовые события (оценка, лид, отчёт, вход, обращение в поддержку). Часовое окно нарочно грубое: при текущем трафике (сотни событий в сутки) минутные всплески — шум, а не сигнал.",
|
||
"tags": ["gendesign", "product"],
|
||
"timezone": "browser",
|
||
"editable": false,
|
||
"schemaVersion": 39,
|
||
"refresh": "5m",
|
||
"time": { "from": "now-24h", "to": "now" },
|
||
"panels": [
|
||
{ "type": "row", "title": "Мера — воронка продукта", "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 } },
|
||
|
||
{
|
||
"type": "timeseries",
|
||
"title": "Оценок в час, по исходу",
|
||
"description": "insufficient_data — не ошибка: аналогов рядом с адресом не нашлось, расчёт прошёл штатно. Тревожиться стоит, если эта линия начинает расти быстрее ok — значит покрытие рынка проседает, а не то, что сломался расчёт.",
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 1 },
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"expr": "sum by (outcome) (increase(mera_estimates_total[1h]))",
|
||
"legendFormat": "{{outcome}}"
|
||
}
|
||
],
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "short",
|
||
"min": 0,
|
||
"custom": { "fillOpacity": 8, "stacking": { "mode": "none" }, "showPoints": "never", "lineWidth": 2 }
|
||
},
|
||
"overrides": [
|
||
{ "matcher": { "id": "byName", "options": "insufficient_data" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "orange" } } ] },
|
||
{ "matcher": { "id": "byName", "options": "ok" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "green" } } ] }
|
||
]
|
||
}
|
||
},
|
||
|
||
{
|
||
"type": "timeseries",
|
||
"title": "Подсказки адреса в час, нашёлся ли результат",
|
||
"description": "found=no — человек напечатал адрес, а автокомплит ничего не предложил: либо адреса нет в базе, либо он вне зоны покрытия. Устойчивый рост этой линии — повод расширять покрытие, а не баг одного запроса.",
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 1 },
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"expr": "sum by (found) (increase(mera_address_suggestions_total[1h]))",
|
||
"legendFormat": "найден: {{found}}"
|
||
}
|
||
],
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "short",
|
||
"min": 0,
|
||
"custom": { "fillOpacity": 8, "stacking": { "mode": "none" }, "showPoints": "never", "lineWidth": 2 }
|
||
},
|
||
"overrides": [
|
||
{ "matcher": { "id": "byRegexp", "options": ".*no.*" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "orange" } } ] }
|
||
]
|
||
}
|
||
},
|
||
|
||
{
|
||
"type": "timeseries",
|
||
"title": "Лиды и скачанные отчёты в час",
|
||
"description": "Лид — заявка с телефоном после оценки, отчёт — скачанный PDF по оценке. Оба редкие: сверяйте с недельным окном (кнопка времени вверху), часовой провал сам по себе ни о чём не говорит при таком трафике.",
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 9 },
|
||
"targets": [
|
||
{ "refId": "A", "expr": "increase(mera_leads_total[1h])", "legendFormat": "лиды" },
|
||
{ "refId": "B", "expr": "increase(mera_reports_exported_total[1h])", "legendFormat": "отчёты" }
|
||
],
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "short",
|
||
"min": 0,
|
||
"custom": { "fillOpacity": 8, "stacking": { "mode": "none" }, "showPoints": "never", "lineWidth": 2 }
|
||
},
|
||
"overrides": []
|
||
}
|
||
},
|
||
|
||
{
|
||
"type": "timeseries",
|
||
"title": "Входы в час, по исходу",
|
||
"description": "Устойчивый рост failed при ровном success — либо перебор паролей, либо сломался клиент (истёкшая сессия, старый билд фронта). При подозрении на перебор смотрите заодно панель «Отказы авторизации и лимитера» на дашборде «Приложения» — там 401/429 по HTTP.",
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 9 },
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"expr": "sum by (result) (increase(mera_logins_total[1h]))",
|
||
"legendFormat": "{{result}}"
|
||
}
|
||
],
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "short",
|
||
"min": 0,
|
||
"custom": { "fillOpacity": 8, "stacking": { "mode": "none" }, "showPoints": "never", "lineWidth": 2 }
|
||
},
|
||
"overrides": [
|
||
{ "matcher": { "id": "byName", "options": "failed" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "red" } } ] },
|
||
{ "matcher": { "id": "byName", "options": "success" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "green" } } ] }
|
||
]
|
||
}
|
||
},
|
||
|
||
{
|
||
"type": "timeseries",
|
||
"title": "Обращения в поддержку в час, по каналу",
|
||
"description": "anon — обращения с экрана входа, без логина (типично «не могу войти»), web — уже залогиненные пользователи. Всплеск anon без роста web — обычно означает баг именно в форме/процессе входа, а не общий рост нагрузки на поддержку.",
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 17 },
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"expr": "sum by (channel) (increase(mera_support_messages_total[1h]))",
|
||
"legendFormat": "{{channel}}"
|
||
}
|
||
],
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "short",
|
||
"min": 0,
|
||
"custom": { "fillOpacity": 8, "stacking": { "mode": "none" }, "showPoints": "never", "lineWidth": 2 }
|
||
},
|
||
"overrides": [
|
||
{ "matcher": { "id": "byName", "options": "anon" }, "properties": [ { "id": "color", "value": { "mode": "fixed", "fixedColor": "orange" } } ] }
|
||
]
|
||
}
|
||
},
|
||
|
||
{
|
||
"type": "timeseries",
|
||
"title": "Конверсия оценка → заявка, скользящие 7 суток",
|
||
"description": "Доля успешных оценок (outcome=ok), после которых оставили заявку (#1971): лиды за 7 суток / оценки ok за 7 суток. Знаменатель — только ok, потому что форма заявки показывается только при посчитанной оценке (insufficient_data формы не видит). Счёт по событиям, а не по людям: одна заявка после трёх пересчётов того же адреса даёт 33 %. Пусто вместо 0 % — за 7 суток не было ни одной успешной оценки.",
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 17 },
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"expr": "sum(increase(mera_leads_total[7d])) / sum(increase(mera_estimates_total{outcome=\"ok\"}[7d]))",
|
||
"legendFormat": "заявки / оценки"
|
||
}
|
||
],
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "percentunit",
|
||
"min": 0,
|
||
"custom": { "fillOpacity": 8, "stacking": { "mode": "none" }, "showPoints": "never", "lineWidth": 2 }
|
||
},
|
||
"overrides": []
|
||
}
|
||
},
|
||
|
||
{ "type": "row", "title": "Птица — экспорт отчётов", "gridPos": { "h": 1, "w": 24, "x": 0, "y": 25 } },
|
||
|
||
{
|
||
"type": "timeseries",
|
||
"title": "Экспортов отчётов по участку в час, по формату",
|
||
"description": "Формат — то, что реально скачали: md/json/docx/pptx/pdf/tg-сводка §22-форсайта плюс best_layouts_pdf (ТЗ на проектирование). Провал всех форматов разом при живом трафике на дашборде «Приложения» значит, что сломан сам экспорт, а не рендер одного конкретного формата.",
|
||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||
"gridPos": { "h": 8, "w": 24, "x": 0, "y": 26 },
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"expr": "sum by (format) (increase(sitefinder_reports_exported_total[1h]))",
|
||
"legendFormat": "{{format}}"
|
||
}
|
||
],
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "short",
|
||
"min": 0,
|
||
"custom": { "fillOpacity": 8, "stacking": { "mode": "none" }, "showPoints": "never", "lineWidth": 2 }
|
||
},
|
||
"overrides": []
|
||
}
|
||
}
|
||
]
|
||
}
|