惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
K
Kaspersky official blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
C
Cybersecurity and Infrastructure Security Agency CISA
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News - Newest:
Hacker News - Newest: "LLM"
Cisco Talos Blog
Cisco Talos Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Cyberwarzone
Cyberwarzone
L
LINUX DO - 最新话题
PCI Perspectives
PCI Perspectives
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
N
News and Events Feed by Topic
V
Vulnerabilities – Threatpost
T
Troy Hunt's Blog
GbyAI
GbyAI
C
CERT Recently Published Vulnerability Notes
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
量子位
Scott Helme
Scott Helme
月光博客
月光博客
Attack and Defense Labs
Attack and Defense Labs
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
Project Zero
Project Zero
G
GRAHAM CLULEY
博客园 - 【当耐特】
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
小众软件
小众软件
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
O
OpenAI News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
S
Security @ Cisco Blogs
The Last Watchdog
The Last Watchdog
MongoDB | Blog
MongoDB | Blog
H
Hacker News: Front Page
Latest news
Latest news
P
Proofpoint News Feed

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Как настроить observability в Spring Boot 3
Sergey Proshchaev · 2026-05-25 · via Все публикации подряд на Хабре

Средний

11 мин

9.2K

Всем привет, меня зовут Сергей Прощаев. Я Tech Lead и руководитель направления Java/Kotlin разработки в FinTech & E-commerce, а ещё преподаю на курсах разработки и архитектуры. В этой статье я покажу, как за полдня настроить observability в Spring Boot 3, чтобы наконец перестать гадать, почему ваш микросервис вдруг начинает тормозить или падать.

Рис. 1. Observability — «глаз» над микросервисами

Рис. 1. Observability — «глаз» над микросервисами

1. Почему вы читаете эту статью (и я её пишу)

Мне как-то попалась статистика: больше половины инцидентов в микросервисных системах приходится на слепую отладку — разработчики и SRE тыкают наугад, смотрят логи одного сервиса, потом другого, строят догадки.

Помню реальный случай из своей практики. Один наш сервис в e-commerce начал периодически отвечать с задержкой 5 секунд. Логи были чисты, метрики CPU — в норме. Команда две недели перебирала гипотезы: то сеть винили, то базу данных. А оказалось — забыли про propagation контекста трейса, и один микросервис делал повторный запрос к внешнему API без таймаута. Если бы у нас тогда был нормальный трейсинг с Zipkin, мы бы нашли причину за час, а не за две недели.

С тех пор я твёрдо уверен: observability — это не фича, а базовая необходимость. Особенно на Spring Boot 3, где инструменты для этого уже встроены нативно.

2. Исходные условия (чтобы вы могли повторить)

Прежде чем переходить к шагам, давайте зафиксируем, с чем мы работаем:

  • Версия Spring Boot: 3.2.x или новее (3.3, 3.4 — подойдёт любая).

  • Java: 17 или 21.

  • Проект: обычное веб-приложение с spring-boot-starter-web и spring-boot-starter-actuator (если нет — добавьте).

  • Инфраструктура: Docker и Docker Compose для поднятия Zipkin, Prometheus, Loki и Grafana. Можно и без Docker, но с ним проще.

  • Цель: получить единый дашборд, где метрики, трейсы и логи связаны одним идентификатором.

Ограничение: гайд не про продовое масштабирование на 10 000+ RPS. Для больших нагрузок понадобится сэмплирование и кластеризация. Но для команд до 20 микросервисов решение отличное.

3. Пошаговый маршрут: от нуля до дашборда

Я разбил процесс на 7 шагов. Каждый шаг заканчивается проверкой — чтобы вы сразу видели, что работает.

Шаг 1. Добавляем зависимости для метрик и трейсинга

В build.gradle (или pom.xml) добавьте:

implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation 'io.micrometer:micrometer-tracing-bridge-brave'
implementation 'io.zipkin.reporter2:zipkin-reporter-brave'

