Skip to the content.

Вернуться к главной странице, списку всех тем

8. Контроль состояния приложений, обнаружение проблем с ними и отслеживание их взаимосвязей

Представь, что у тебя есть большая фабрика с сотнями станков. Каждый станок что-то делает, между ними по конвейерам ездят детали, а в конце получаются готовые телефоны. Если завтра один станок сломается — заметишь ли ты это сразу? А через час?

Точно так же современное приложение — это не одна программа, а десятки или сотни маленьких сервисов, общающихся друг с другом. У тебя может быть отдельный сервис для авторизации, отдельный для каталога товаров, отдельный для оплаты, отдельный для уведомлений. Когда пользователь жмёт «купить», запрос проходит через 10 разных сервисов. Если один из них сломается или начнёт тормозить — без правильных инструментов ты узнаешь об этом из жалоб клиентов, а не от системы.

Observability (наблюдаемость) — это способность по выходным сигналам системы понимать, что происходит внутри неё. На русский часто переводят как «наблюдаемость», но термин «observability» уже устойчиво прижился. Это не то же самое, что мониторинг — это его эволюция.

Три кита observability

Современная наблюдаемость стоит на трёх «китах» — три типа данных, которые мы собираем с системы:

  1. Метрики (Metrics) — числовые показатели во времени. «Сейчас 12 запросов в секунду», «средняя задержка 50 мс», «использовано 70% CPU». Дёшево хранить, легко агрегировать. Отвечают на вопрос «что происходит?».
  2. Логи (Logs) — текстовые записи событий с временной меткой. «2026-04-15 10:23:01 ERROR: connection to db timeout». Дорого хранить (много данных), но содержат подробности. Отвечают на вопрос «почему это произошло?».
  3. Трейсы (Traces) — путь одного запроса через все сервисы системы. «Запрос пришёл в API Gateway → ушёл в auth-service (5 мс) → ушёл в catalog-service (45 мс — вот где тормоз!) → вернулся пользователю». Отвечают на вопрос «где это произошло?».

В современных системах к ним часто добавляют четвёртый «кит» — события (Events) и профили (Continuous Profiling) — но базовая модель остаётся.

Метрики и Prometheus

Prometheus — самый популярный движок мониторинга, де-факто стандарт в облачных и Kubernetes-системах. Это open-source проект под управлением CNCF (Cloud Native Computing Foundation). В ноябре 2024 года вышел Prometheus 3.0 с большими улучшениями: нативные гистограммы, поддержка OTLP, UTF-8 в названиях метрик.

Как работает Prometheus

  1. Pull-модель — Prometheus сам ходит по приложениям и забирает метрики с эндпоинта /metrics. Это противоположно push-модели, где приложение само отправляет данные. Pull удобнее для service discovery в Kubernetes и для отладки.
  2. Time-series database — данные хранятся как временные ряды: metric_name{label1="value1", label2="value2"} value @timestamp.
  3. PromQL — мощный язык запросов, на котором строятся графики, recording rules и алерты.
  4. Service discovery — Prometheus сам находит, какие приложения и поды нужно опрашивать (через Kubernetes API, файлы, Consul, etc.).

Основные типы метрик

  1. Counter — счётчик, только растёт (или сбрасывается в 0 при рестарте). Примеры: http_requests_total, errors_total. Из них считают rate.
  2. Gauge — значение, которое может расти и падать. Примеры: memory_usage_bytes, current_connections, queue_size.
  3. Histogram — распределение значений по бакетам. Например, сколько запросов уложились в 100 мс, сколько в 500 мс, сколько в 1 секунду. Из него считают перцентили (P50, P95, P99).
  4. Summary — похож на гистограмму, но перцентили считаются на стороне приложения. Используется реже.

В Prometheus 3.0 появились native histograms — компактнее и точнее, чем классические бакеты, но пока поддерживаются не всеми клиентскими библиотеками.

Примеры PromQL-запросов

# Запросов в секунду за последние 5 минут
sum(rate(http_requests_total[5m]))

# По коду ответа
sum by (status) (rate(http_requests_total[5m]))

# Процент ошибок (5xx) от всех запросов
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m]))

