Обзор — что делает экран
Решение проблем — это рабочий процесс карточек инцидентов для ролевой области «Сервисы». Зарегистрируйте любой сбой, ошибку или деградацию как отдельную карточку и проведите её по конвейеру статусов регистрация → расследование → причина установлена → решено → закрыто, фиксируя на каждом шаге ход разбора, причину и принятые меры. Экран одновременно служит журналом постмортемов и предупреждающих мер.
Все данные хранятся в одной таблице infr_incident, и этот экран работает только со строками, у которых area='service'. Экран Решение проблем безопасности использует ту же таблицу со значением area='security' — схема идентична, доски раздельные.
Каждая карточка содержит четыре поля причин и мер, построенные по образцу официального постмортем-отчёта:
| Поле | Значение | Пример |
|---|---|---|
direct_cause |
Непосредственный, видимый триггер сбоя | превышен лимит подключений mysql (Too many connections) |
root_cause |
Глубинная причина, породившая видимую | пятиминутный cron-скрипт не возвращал подключения → утечка → лимит исчерпан |
resolution |
Действие, восстановившее сервис во время инцидента | подключения сброшены, процесс перезапущен, лимит повышен для немедленного восстановления |
action_taken |
Постоянное исправление, исключающее повторение | выделенная учётная запись изолирована через MAX_USER_CONNECTIONS, скрипт исправлен, добавлено оповещение мониторинга |
Этот экран переименован из прежнего меню «SLA & Uptime» (пространство имён
sla→resolution). Показатель целевой доступности (uptime_target) сохранён.
Когда использовать
- Разбор после инцидента: после того как сервис упал и восстановился, зафиксируйте причину, исправление и профилактику как переиспользуемую ретроспективу.
- Отслеживание повторов: убедиться, повторяется ли одна и та же ошибка и была ли коренная причина действительно устранена.
- Управление MTTR и простоем: вести среднее время решения и суммарный простой как метрики и сопоставлять их с целевой доступностью.
- Обработка очереди автоприёма: когда внешние приложения отправляют ошибки через Pulse или репортер исключений, они попадают сюда как карточки с
source='pulse', которые человек сортирует и решает.
Устройство экрана
Полоса KPI
Показатели вверху рассчитываются по всем карточкам с area='service'.
| KPI | Как рассчитывается |
|---|---|
Всего (total) |
Количество сервисных карточек |
Активные (active) |
Сумма open + investigating + cause_identified |
Решённые (resolved) |
Сумма resolved + closed |
MTTR (mttr_min) |
Среднее значение (решение − возникновение) в минутах, только для карточек, у которых заполнены И occurred_at, И resolved_at |
Суммарный простой (downtime_min) |
Обычная сумма поля downtime_min по каждой карточке (в минутах) |
Целевая доступность (uptime_target) |
Параметр sla_uptime_target операционной политики (по умолчанию 99.9%) |
Чтобы MTTR был корректным, укажите в карточке время возникновения (
occurred_at) и позвольте переходу в статус «Решено» проставитьresolved_atавтоматически. Карточка без времени возникновения исключается из среднего MTTR.
Доска карточек
Карточки выводятся списком карточек/строк и сортируются на сервере (средствами PHP, чтобы не писать сырой SQL в контроллере) по такому приоритету:
- Ранг статуса:
open→investigating→cause_identified→resolved→closed - Ранг серьёзности:
crit→warn→info - Сначала самый новый id
Так наверх поднимаются активные, серьёзные и свежие карточки.
На каждой карточке видны значок источника (вручную / Pulse / оповещение / ведомство / карантин / повышено из обнаружения), серьёзность, статус, название проекта, время возникновения, простой и количество событий.
Модальное окно деталей
При открытии карточки слева показывается Отчёт (сводка · непосредственная причина · коренная причина · восстановление · предупреждающая мера), а справа — Хронология (смены статуса · заметки); кнопки переходов по конвейеру расположены сверху.
Как пользоваться
1) Зарегистрировать карточку
[Register case] → модальная форма. При создании карточка сохраняется с source='manual', area='service', status='open'; поле detected_at проставляется на сервере (now()), а в хронологию добавляется событие created.
Поля и ограничения проверки:
| Поле | Обязательное | Ограничение |
|---|---|---|
title |
✔ | не более 200 символов |
severity |
info/warn/crit — если пусто, по умолчанию warn (операционная политика, incident_default_severity) |
|
project_id |
должен существовать в infr_project |
|
service_id |
должен существовать в infr_service |
|
url |
не более 255 символов | |
occurred_at |
дата | |
summary |
не более 4000 символов | |
direct_cause / root_cause / resolution / action_taken |
не более 4000 символов каждое | |
downtime_min |
целое, ≥ 0 | |
impact |
не более 191 символа |
2) Переход статуса (конвейер)
В окне деталей нажатие кнопки следующего шага открывает диалог перехода по шагу. Каждый шаг поясняет, «что нужно сделать на этом шаге», и позволяет заполнить относящиеся к нему поля отчёта. Обновляются только те поля, которые вы отправили, поэтому вы можете дополнять причины, не меняя статус, либо расширять только отчёт.
| Шаг | Код | Что нужно сделать на этом шаге |
|---|---|---|
| Регистрация | open |
Вернуть карточку в приёмную очередь (до расследования) |
| Расследование | investigating |
Подтвердить симптомы, оценить масштаб влияния, написать сводку |
| Причина установлена | cause_identified |
Определить и зафиксировать непосредственную причину и её коренную (фоновую) причину |
| Решено | resolved |
Зафиксировать применённый способ восстановления и предупреждающую меру |
| Закрыто | closed |
Убедиться, что исправление и профилактика внедрены, и закрыть карточку |
Правила переходов:
- Переход в
resolvedпроставляетresolved_atзначениемnow(), если поле пустое (основа расчёта MTTR). - Переход в
closedпозволяет вручную задать время закрытия (closed_at) через тот же виджет flatpickr, что и для времени возникновения. Если вы укажете значение, используется оно; если оставите пустым (и оно ещё не задано), сервер подставитnow(). - Если статус действительно изменился (
from !== to), добавляется событиеstatus_change; если вы дополнительно введёте в диалоге заметку, добавится и событиеnote.
Даты отрисовываются через
toLocaleString, привязанный к активной локали интерфейса (window.__locale), поэтому месяц и время отображаются корректно даже в режиме EN.
3) Заметки для совместной работы
Добавление заметки в окне деталей добавляет в хронологию событие kind='note' (заметки объединены в infr_incident_event — отдельной таблицы заметок нет). Текст — не более 4000 символов.
4) Удаление
Удаление карточки удаляет инцидент вместе со всеми связанными строками infr_incident_event. Отменить это действие нельзя.
5) Автоприём (Pulse / репортер исключений)
Когда внешнее приложение на Laravel отправляет свои исключения в API приёма инцидентов (POST /api/v1/incidents), их обрабатывает IncidentIngestService и автоматически заносит на эту доску:
- Дедупликация по отпечатку: если такая же ошибка уже присутствует в открытом состоянии (
open/investigating/cause_identified), новая карточка не создаётся — увеличивается толькоoccurrence_count. Решённые и закрытые карточки заводятся заново как новые. - Новые карточки создаются с
source='pulse',status='open',entity_type='exception'(полеareaне задаётся → значение миграции по умолчаниюservice→ карточка видна на этой доске), и добавляется событиеcreated. - Заметки о повторах ограничены одной на 300 секунд, чтобы хронология не переполнялась.
- Поле
levelиз полезной нагрузки (error/warning/critical…) отображается в серьёзность (warn/crit…); если входящая серьёзность выше существующей, карточка эскалируется.
Ключи и код интеграции управляются в разделе Администрирование ▸ API-ключи.
Источники данных
| Таблица | Роль |
|---|---|
infr_incident |
Сама карточка. Этот экран запрашивает только area='service'. Миграция 000719 (+ 000723 поля приёма · 000731 area · 000732 расширение source) |
infr_incident_event |
Хронология (только добавление). kind = created/note/action/status_change/cause/resolution/alert_added. Использует только created_at (миграция 000720) |
infr_project |
Выпадающий список проектов · название проекта на карточке |
infr_service |
Выпадающий список сервисов |
infr_audit_log |
Аудиторский след создания/изменения/перехода/удаления |
Ключевые столбцы infr_incident: source, area, title, severity, status, project_id, service_id, url, occurred_at, detected_at, resolved_at, closed_at, summary, direct_cause, root_cause, resolution, action_taken, downtime_min, impact, fingerprint, occurrence_count, last_occurred_at, api_key_id, created_by, updated_by.
Значения по умолчанию берутся из операционной политики OpsPolicy::slaDefaults():
sla_uptime_target = 99.9 # целевая доступность по SLA (%)
incident_default_severity = warn # серьёзность по умолчанию при регистрации (info|warn|crit)
Маршруты:
GET /service/resolution index (доска)
GET /service/resolution/live live (обновление опросом JSON)
POST /service/resolution/save регистрация / изменение карточки
POST /service/resolution/transition переход статуса (+ отчёт по шагу / closed_at)
POST /service/resolution/note добавить заметку для совместной работы
POST /service/resolution/delete удалить карточку
Доступ
| Действие | Требуемый уровень |
|---|---|
Просмотр доски (index/live) |
Аутентифицированный пользователь (infr.auth, уровень ≥ 1) |
| Регистрация / изменение / переход / заметка / удаление | уровень ≥ 2 |
- demo (1) — только чтение. Любая попытка записи возвращает 403 (
resolution.err.forbidden, «нет прав — требуется уровень 2 или выше»). - staff (5) · admin (10) — полный набор операций CRUD и переходы.
Каждая запись (регистрация/изменение/переход/удаление) фиксируется в infr_audit_log как incident.create / incident.update / incident.transition / incident.delete с указанием исполнителя и статуса до и после. Модель уровней описана в разделе Уровни RBAC.
Устранение неполадок и вопросы
В. MTTR отображается пустым / без значения.
Чтобы карточка попала в среднее значение MTTR, у неё должны быть заполнены И время возникновения (occurred_at), И время решения (resolved_at). Проверьте, что вы указали время возникновения и что переход в статус «Решено» проставил resolved_at.
В. Суммарный простой показывает 0.
Показатель простоя — это обычная сумма поля downtime_min по каждой карточке. Простой (в минутах) нужно указать в карточке вручную; он не выводится автоматически из времени возникновения и решения.
В. Карточка из Pulse не появляется.
Принятые карточки имеют source='pulse' и оставляют area незаданным, поэтому берётся значение по умолчанию service и они появляются здесь. Если карточки всё же нет, проверьте: (1) действителен ли API-ключ и (2) не был ли тот же отпечаток объединён дедупликацией с уже открытой карточкой (увеличился только occurrence_count). Инциденты безопасности появляются в разделе Решение проблем безопасности (area='security'), а не на этой доске.
В. Можно ли задать время закрытия задним числом?
Да. Введите нужное время в поле времени закрытия (flatpickr) диалога перехода closed, и это значение будет сохранено. Оставьте поле пустым, чтобы использовалось текущее время сервера (now()).
В. Я хочу дополнить причины, не меняя статус. Диалог перехода обновляет только те поля, которые вы отправили. Переход в тот же самый статус с заполнением полей отчёта обновит отчёт без события смены статуса (либо отредактируйте карточку напрямую).
В. Можно ли восстановить удалённую карточку? Нет. Удаление убирает карточку и все её события хронологии и не может быть отменено. Само действие удаления фиксируется в журнале аудита.
Связанные разделы
- Решение проблем безопасности — зеркальная доска, использующая ту же таблицу
infr_incidentсо значениемarea='security'. - API приёма инцидентов · API-ключи — автоматически заносить ошибки внешних приложений как карточки с
source='pulse'. - Проекты — реестр проектов, к которым вы привязываете карточки.
- Обзор сервисов — оперативный контроль работающих сервисов (питает KPI нерешённых инцидентов).
- Наблюдаемость (Pulse/Horizon) — общие сведения о конвейере сбора исключений.