Зачем: actuator даёт эндпоинты, micrometer-registry-prometheus — экспорт метрик в формате Prometheus, tracing-bridge-brave и zipkin-reporter — отправку трейсов в Zipkin.

Проверка: после запуска приложения перейдите на http://localhost:8080/actuator. Если видите список эндпоинтов (health, info, metrics) — шаг выполнен.

Шаг 2. Настраиваем метрики и открываем /prometheus

В application.yml (или application.properties) настройте метрики:

management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus
  metrics:
    export:
      prometheus:
        enabled: true
    tags:
      application: my-awesome-service

Теперь метрики доступны по адресу /actuator/prometheus. Prometheus будет забирать их оттуда.

Проверка: откройте http://localhost:8080/actuator/prometheus — вы должны увидеть длинный список метрик (jvm_memory_used_bytes, http_server_requests_seconds и т.д.). Если страница не пустая — всё ок.

Шаг 3. Настраиваем трейсинг с Micrometer Tracing (НЕ Sleuth!)

Важное уточнение: в Spring Boot 3.x больше нет Spring Cloud Sleuth! Вместо него используется Micrometer Tracing. Поэтому настройки изменились.

В application.yml добавьте:

management:
  tracing:
    sampling:
      probability: 1.0   # 100% запросов в трейсы (для теста. В проде 0.1)
  zipkin:
    tracing:
      endpoint: http://localhost:9411/api/v2/spans   # Новый endpoint!

Эти настройки говорят Spring Boot 3 отправлять трейсы (спаны) на Zipkin сервер по новому адресу /api/v2/spans.

Заметка про выбор бекенда: для простоты демо мы используем Zipkin. В реальных системах в 2026 году чаще применяют Grafana Tempo или OTel Collector — они лучше интегрируются с современным стеком и масштабируются. Но для локального теста Zipkin остаётся самым лёгким вариантом.

Проверка: Сделайте любой HTTP-запрос к вашему приложению. Затем откройте http://localhost:9411 и нажмите «Run query». Если увидите хотя бы один трейс — трейсинг работает.

Шаг 4. Настраиваем логи с traceId (гарантированно)

Чтобы связать логи с трейсами, добавим traceId в вывод логов.

Важное предупреждение: в ряде конфигураций Micrometer Tracing может не прокидывать traceId в MDC автоматически (это зависит от используемого bridge и логгера). Это один из частых подводных камней при переходе на Spring Boot 3. Чтобы гарантировать появление traceId в логах, добавьте в любой @Configuration класс два бина:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.micrometer.tracing.logging.Slf4JEventListener;
import io.micrometer.tracing.brave.bridge.BraveBaggageTagCorrelation;
import java.util.List;

@Configuration
public class TracingConfig {
    
    @Bean
    public Slf4JEventListener slf4JEventListener() {
        return new Slf4JEventListener();
    }
    
    @Bean
    public BraveBaggageTagCorrelation baggageTagCorrelation() {
        return new BraveBaggageTagCorrelation(List.of("traceId", "spanId"));
    }
}

Важно: этот способ MDC-корреляции работает только для bridge Brave (micrometer-tracing-bridge-brave). Если вы переходите на OpenTelemetry (micrometer-tracing-bridge-otel), используйте вместо него OtelBaggageTagCorrelation из пакета io.micrometer.tracing.otel.bridge:

import io.micrometer.tracing.otel.bridge.OtelBaggageTagCorrelation;

@Bean
public OtelBaggageTagCorrelation baggageTagCorrelation() {
    return new OtelBaggageTagCorrelation(List.of("traceId", "spanId"));
}

Без этой замены traceId в логах снова пропадёт.

После этого в logback-spring.xml укажите паттерн:

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] traceId=%X{traceId} spanId=%X{spanId} %-5level %logger{36} - %msg%n</pattern>

Проверка: запустите приложение, сделайте запрос. Найдите в консоли строку лога — там должно быть traceId=.... Если есть — логи обогащены.

