中文翻译暂不可用,显示俄语原文。
Реализовать автоматический postmortem
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Реализовать автоматический postmortem
1. Цель задачи
Разработать скрипт (или микросервис), который по временному окну инцидента автоматически собирает логи, метрики и traces из production-инфраструктуры и генерирует черновик postmortem-отчёта в заданном формате. Автоматизация должна сократить время сбора данных для анализа с часов до ~5 минут.
Ключевой результат Скрипт, который за 5 минут формирует markdown-файл postmortem с заполненными полями: таймлайн, ключевые метрики «до/во время/после», фрагменты логов, аномалии в traces и гипотезу о root cause.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Время начала и конца инцидента (ISO 8601) | Из системы оповещений (PagerDuty, Opsgenie) — симулировать |
| Логи (сервиса RAG / API) | Loki / Elasticsearch — симулировать файлами |
| Метрики (latency, error rate, request count) | Prometheus / VictoriaMetrics — симулировать CSV |
| Traces (span-id, duration, status) | Jaeger / Tempo — симулировать JSON |
| Описание сервисов и их зависимостей | README проекта — можно выдумать |
| Baseline метрик за 24 часа до инцидента | Те же источники, сдвиг окна |
Если нет реального инструмента — симулируем:
- Создай Python-скрипт
simulate_incident_data.py, который генерирует каталогincident_data/с файлами:logs_sample.log— 200–500 строк формата[Вики/Recency|timestamp [level] [Вики/Service|service [Вики/Request ID|trace_id message- metrics_sample.csv — 4 столбца: timestamp, service, metric_name, value (например,
request_duration_seconds, error_rate) - traces_sample.json — список span-объектов с полями trace_id, span_id, parent_span_id, start_time, duration, status_code, service_name
- Задай в коде
INCIDENT_START = "2025-03-15T10:30:00Z",INCIDENT_END = "2025-03-15T10:45:00Z"— окно инцидента 15 минут. - В logs_sample.log выдели 10–15% записей с
level=ERRORвнутри окна, сделай всплеск метрики error_rate с 1% до 15%.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык | Python 3.10+ | Логика агрегации и генерации отчёта |
| Парсинг логов | re, pandas | Чтение симулированных логов |
| Получение метрик | requests к Prometheus API (или чтение CSV) | Query range |
| Traces | JSON / Pandas | Фильтрация по времени, аномалии |
| Шаблонизатор | Jinja2 | Рендеринг markdown-отчёта |
| Файловая система | pathlib | Сохранение результатов |
| Тестирование | pytest | Проверка корректности скрипта |
4. Этапы выполнения
Этап 1: Подготовка окружения и данных (30 минут)
Действия
- Установи Python-зависимости: pip install pandas jinja2 requests pytest
- Скачай или создай шаблон postmortem (
postmortem_template.j2):# POSTMORTEM: {{ incident_id }} - Дата инцидента {{ start_time }} — {{ end_time }} - Длительность {{ duration_min }} мин - [[Вики/severity|Severity]] {{ severity }} ## Таймлайн {% for event in timeline %} - {{ event.time }}: {{ event.description }} {% endfor %} ## Метрики (до/во время/после) {% for metric in metrics %} - {{ metric.name }}: {{ metric.before }} → {{ metric.during }} → {{ metric.after }} {% endfor %} ## Логи (топ ERROR за окно) {% for log in top_logs %} - `{{ log }}` {% endfor %} ## Traces: аномально медленные {% for trace in slow_traces %} - trace_id={{ trace.trace_id }}, duration={{ trace.duration }}ms, service={{ trace.service }} {% endfor %} ## Гипотеза root cause {{ hypothesis }} - Создай файл
simulate_incident_data.py(описан в разделе 2) и запусти его, чтобы получить набор тестовых данных.
Ожидаемый результат этапа Каталог incident_data/ с тремя файлами, готовый шаблон postmortem_template.j2.
Этап 2: Разработка модуля сбора логов (1 час)
Действия
- Напиши функцию
load_incident_params(incident_id, start_time, end_time, data_dir), которая читает из командной строки или файла параметры окна. - Реализуй
parse_logs(filepath, start, end):- Используй pandas.read_csv с разделителем
|(симулируем структурированные логи) илиreдля парсинга. - Фильтруй строки по времени.
- Подсчитай количество ERROR-сообщений, сгруппируй по сервису.
- Извлеки топ-10 ERROR-строк с наибольшей частотой.
- Используй pandas.read_csv с разделителем
- Реализуй get_metrics(filepath, metric_name, start, end, baseline_hours=24):
- Прочитай CSV метрик.
- Вычисли среднее значение метрики за три окна:
[start - 1h, start),[start, end],[end, end + 1h). - Верни словарь
{metric_name: {before: val, during: val, after: val}}.
- Реализуй
parse_traces(filepath, start, end):
Ожидаемый результат этапа Три функции в collectors.py, которые возвращают структуры данных.
Этап 3: Разработка модуля генерации гипотезы (45 минут)
Действия
- Создай
hypothesis_engine.py:- Простая эвристика: если error_rate выросла одновременно с ростом
request_latencyи есть ERROR-логи в том же сервисе — гипотеза: «Проблема в сервисе {service}, возможно, из-за увеличения времени ответа downstream». - Если latency выросла, но error_rate не изменилась — «Возможно, медленный upstream-запрос или изменение конфигурации».
- Если error_rate выросла, а latency нет — «Ошибки не связаны с производительностью, возможно, логическая ошибка или некорректные данные».
- Простая эвристика: если error_rate выросла одновременно с ростом
- Функция generate_hypothesis(metrics, logs, traces) возвращает строку с гипотезой.
Ожидаемый результат этапа Функция, которая на основе собранных данных возвращает текст гипотезы.
Этап 4: Интеграция и генерация отчёта (1 час)
Действия
- Создай главный скрипт
auto_postmortem.py:import sys, json from collectors import parse_logs, get_metrics, parse_traces from hypothesis_engine import generate_hypothesis from jinja2 import Environment, FileSystemLoader def main(incident_id, start, end, data_dir): # 1. Загрузить данные logs = parse_logs(f"{data_dir}/logs_sample.log", start, end) metrics = {} for m in ["error_rate", "request_duration_seconds"]: metrics[m] = get_metrics(f"{data_dir}/metrics_sample.csv", m, start, end) traces = parse_traces(f"{data_dir}/traces_sample.json", start, end) hypothesis = generate_hypothesis(metrics, logs, traces) # 2. Подготовить контекст для шаблона duration_min = (end - start).seconds // 60 context = { "incident_id": incident_id, "start_time": start.isoformat(), "end_time": end.isoformat(), "duration_min": duration_min, "severity": "P1" if metrics["error_rate"]["during"] > 10 else "P2", "timeline": [ {"time": start.isoformat(), "description": "Начало роста error_rate"}, {"time": end.isoformat(), "description": "Интервал инцидента завершён"} ], "metrics": [{"name": k, **v} for k, v in metrics.items()], "top_logs": logs["top_errors"][:5], "slow_traces": traces[:5], "hypothesis": hypothesis } # 3. Рендеринг env = Environment(loader=FileSystemLoader(".")) template = env.get_template("postmortem_template.j2") report = template.render(**context) # 4. Сохранить with open(f"output/pm_{incident_id}.md", "w") as f: f.write(report) print("Report saved.") - Добавь парсинг аргументов командной строки:
--id,--start,--end,--data-dir. - Протестируй на симулированных данных:
python auto_postmortem.py --id INC-20250315 \ --start 2025-03-15T10:30:00Z \ --end 2025-03-15T10:45:00Z \ --data-dir incident_data - Убедись, что
output/pm_INC-20250315.mdсоздан и содержит осмысленные данные.
Ожидаемый результат этапа Рабочий скрипт и заполненный отчёт.
Этап 5: Оценка качества и доработка (30 минут)
Действия
- Напиши
test_collectors.pyс pytest:- Тест на корректность фильтрации логов по времени.
- Тест на расчёт средних метрик.
- Тест на обнаружение аномальных trace.
- Замерь время выполнения всего скрипта на симулированных данных (должно быть <5 мин, обычно <1 с).
- Добавь в отчёт секцию «Аномалии в коде» (если есть доступ к git log) — опционально, симулируй коммит перед инцидентом.
Ожидаемый результат этапа Набор тестов (100% прохождение), метрика времени выполнения.
5. Критерии приемки (Definition of Done)
- Скрипт
auto_postmortem.pyпринимает параметры через CLI (incident_id, start, end, data_dir). - Генерируется markdown-файл с именем
pm_{incident_id}.mdв папкеoutput/. - Отчёт содержит все обязательные разделы: таймлайн, метрики (до/во время/после), топ-5 ERROR-логов, аномальные traces, гипотеза.
- Для метрик
error_rateиrequest_duration_secondsкорректно вычислены средние за три окна. - Гипотеза осмысленно связана с входными данными (не пустая строка и не случайный текст).
- Все симулированные данные создаются однократным запуском
simulate_incident_data.py. - Время выполнения на симулированных данных не превышает 5 минут (обычно <1 сек).
-
pytestпроходит минимум 3 теста.
6. Ожидаемый результат
-
Основной артефакт каталог
auto_postmortem/с файлами:auto_postmortem.py— главный скриптcollectors.py— функции сбораhypothesis_engine.py— генерация гипотезыpostmortem_template.j2— шаблон Jinja2simulate_incident_data.py— генератор тестовых данныхincident_data/— сгенерированные данныеoutput/pm_*.md— итоговый отчётtest_collectors.py— тесты
-
Содержание отчёта автоматически заполненный postmortem, готовый к редактированию человеком.
-
Опционально интеграция с реальными источниками (Prometheus API, Loki API) — можно расширить.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Форматы логов отличаются от симулированных | Использовать json.loads для парсинга JSON-логов; добавить конфигурацию с регулярными выражениями |
| Временные метки в разных часовых поясах | Конвертировать все в UTC с помощью pytz или zoneinfo |
| Много аномальных traces (шум) | Использовать процентиль 99.9 вместо порога ×3 |
| Не хватает данных для гипотезы | Вернуть шаблонную строку «Требуется ручной анализ — данных недостаточно» |
| Скрипт работает дольше 5 минут на реальных данных | Оптимизировать запросы (batch-чтение, параллелизм) или ограничить объём пре-агрегированными данными |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Этап 1: Подготовка окружения и данных | 30 мин |
| Этап 2: Модуль сбора логов | 1 ч |
| Этап 3: Модуль генерации гипотезы | 45 мин |
| Этап 4: Интеграция и генерация отчёта | 1 ч |
| Этап 5: Оценка качества и доработка | 30 мин |
| Итого | ~3 ч 45 мин |
Примечание: Если инженер впервые работает с Jinja2 или Prometheus-запросами, добавьте 1 час на ознакомление.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 102 | Метрики SLA/SLO/SLI |
| 115 | Управление инцидентами |
| 137 | Архитектура observability (logs, metrics, traces) |
| 189 | Анализ root cause (RCA) в распределённых системах |
| 210 | Jinja2 шаблоны для отчётов |
| 244 | Prometheus query language (PromQL) basics |
| 267 | OpenTelemetry и сбор traces |
| 315 | Git blame и интеграция с инцидентами |
| 418 | Автоматическая классификация severity |
| 501 | Тестирование скриптов на симулированных данных |
10. Чек-лист самопроверки
- Я проверил, что скрипт работает на симулированных данных без ошибок.
- Я убедился, что сгенерированный отчёт имеет все требуемые разделы.
- Я написал минимум 3 теста (pytest) для ключевых функций.
- Я замерил время выполнения и оно <5 минут.
- Я проверил, что гипотеза не пустая и логична (например, «Проблема в сервисе auth, так как error_rate выросла с 1% до 15%»).