# 95-й перцентиль времени отклика
histogram_quantile(0.95,
  sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

# Использование памяти приложением, в % от лимита
container_memory_usage_bytes{pod=~"my-app-.*"}
/ container_spec_memory_limit_bytes{pod=~"my-app-.*"} * 100

Grafana — визуализация

Grafana — самый популярный инструмент для построения дашбордов. Подключается ко множеству источников: Prometheus, Loki, Tempo, Elasticsearch, PostgreSQL, ClickHouse. В 2026 году актуальна версия Grafana 11.

Возможности Grafana:

Любители готового могут пользоваться Grafana Cloud — SaaS-версией со встроенным Prometheus, Loki, Tempo и хранилищем «из коробки». Бесплатный tier позволяет хранить метрики 14 дней.

Логирование: Loki и ELK

Логи — это второй кит. Их собирают со всех серверов, контейнеров, приложений в одно центральное место, чтобы можно было искать по тексту и фильтровать.

Loki — «Prometheus для логов»

Grafana Loki — современный движок логов от той же команды, что делает Grafana. Главная идея: индексировать только метаданные (лейблы), а не полный текст логов. Это делает Loki в 10–100 раз дешевле в хранении, чем Elasticsearch.

Архитектура Loki:

Язык запросов LogQL очень похож на PromQL:

# Логи приложения my-app с уровнем error
{app="my-app", level="error"}

# Поиск по тексту
{app="my-app"} |= "connection timeout"

# Только за последние 5 минут с регуляркой
{app="my-app"} |~ "user_id=\\d+" | json

# Rate ошибок
rate({app="my-app", level="error"}[5m])

ELK / Elastic Stack

Elasticsearch + Logstash + Kibana — классический стек, более старый, но всё ещё популярный. Полнотекстовый поиск работает лучше Loki, но в разы дороже из-за полной индексации.

⚠️ В 2021 году Elasticsearch сменил лицензию на SSPL, что было воспринято как «closed source». В ответ AWS форкнул проект и создал OpenSearch — полностью open-source версию. Сейчас OpenSearch активно развивается и для многих случаев — оптимальная замена.

Что выбрать: Loki или ELK?

Критерий Loki ELK / OpenSearch
Стоимость хранения Низкая Высокая
Поиск по тексту Простой Мощный
Аналитика, агрегации Базовая Очень богатая
Интеграция с Prometheus/Grafana Идеальная Нужны плагины
Сложность эксплуатации Низкая Средняя–высокая
Подходит для Большинства DevOps-сценариев Search-кейсы, SIEM, аудит

В 2026 году для нового стека observability обычно начинают с Loki. ELK/OpenSearch остаётся для случаев, где нужен мощный поиск (например, безопасность, SIEM, аудит-логи финтеха).

Трейсинг: путь запроса через систему

Когда у тебя 50 микросервисов, и пользователь жалуется на медленную страницу, единственный способ понять, где именно тормозит — посмотреть трейс (распределённую трассировку). Трейс — это дерево вызовов: главный запрос → подзапросы → их подзапросы и т. д.

OpenTelemetry — единый стандарт 2026 года

OpenTelemetry (часто сокращают до OTel) — это единый открытый стандарт для всех типов телеметрии (трейсы, метрики, логи), под управлением CNCF. К 2026 году OpenTelemetry стал безусловным стандартом — все новые приложения должны инструментироваться через него, а не через специфичные SDK конкретных движков.

Структура OpenTelemetry:

Главные преимущества: один SDK подходит ко всем хранилищам. Перешёл с Jaeger на Tempo? Не нужно переписывать приложение, достаточно поменять конфиг Collector’а.

Хранилища трейсов

  1. Jaeger — классический open-source трейсер от Uber. Прост, надёжен, но плохо масштабируется на сотни миллионов спанов в сутки.
  2. Grafana Tempo — современный движок от Grafana Labs. Хранит данные в Object Storage (как Loki), масштабируется почти бесконечно, дёшев. В 2026 году — основной выбор для новых стеков.
  3. Yandex Cloud Tracing — managed-сервис в Yandex Cloud, OTLP-совместимый.
  4. Zipkin — самый старый из живых, но используется всё реже.

Что показывает трейс

Один трейс — это «дерево» спанов (span — единица работы). Например, для HTTP-запроса:

Span 1: GET /api/order/123                          250 ms
├── Span 2: auth.verify_token                        15 ms
├── Span 3: order_service.get_order                 180 ms
│   ├── Span 4: postgres.SELECT * FROM orders        12 ms
│   ├── Span 5: redis.GET order:123                    1 ms
│   └── Span 6: kafka.publish order.viewed             3 ms
└── Span 7: response.serialize                        5 ms

Видно: 72% времени съел сам order_service.get_order, в нём чистая БД — 12 мс, остальное — что-то ещё. Дальше можно копать дальше.

Service Mesh: Istio, Linkerd, Cilium

В микросервисной архитектуре service mesh берёт на себя сетевое общение между сервисами: маршрутизацию, шифрование (mTLS), retry, rate limiting, observability «из коробки».

Istio

Самый мощный и самый сложный service mesh. Состоит из:

Что умеет Istio:

Linkerd

Более простая и легковесная альтернатива Istio. Не такая богатая функциональность, но проще в эксплуатации, меньше потребляет ресурсов.

Cilium

В 2026 году Cilium — это уже не только CNI (сетевой плагин для Kubernetes), но и полноценный service mesh, построенный на технологии eBPF. eBPF позволяет запускать программы прямо в ядре Linux, что даёт огромную производительность и минимальные накладные расходы. Cilium умеет:

В 2026 году выбор обычно такой:

eBPF-based observability

eBPF — революционная технология ядра Linux, позволяющая прозрачно собирать метрики, логи и трейсы прямо с уровня ядра, не модифицируя приложения. К 2026 году появилось целое поколение eBPF-инструментов:

Это направление активно растёт и постепенно дополняет (а иногда вытесняет) классический Prometheus + ручную инструментацию.

Золотые сигналы и методы мониторинга

Four Golden Signals (Google SRE)

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

  1. Latency (Задержка) — сколько времени занимает запрос. Отдельно успешные и неуспешные.
  2. Traffic (Трафик) — сколько запросов идёт. RPS, QPS, MB/s, в зависимости от типа сервиса.
  3. Errors (Ошибки) — какой процент запросов завершается ошибкой.
  4. Saturation (Насыщение) — насколько забиты ресурсы. CPU, память, диск, очереди.

RED method (для сервисов)

Усечённая версия Golden Signals от Tom Wilkie (Grafana Labs), применимая к любому сервису:

USE method (для ресурсов)

От Brendan Gregg, применим к любому ресурсу (CPU, диск, сеть):

SLO, SLI, Error Budget — фундамент SRE

SLI (Service Level Indicator) — измеримый показатель качества сервиса. Например, «доля успешных HTTP-запросов».

SLO (Service Level Objective) — целевое значение SLI. Например, «99.9% запросов должны быть успешными за rolling 30-day window».

SLA (Service Level Agreement) — контрактное обязательство перед клиентом. Обычно слабее SLO (если SLO = 99.9%, SLA = 99.5%, чтобы был запас).

Error Budget — допустимое количество ошибок, чтобы оставаться в SLO. Если SLO = 99.9% за 30 дней, error budget = 0.1% × 43200 минут = 43.2 минуты downtime в месяц. Пока бюджет не израсходован — можно катить рисковые релизы. Если израсходован — заморозка релизов, фокус на стабильности.

Burn Rate — скорость сжигания error budget. Multi-window burn rate alerts (5-минутное окно + 1-часовое) — золотой стандарт для алертов 2026 года.

Алерты — правильно и неправильно

Хорошие алерты:

Плохие алерты:

Хороший on-call: за смену 0–1 настоящих алерта. Если будят чаще — нужно срочно чинить алерты и причины, иначе выгорание гарантировано.

Теоретические вопросы

  1. Что такое observability и чем отличается от мониторинга? Ответ: Мониторинг — наблюдение за заранее известными показателями (CPU, RAM, error rate). Observability — способность ответить на любой новый вопрос о системе по её внешним сигналам, даже на тот, который не был предусмотрен заранее. Для observability нужны три кита: метрики, логи, трейсы.

  2. Перечисли три (или четыре) кита observability и приведи примеры инструментов. Ответ: Метрики (Prometheus, VictoriaMetrics), логи (Loki, Elasticsearch/OpenSearch), трейсы (Tempo, Jaeger). Иногда добавляют непрерывное профилирование (Parca, Pyroscope) как четвёртый кит.

  3. Pull vs Push в мониторинге — в чём разница? Ответ: Pull — система мониторинга сама ходит и забирает метрики (Prometheus). Push — приложение само отправляет метрики (StatsD, Graphite). Pull удобнее для service discovery и отладки (приложение всегда отдаёт /metrics), push — для систем с динамическими/короткоживущими процессами (CronJob, Lambda) или когда приложение за NAT.

  4. Что такое Counter, Gauge, Histogram в Prometheus? Ответ: Counter — только растущий счётчик (запросы, ошибки). Gauge — может расти и падать (CPU, память, очередь). Histogram — распределение значений по бакетам, нужен для перцентилей задержки.

  5. Что такое PromQL? Приведи пример rate-запроса. Ответ: Язык запросов Prometheus. rate(http_requests_total[5m]) — скорость роста счётчика за последние 5 минут, то есть RPS.

  6. Что такое recording rule и зачем оно нужно? Ответ: Заранее вычисляемое выражение, которое сохраняется как новая метрика. Используется для тяжёлых вычислений, которые применяются часто (на дашбордах, в алертах). Снижает нагрузку на Prometheus, ускоряет дашборды, делает алерты надёжнее.

  7. Чем отличается Loki от Elasticsearch? Ответ: Loki индексирует только лейблы, а не полный текст логов — дешевле в 10–100 раз, но поиск по тексту менее гибкий. Elasticsearch индексирует всё — дорого, но мощный полнотекстовый поиск и аналитика. Loki — для большинства DevOps-сценариев, Elasticsearch/OpenSearch — для SIEM, аудит-логов, мощного поиска.

  8. Что такое OpenTelemetry и почему он стал стандартом? Ответ: Единый открытый стандарт CNCF для всех типов телеметрии (трейсы, метрики, логи). Стандартизировал API, SDK и протокол передачи (OTLP). Раньше каждый трейсер (Jaeger, Zipkin, Datadog) имел свой SDK — переход с одного на другой был болью. OpenTelemetry эту проблему решил: переключение хранилища — это конфиг, не код.

  9. Что такое distributed trace и span? Ответ: Trace — полный путь запроса через систему (дерево). Span — одна единица работы внутри trace: HTTP-вызов, запрос к БД, обработка функцией. Каждый span имеет ID, parent_id (формирует дерево), время начала и длительность.

  10. Что такое Service Mesh? Какую проблему он решает? Ответ: Слой сетевой инфраструктуры между микросервисами. Берёт на себя: mTLS-шифрование, retry, timeout, circuit breaker, load balancing, observability — без изменения кода приложений. Главные представители: Istio, Linkerd, Cilium.

  11. Что такое Istio Ambient mode и чем он лучше классического Istio? Ответ: Архитектура Istio без sidecar-контейнеров в каждом поде. Стабильна с Istio 1.24 (август 2024). Преимущества: меньше потребляет CPU/RAM (нет сайдкара на каждый под), проще rollout (не нужно перезапускать поды для обновления mesh), безопаснее (меньше attack surface). Недостатки: пока менее богатая функциональность чем классический режим.

  12. Что такое eBPF и какую роль он играет в observability 2026 года? Ответ: Технология ядра Linux, позволяющая запускать программы внутри ядра без модификации ядра. Позволяет прозрачно собирать метрики, логи, трейсы прямо с уровня kernel space, без инструментации приложений. Лежит в основе современных observability-инструментов (Cilium Hubble, Pixie, Coroot, Parca).

  13. Что такое SLI, SLO, SLA? Ответ: SLI — измеримый показатель (например, % успешных запросов). SLO — целевое значение SLI (например, 99.9%). SLA — внешнее контрактное обязательство (обычно слабее SLO, чтобы был запас).

  14. Что такое Error Budget? Ответ: Допустимое количество «плохих» событий, чтобы оставаться в SLO. SLO 99.9% за 30 дней = error budget 43.2 минуты downtime. Пока бюджет есть — релизы катим, как только израсходован — заморозка и фокус на надёжности.

  15. Что такое burn rate и multi-window burn rate alert? Ответ: Burn rate — текущая скорость сжигания error budget. Multi-window — алерт срабатывает, когда одновременно два временных окна (короткое и длинное) показывают высокий burn rate. Это снижает ложные срабатывания и позволяет ловить как «быстрые катастрофы», так и «медленные деградации».

  16. Назови Four Golden Signals и приведи метрику для каждого. Ответ: Latency (histogram_quantile(0.95, ...)), Traffic (rate(requests_total)), Errors (rate(errors_total) / rate(requests_total)), Saturation (cpu_usage / cpu_limit).

  17. Что такое cardinality и почему он критичен для Prometheus? Ответ: Количество уникальных комбинаций лейблов у метрики. Метрика http_requests_total{path="/api/users/123"} с user_id в пути создаст миллионы рядов и убьёт Prometheus. Правило: лейблы должны быть с конечным небольшим набором значений (status, method, route, но не user_id и не request_id).

  18. Зачем алерты сначала идут в Alertmanager, а не в Slack/Telegram напрямую? Ответ: Alertmanager делает дедупликацию (одно событие — один алерт, а не сто), группировку (схожие алерты вместе), маршрутизацию (critical → on-call, warning → ticket), ингибицию (если упал хост — не шуметь про сервисы на нём), silence (на время плановых работ).

  19. Что такое RED-метод и для чего он применяется? Ответ: Rate, Errors, Duration — три метрики, которые надо мониторить для каждого сервиса (от Tom Wilkie). Универсальный подход для микросервисов.

  20. Назови минимальный observability-стек для нового проекта в 2026 году. Ответ: Метрики — Prometheus + Grafana, логи — Loki + Promtail/Alloy, трейсы — Tempo, инструментация приложений — OpenTelemetry SDK + Collector, алерты — Alertmanager. Для Kubernetes-кластера установить kube-prometheus-stack (Helm-чарт), и это всё через 30 минут.

Практическая часть

Задание 1. Развернуть полный стек на одной машине через Docker Compose

Цель: Получить рабочий monitoring-стек локально.

Шаги:

  1. Создай папку и файл compose.yml:

    services:
      prometheus:
        image: prom/prometheus:v3.1.0
        ports: ["9090:9090"]
        volumes:
          - ./prometheus.yml:/etc/prometheus/prometheus.yml
          - prom_data:/prometheus
        command:
          - "--config.file=/etc/prometheus/prometheus.yml"
          - "--web.enable-lifecycle"
          - "--enable-feature=otlp-write-receiver"
        restart: unless-stopped
    
      grafana:
        image: grafana/grafana:11.4.0
        ports: ["3000:3000"]
        environment:
          GF_SECURITY_ADMIN_PASSWORD: admin
        volumes:
          - grafana_data:/var/lib/grafana
        restart: unless-stopped
    
      loki:
        image: grafana/loki:3.3.0
        ports: ["3100:3100"]
        command: -config.file=/etc/loki/local-config.yaml
        restart: unless-stopped
    
      alloy:
        image: grafana/alloy:v1.5.0
        volumes:
          - ./alloy-config.river:/etc/alloy/config.river
          - /var/log:/var/log:ro
        command:
          - run
          - --server.http.listen-addr=0.0.0.0:12345
          - /etc/alloy/config.river
        restart: unless-stopped
    
      node-exporter:
        image: prom/node-exporter:v1.8.2
        ports: ["9100:9100"]
        pid: host
        volumes:
          - /proc:/host/proc:ro
          - /sys:/host/sys:ro
        command:
          - "--path.procfs=/host/proc"
          - "--path.sysfs=/host/sys"
        restart: unless-stopped
    
      alertmanager:
        image: prom/alertmanager:v0.28.0
        ports: ["9093:9093"]
        volumes:
          - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
        restart: unless-stopped
    
      tempo:
        image: grafana/tempo:2.6.1
        ports: ["3200:3200", "4317:4317"]
        command: ["-config.file=/etc/tempo.yaml"]
        volumes:
          - ./tempo.yaml:/etc/tempo.yaml
        restart: unless-stopped
    
    volumes:
      prom_data:
      grafana_data:
    
  2. Создай минимальный prometheus.yml:

    global:
      scrape_interval: 15s
      evaluation_interval: 15s
    
    scrape_configs:
      - job_name: prometheus
        static_configs: [{ targets: ["prometheus:9090"] }]
    
      - job_name: node
        static_configs: [{ targets: ["node-exporter:9100"] }]
    
  3. Запусти всё:
    docker compose up -d
    docker compose ps
    
  4. Открой:
    • Prometheus: http://localhost:9090
    • Grafana: http://localhost:3000 (admin / admin)
    • Alertmanager: http://localhost:9093
  5. В Grafana добавь два data source: Prometheus (http://prometheus:9090) и Loki (http://loki:3100).

Задание 2. Импортировать готовый дашборд

  1. В Grafana: Dashboards → New → Import.
  2. ID 1860 (Node Exporter Full) → загрузи.
  3. Изучи метрики: CPU, RAM, диск, сеть.

Задание 3. Написать свои PromQL-запросы

В Prometheus UI (http://localhost:9090) попробуй:

# Текущая загрузка CPU в %
100 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100

# Доступная память в гигабайтах
node_memory_MemAvailable_bytes / 1024 / 1024 / 1024

# Свободное место на диске /
node_filesystem_avail_bytes{mountpoint="/"} / 1024 / 1024 / 1024

# Запросов в секунду к самому Prometheus
sum(rate(prometheus_http_requests_total[5m]))

Задание 4. Настроить alert и проверить через Alertmanager

  1. Добавь в Prometheus файл alerts.yml:

    groups:
      - name: demo
        rules:
          - alert: HighCPUUsage
            expr: 100 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 > 80
            for: 2m
            labels: { severity: warning }
            annotations:
              summary: "Высокая загрузка CPU"
              description: "CPU > 80% уже 2 минуты"
    
  2. Добавь его в prometheus.yml: ```yaml rule_files:
    • /etc/prometheus/alerts.yml

    alerting: alertmanagers: - static_configs: - targets: [“alertmanager:9093”] ```

  3. Перезагрузи Prometheus: curl -X POST http://localhost:9090/-/reload.

  4. Создай искусственную нагрузку, чтобы алерт сработал:
    yes > /dev/null &  # съест одно ядро на 100%
    yes > /dev/null &  # ещё одно
    
  5. Через 2 минуты алерт появится в Prometheus → Alerts и в Alertmanager.

  6. Останови нагрузку: pkill yes.

Задание 5. Изучить eBPF observability через Coroot

Цель: Увидеть, как современные инструменты «из коробки» рисуют карту сервисов.

Шаги:

  1. Открой https://demo.coroot.com — там готовое демо со всеми тремя китами одновременно.
  2. Изучи Service Map — Coroot автоматически нарисовал граф взаимодействий между сервисами.
  3. Кликни на любой сервис → посмотри: RED-метрики, логи, трейсы, профайлинг.
  4. Изучи SLO — Coroot автоматически считает SLO для всех сервисов.
  5. Прочитай документацию: https://coroot.com/blog/engineering/getting-started-with-coroot-concepts-and-terminology/

Задание 6. SLO + Error Budget в проде

Цель: Спроектировать SLO для гипотетического сервиса.

Допустим, у тебя API-сервис payments. Опиши:

  1. SLI: какая метрика отражает «успешность» с точки зрения пользователя?
    • Пример: (rate(http_requests_total{status!~"5..", service="payments"}[5m]) / rate(http_requests_total{service="payments"}[5m]))
  2. SLO: какой процент успешных запросов целевой?
    • 99.9% за rolling 30 дней.
  3. Error Budget: сколько минут downtime допускается в месяц?
    • 0.1% × 30 × 24 × 60 = 43.2 минуты.
  4. Burn rate alerts (multi-window):
    • Page: если за последние 5 минут И за последний час burn rate > 14.4 (это значит, что в текущем темпе бюджет кончится за ~2 часа).
    • Ticket: если за час И за 6 часов burn rate > 3 (бюджет кончится за ~10 дней).
  5. Error Budget Policy (политика бюджета):
    • Бюджет израсходован — заморозка фич, фокус на стабильности.
    • Бюджет в норме — можно катить рисковые релизы.

Задание 7. Чек-лист observability на проде