Шаг 5. Поднимаем Prometheus и настраиваем сбор метрик

Есть два способа: упрощённый (через host.docker.internal) и более правильный (через docker-compose). Покажу оба.

Способ 1 (для быстрой проверки на Windows/Mac):

Создайте prometheus.yml:

scrape_configs:
  - job_name: 'spring-boot-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['host.docker.internal:8080']

На Linux host.docker.internal не работает из коробки. Используйте способ 2.

Способ 2 (рекомендуемый, универсальный):

Запустите и приложение, и Prometheus в одной Docker-сети. Например, docker-compose.yml:

version: '3'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    networks:
      - observability
  
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
    networks:
      - observability

networks:
  observability:

В prometheus.yml тогда пишем:

scrape_configs:
  - job_name: 'spring-boot-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['app:8080']   # обращение по имени сервиса

Этот подход ближе к реальному продакшену (Kubernetes, docker swarm).

Проверка: откройте http://localhost:9090, введите в строке запроса up. Если ваш сервис появляется со значением 1 — метрики собираются.

Шаг 6. Настраиваем Loki для логов

Loki — легковесная замена ELK. Запустите её вместе с Promtail (агент для tail логов из файлов) через Docker Compose.

Минимальный конфиг promtail.yml для чтения логов приложения из файла:

