# Service Observability Documentation Writing

> Проектирование, создание и ревью аналитической Markdown-документации наблюдаемости сервиса. Сейчас использовать для согласования logging-контракта: общих полей и формата, значимых логируемых ситуаций API и отдельных worker-процессов, уровней, идентификаторов, ошибок, безопасности и контроля объёма. Не применять для реализации logging, выбора системы сбора, метрик или трассировки.

- Skill: `nemagu/service-observability-documentation-writing` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add nemagu/service-observability-documentation-writing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nemagu/service-observability-documentation-writing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: Nemagu (https://skillmd.com/u/nemagu)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/nemagu/service-observability-documentation-writing

---


# Документация наблюдаемости сервиса

Документировать целевой logging-контракт всего сервиса и дополнения его отдельных
процессов. Не считать текущие вызовы logging требованиями и не проектировать
реализацию адаптеров.

## Порядок работы

1. Прочитать `$hexagonal-service-documentation-writing` и получить от него
   корневой слот, структуру документации и позицию в `SUMMARY.md`.
2. Спросить, существует ли принятый набор полей, пример записи или соглашение
   экосистемы. Использовать их как требования только после подтверждения.
3. Если готовой схемы нет, позволить пользователю описать любой удобный вход:
   сценарии поиска и расследования, процессы, важные операции и отказы,
   идентификаторы либо желаемые поля.
4. Если пользователь не знает, с чего начать, изучить разрешённые им сведения о
   составе сервиса и предложить стартовый набор полей и ситуаций с объяснением,
   какой поиск они обеспечивают.
5. Согласовать общий контракт сервиса. Не утверждать предложенные поля за
   пользователя.
6. Для каждого отдельно запускаемого процесса согласовать дополнительные поля и
   значимые логируемые ситуации.
7. Показать итоговые таблицы до записи документов. Непринятые варианты оставить
   предложениями или открытыми вопросами.
8. Создать документы и дополнить только назначенный фрагмент `SUMMARY.md`.
9. Проверить отсутствие дублирования, разрешимость ссылок и достижимость каждого
   документа из навигации.

## Структура документов

По умолчанию создавать поддерево:

```text
observability/
├── README.md
└── logging/
    ├── README.md
    ├── common.md
    └── <process>.md
```

- `observability/README.md` — индекс согласованных сигналов наблюдаемости.
- `logging/README.md` — назначение logging-контракта, состав процессов и
  навигация.
- `logging/common.md` — подтверждённые общие поля, формат, уровни, правила
  ошибок, идентификаторов, безопасности и объёма.
- `logging/<process>.md` — только дополнительные поля и ситуации конкретного
  фактически существующего процесса.

Технические имена файлов процессов писать в `snake_case`, например
`http_api.md`, `nats_consumer.md` и `nats_publisher.md`.

Не создавать единый `logging.md`. Не создавать страницы отсутствующих процессов
и будущих сигналов. Каждый содержательный документ завершать разделом
`## Открытые вопросы` по правилам общего скила.

Фрагмент навигации строить так:

```markdown
- [Наблюдаемость](./observability/README.md)
  - [Логирование](./observability/logging/README.md)
    - [Общий контракт](./observability/logging/common.md)
    - [Название процесса](./observability/logging/<process>.md)
```

Размещать раздел наблюдаемости в позиции, заданной общим скилом; не переставлять
соседние корневые разделы.

## Общий контракт

### Стабильные обозначения

Использовать схему
`<контекст>.observability.<сигнал>.<процесс или профиль>.<ситуация>`.
Сигнал, процесс и ситуация являются отдельными смысловыми сегментами; не
склеивать процесс с ситуацией и не пропускать профиль. Одинаковый logging-контракт
или ситуация во всех документах имеет одно обозначение независимо от имени файла
и человекочитаемого сообщения.

Не задавать универсальный список обязательных полей внутри скила. Согласовывать
их с пользователем для сервиса, учитывая поля, уже добавляемые runtime,
контейнерной платформой или системой сбора. Для каждого поля фиксировать:

|Поле|Обязательность|Семантика|Источник контекста|Применимость|Ограничения|
|:---|:---|:---|:---|:---|:---|

Отсутствующее неприменимое поле не требовать заполнять `null`, если пользователь
не выбрал фиксированную схему. Одинаковое понятие называть одинаково во всех
процессах.

Для обязательности использовать единый закрытый словарь: `Обязательное`,
`Условное`, `Необязательное`. Условие присутствия условного поля указывать явно.

Спрашивать о существующей конвенции имён. При её отсутствии предлагать
`snake_case`. Отделять стабильное машинное имя ситуации от человекочитаемого
сообщения; переименование согласованного имени считать изменением контракта.
Для машинных имён событий и значений классифицирующих полей (`operation`,
`outcome`, тип процесса и аналогичные внутренние обозначения) по умолчанию
использовать слова с разделителем `_`, а не `-`. Не распространять это правило
на внешние значения: URL, subject, topic, header и заданные чужим контрактом
идентификаторы сохранять без переименования.

Для каждого ограниченного классифицирующего поля перечислять все допустимые
значения. Перечисления профиля логирования принадлежат logging-контракту: они
могут соответствовать значениям публичного application DTO один к одному, но не
зависят от типа или перечисления прикладного слоя. Одинаковые типы worker-ов в
экосистеме используют одинаковые имена полей и значения перечислений.

## Формат и вывод

- Согласовывать формат с пользователем; по умолчанию предлагать structured JSON.
- Допускать человекочитаемый renderer для локальной разработки при сохранении
  тех же логических полей.
- Описывать семантику независимо от logging-библиотеки.
- Для контейнеров по умолчанию предлагать `stdout`/`stderr`.
- Файлы, прямую отправку и другой transport добавлять только по требованию.
- Не проектировать сбор, доставку, ротацию и хранение вне заданной области.

## Уровни

Использовать единую семантику:

- `DEBUG` — внутренние диагностические и высокочастотные шаги.
- `INFO` — штатный lifecycle и подтверждённый значимый успешный результат.
- `WARNING` — контролируемая деградация, retry или ожидаемая проблема без потери
  управления процессом.
- `ERROR` — операция не завершена, но процесс способен продолжать работу.
- `CRITICAL` — процесс не способен продолжать работу.

Показывать пользователю высокочастотные ситуации и отдельно согласовывать их
перевод из `DEBUG` в `INFO`. Не назначать `INFO` каждому успешному сообщению или
внутреннему шагу автоматически.

## Профиль процесса

Для каждого процесса определить дополнительные поля, а затем таблицу:

|Ситуация|Машинное имя|Уровень|Условие записи|Обязательные поля|Дополнительные поля|
|:---|:---|:---|:---|:---|:---|

Описывать только значимые ситуации: lifecycle, итог операции, retry,
контролируемую деградацию и окончательный отказ. Не превращать документ в трассу
каждой функции. Не копировать общие поля в каждый профиль; ссылаться на
`common.md`.

## Идентификаторы

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

Фиксировать требуемую семантику, а не способ реализации. Если согласован
`event_id`, документировать его стабильность при retry, но не определять таблицу,
адаптер, слой хранения или алгоритм генерации.

## Ошибки

- Логировать один окончательный отказ один раз на внешней границе, знающей исход.
- Внутренним слоям и адаптерам разрешать преобразование ошибки без повторной
  записи того же отказа.
- Ожидаемые отказы и предусмотренные retry описывать без stack trace: безопасная
  категория, исход, попытка и относящийся к операции контекст.
- Для неожиданной ошибки предлагать один stack trace на конечной границе и
  согласовывать политику повторов, ограничения объёма и усечения. Для structured
  формата отдельно согласовывать и фиксировать стабильное имя условного поля,
  содержащего stack trace; в записях без stack trace это поле не требовать.
- Не делать stack trace обязательным общим полем.
- Для повторяющейся неожиданной ошибки worker-а предлагать ограничение или
  агрегацию одинаковых записей, не скрывая факт продолжающегося сбоя.

## Безопасность

Не логировать секреты, токены, пароли, authorization headers, строки подключения,
полные HTTP/message payload, SQL и его параметры. Персональные данные и иные
предметно чувствительные сведения включать только после явного подтверждения.
Спрашивать пользователя о дополнительных категориях чувствительных данных и о
допустимых идентификаторах.

## Границы

- Описывать целевое состояние, а не реестр расхождений реализации.
- Использовать код для определения процессов только с разрешения пользователя.
- Аудит текущего logging выполнять отдельным отчётом по явной просьбе.
- Не выбирать logging-библиотеку, collector, хранилище или dashboard.
- Не определять устройство HTTP, broker, persistence, outbox и worker-адаптеров.
- Пока не документировать метрики и трассировку и не создавать для них пустые
  разделы. Добавить их в этот скил позднее после отдельного согласования.

## Проверка

- Общий контракт и каждый профиль процесса подтверждены пользователем.
- Для полей объяснены семантика и сценарии поиска.
- Для ситуаций определены условие, уровень и относящиеся к ним поля.
- Высокочастотные записи и политика неожиданных ошибок согласованы.
- Для structured-формата зафиксировано имя условного поля stack trace.
- Идентификаторы описаны семантически без проектирования чужих адаптеров.
- Чувствительные данные исключены.
- Process-документы не повторяют `common.md`.
- Поддерево встроено в структуру и `SUMMARY.md` общего скила.
- Каждый документ содержит актуальный раздел открытых вопросов.