scrape_configs:
  - job_name: spring-logs
    static_configs:
      - targets: [localhost]
        labels:
          job: spring
          __path__: /var/log/application/*.log   # путь к вашим логам

Запустите Loki и Promtail (например, через docker-compose), и логи появятся в Grafana. Полный docker-compose.yml с Loki + Grafana можно найти в официальной документации — не привожу его, чтобы не раздувать статью.

Проверка: если настроили Loki, то в Grafana вы сможете выбирать источник данных «Loki» и видеть логи, отфильтрованные по traceId.

Шаг 7. Собираем всё в Grafana

Запустите Grafana:

docker run -d -p 3000:3000 grafana/grafana

Зайдите на http://localhost:3000 (логин admin/admin). Добавьте источники данных:

  • Prometheus — URL http://localhost:9090

  • Zipkin — выберите в списке Zipkin (если его нет, установите плагин zipkin из каталога Grafana Plugins). Не путайте с Jaeger — это разные источники.

  • Loki — если настроили

Затем импортируйте любой готовый дашборд для Spring Boot из каталога Grafana (например, популярный дашборд с ID 4701) или создайте свой. Я обычно добавляю три панели:

  1. График RPS и ошибок (из Prometheus)

  2. Список последних трейсов (из Zipkin)

  3. Логи по выбранному traceId (из Loki)

Финальная проверка: выполните запрос к приложению, который генерирует ошибку или долго выполняется. В Grafana найдите этот трейс, кликните на него — должны подтянуться соответствующие логи. Если да — вы построили полноценную observability.

Ниже — схема того, как всё это взаимодействует (рис. 2).

Рис. 2. Архитектура observability: три источника данных стекаются в Grafana

Рис. 2. Архитектура observability: три источника данных стекаются в Grafana

Эта схема показывает, как три типа данных — метрики, трейсы и логи — покидают микросервис Spring Boot 3 и стекаются в единую точку визуализации — Grafana. Метрики собираются Prometheus (через /actuator/prometheus), трейсы отправляются в Zipkin, а логи через Promtail передаются в Loki. Grafana подключается ко всем трём хранилищам и позволяет анализировать их совместно.

Observability строится не из одного инструмента, а из трёх независимых каналов, каждый из которых решает свою задачу, но в Grafana они объединяются в единую картину!

А вот как выглядит сквозная трассировка одного запроса через сервисы (рис. 3):

Рис. 3. Сквозной трейс: одинаковый traceId позволяет увидеть весь путь запроса

Рис. 3. Сквозной трейс: одинаковый traceId позволяет увидеть весь путь запроса

Диаграмма последовательности показывает один HTTP-запрос GET /order, который проходит через три звена: Client → ServiceA → ServiceB → DB. Ключевой момент: во всех сообщениях передаётся один и тот же traceId = abc, а также добавляются spanId для каждого шага. Это позволяет отследить весь путь запроса от клиента до базы данных и обратно.

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

4. Где автоматическая propagation НЕ работает (и что делать)

Автоматическая передача контекста трейса между сервисами — это магия, но только для определённых технологий.

Работает из коробки:

  • RestTemplate

  • WebClient

  • FeignClient

Не работает автоматически (нужно донастраивать):

  • Kafka / RabbitMQ (потоковая обработка)

  • gRPC

  • кастомные HTTP-клиенты (Apache HttpClient, OkHttp без интерцепторов)

  • асинхронные вызовы (@Async, пулы потоков)

Если в вашей системе есть Kafka, вы не увидите сквозного трейса, пока не добавите в конфигурацию продюсера и консьюмера специальные интерцепторы для Micrometer Tracing.
Для Kafka это решается подключением модуля micrometer-tracing-integration-kafka, который регистрирует необходимые интерцепторы в продюсере и консьюмере и прокидывает trace-контекст через заголовки сообщений.

5. Добавляем бизнес-метки в трейсы (современный способ)

Просто иметь traceId — это уже много. Но добавить в трейс orderId или userId — следующий уровень.

В новых версиях Micrometer (1.12+) предпочтительнее использовать Observation API вместо прямого обращения к Tracer. Вот как это выглядит:

import io.micrometer.observation.Observation;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    
    public Order createOrder(OrderRequest request) {
        Observation current = Observation.current();
        if (current != null) {
            current.highCardinalityKeyValue("userId", request.getUserId());
            current.highCardinalityKeyValue("orderId", request.getOrderId());
        }
        // ваша бизнес-логика
    }
}

Откуда вообще берётся Observation?Spring Boot автоматически создаёт Observation для каждого входящего HTTP-запроса, а также для вызовов RestTemplateWebClient, JDBC и многих других интеграций. Это работает, потому что Spring Boot автоматически регистрирует ObservationThreadLocalAccessor, который хранит текущий контекст в ThreadLocal. Внутри такого контекста Observation.current() не null. Однако в кастомных потоках (например, @Async, собственных пулах потоков, обработчиках Kafka) контекста может не быть. В этих случаях нужно создавать наблюдение вручную:

Observation observation = Observation.createNotStarted("myCustomOperation", registry);
try (Observation.Scope scope = observation.openScope()) {
    // ваш код
} finally {
    observation.stop();
}

registry — это бин ObservationRegistry, который уже есть в контексте Spring Boot и может быть внедрён через @Autowired.

Почему это лучше: Observation — это более высокоуровневый API, который абстрагирует и трейсинг, и метрики. Он появился в Micrometer 1.10 и стал стандартом в Spring Boot 3.2+. Использовать Tracer.currentSpan() напрямую — устаревшая практика.

Проверка: Откройте Zipkin, найдите трейс запроса, в котором были эти метки, — они должны отображаться в деталях спана.

6. Коротко про OpenTelemetry — почему это важно в 2026

Вы могли слышать про OpenTelemetry (OTel). Это индустриальный стандарт для сбора метрик, трейсов и логов, который поддерживается всеми крупными игроками.

Spring Boot 3 с Micrometer Tracing прекрасно с ним работает. Чтобы переключиться с Brave на OTel, достаточно заменить две зависимости:

// Было:
// implementation 'io.micrometer:micrometer-tracing-bridge-brave'
// implementation 'io.zipkin.reporter2:zipkin-reporter-brave'

// Стало:
implementation 'io.micrometer:micrometer-tracing-bridge-otel'
implementation 'io.opentelemetry:opentelemetry-exporter-zipkin'

И всё! Остальные настройки не меняются. OTel даёт:

  • Единый стандарт — не привязаны к вендору.

  • Лучшую поддержку в современных системах (например, в Grafana Tempo).

  • Гибкость: можно слать данные в Zipkin, Jaeger, Tempo и другие системы без изменения кода.

В 2026 году начинать новые проекты на OTel — это best practice.

7. Реальная история, которая перевернула мой подход

Помню, как работал над проектом для крупного финтех-клиента. У нас было около 40 микросервисов, и производительность начала резко падать каждую пятницу в 18:00. Пользователи бесились, бизнес терял деньги. SRE полгода боролись с «призраками»: меняли сеть, увеличивали ресурсы, переписывали код.

А потом мы наконец внедрили полноценный трейсинг с OpenTelemetry и подключили его к Grafana Tempo. И сразу увидели: каждую пятницу один из сервисов начинал делать повторные запросы к устаревшему SOAP-сервису с таймаутом в 30 секунд. Виновник — баг в расписании кэширования, которое не сбрасывало токены. Без трейсинга мы бы не связали падение производительности с конкретным вызовом.

Что я вынес из этой истории:

  • Observability должна быть спроектирована до того, как система пойдёт в прод. Не «потом починим», а сразу.

  • Всегда добавляйте в трейсы бизнес-метки (например, userIdorderId), чтобы можно было найти проблему конкретного клиента.

8. Где этот подход может не сработать (честные ограничения)

Observability — не серебряная пуля. Вот когда я бы не стал её разворачивать в полном объёме:

  • Очень маленький проект (2-3 сервиса, 500 запросов в сутки) — проще смотреть логи через kubectl logs. Накладные расходы на инфраструктуру могут превысить пользу.

  • Жёсткие требования к задержкам (real-time, high-frequency trading). Добавление трейсинга может внести микросекундные задержки. Решение — использовать низкоуровневые трейсеры вроде async profiler, но это уже не про Spring.

  • Когда нет культуры SRE — если команда не умеет интерпретировать метрики и трейсы, то даже самая красивая Grafana будет просто картинкой.

Но в 90% случаев — ставьте, не пожалеете!

9. Итог и следующий шаг

Мы прошли 7 шагов: от добавления зависимостей до дашборда в Grafana. Главное, что вы теперь умеете:

  • Настраивать метрики и выставлять их в Prometheus.

  • Добавлять трейсинг через Micrometer Tracing (не путать со Sleuth!).

  • Гарантированно добавлять traceId в логи через MDC-бины (и знаете разницу между Brave и OTel).

  • Понимать, где propagation работает, а где нет (и как починить Kafka).

  • Добавлять бизнес-метки через Observation API.

  • Выбирать между Zipkin (демо) и Tempo/OTel (прод).

  • Сводить всё в единый дашборд.

Мой вам совет: начните с малого — метрики + трейсинг 10% запросов. Это уже даст 80% пользы. Логи централизуйте позже, но с обязательным добавлением traceId.

Если этот гайд был полезен и вы хотите не просто прочитать, а научиться настраивать observability в продакшене, приходите на открытые уроки в OTUS. Разберём реальные дашборды, SLO, алерты и кейсы из практики.

  • 10 июня, 20:00 — «Мониторинг распределенных систем». Записаться
    Поговорим о том, как наблюдать за микросервисами, видеть сбои раньше пользователей и связывать метрики, логи и трейсы в единую картину.

  • 16 июня, 20:00 — «Инцидент-менеджмент в SRE. Как быстро находить, устранять и предотвращать сбои в системе». Записаться
    Разберём, как действовать при инцидентах: быстро локализовать проблему, не теряться в догадках и снижать риск повторных сбоев.

А пока — ставьте трейсинг, включайте метрики и пусть ваши логи всегда содержат traceId. До встречи в эфире.

Не забывайте подписываться на канал OTUS в MAX — там публикуем новые открытые уроки, разборы архитектуры, DevOps, Java, Spring и другие материалы для IT-специалистов.