Перейти к содержанию

Tempo, Loki и Prometheus

Collector умеет принимать сигналы, но debug не хранит историю. Подключим три backend: Tempo для traces, Loki для logs и Prometheus для metrics. Grafana получит источники данных для каждого из них. В результате у «Пульса» появится конкретный путь от инструментирования до поиска, а не обещание «всё хранит OpenTelemetry». Эти компоненты выполняют разные операции и требуют отдельных правил доступа и retention.

Для лаборатории закреплены Tempo 2.7.2, Loki 3.4.2, Prometheus 3.2.1 и Grafana 11.6.0. Их выпуск подтверждён первичными источниками; выбран исторический согласованный набор для конкретного API. Контейнеры не запускались, поэтому совместимость конфигурации описана по документации, а не доказана выполненным стендом. Перед публичной эксплуатацией версии и безопасность обновляют и проверяют отдельно.

Traces в Tempo

Collector отправляет trace pipeline через otlphttp/tempo на внутренний адрес tempo:4318. Tempo принимает OTLP и хранит блоки в локальном volume лаборатории. Его HTTP query API доступен Grafana через порт 3200 внутри сети Compose. Порт приёма данных и порт поиска отличаются: источник Grafana обращается к query API, а приложение не должно отправлять spans на адрес интерфейса поиска.

Полный файл tempo.yaml состояния 08:

server:
  http_listen_port: 3200
distributor:
  receivers:
    otlp:
      protocols:
        http:
          endpoint: 0.0.0.0:4318
ingester:
  max_block_duration: 5m
compactor:
  compaction:
    block_retention: 24h
storage:
  trace:
    backend: local
    wal:
      path: /var/tempo/wal
    local:
      path: /var/tempo/blocks

Retention traces задан сутками. Это подходит небольшой лаборатории, но не гарантирует сохранение producer для задания, которое выполняется позже. При длинных очередях срок traces согласуют с максимальным временем расследуемой операции. Volume сохраняет данные между обычными перезапусками контейнера, но локальный диск не становится распределённым резервным хранилищем автоматически. Отказ диска требует отдельного плана.

Поиск свежего trace может зависеть от состояния ingestion и блоков. Если данные ещё не доступны в выбранном пути поиска, отсутствие немедленного результата не доказывает потерю span. Поэтому полезно искать конкретный ID, проверять интервал и состояние exporter. В учебных материалах нет наблюдённых секунд появления trace или скриншота: реальная задержка стенда ещё не измерена.

Logs в Loki

Loki принимает OTLP logs через exporter с endpoint http://loki:3100/otlp. SDK отправляет данные Collector, а Collector добавляет необходимый путь сигнала. Не используем старый специальный Loki exporter как обязательный слой: выбран native OTLP приём. Для structured metadata нужен подходящий schema и allow_structured_metadata; в конфиге используется TSDB schema v13.

Полный файл loki.yaml состояния 08:

auth_enabled: false
server:
  http_listen_port: 3100
common:
  instance_addr: 127.0.0.1
  path_prefix: /tmp/loki
  storage:
    filesystem:
      chunks_directory: /tmp/loki/chunks
      rules_directory: /tmp/loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory
schema_config:
  configs:
    - from: 2024-01-01
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h
limits_config:
  allow_structured_metadata: true
  retention_period: 24h
compactor:
  working_directory: /tmp/loki/compactor
  retention_enabled: true
  delete_request_store: filesystem
distributor:
  otlp_config:
    default_resource_attributes_as_index_labels: [service.name, deployment.environment.name]

Index labels ограничены service.name и окружением. Trace ID хранится как structured metadata, а не label потока. Такое разделение позволяет искать конкретный trace без создания отдельного indexed stream для каждой операции. При OTLP-нормализации точки в именах заменяются подчёркиваниями, поэтому LogQL использует service_name и trace_id. Синтаксис запроса зависит от реально сохранённого представления, а не от исходного названия поля в JavaScript.

В лаборатории auth_enabled:false означает отсутствие внутренней многопользовательской аутентификации Loki. Его порт не опубликован наружу, и Grafana обращается к нему внутри сети. Такое состояние нельзя переносить на публичный endpoint. Для реального сервиса доступ к backend ограничивают сетью, gateway и правами пользователей, а правила организации данных согласуют с возможностями multi-tenancy выбранной системы.

Metrics в Prometheus

В этом наборе Prometheus не принимает metrics тем же способом, что Tempo принимает traces. Collector exporter prometheus выставляет endpoint 8889, а Prometheus периодически scrapes его. Поэтому pipeline состоит из OTLP HTTP от Node до Collector и scrape от Prometheus до Collector. Если пропустить второй шаг, метрики могут находиться в памяти exporter, но не появляться в базе временных рядов.

Полный файл prometheus.yaml состояния 08:

global:
  scrape_interval: 5s
  evaluation_interval: 15s
rule_files: ["/etc/prometheus/alerts.yaml"]
scrape_configs:
  - job_name: pulse-collector
    static_configs:
      - targets: [collector:8889]

Мы не копируем все resource attributes в metric labels. Приложение уже добавило bounded service label, который используется запросами. Exporter переводит имена и единицы в представление Prometheus: counter получает суффикс total, histogram секунд — соответствующие bucket/count/sum. Далее дашборд использует именно это ожидаемое представление. При будущей проверке нужно сверить реальные имена на endpoint, а не угадывать их по одной строке SDK.

Prometheus хранит данные в отдельном volume и ограничен сутками retention. Counter, histogram и gauge имеют разные правила запросов: для накопительного счётчика обычно нужен rate, для bucket — rate перед histogram_quantile, для текущего возраста очереди — gauge. Один общий график sum(value) не объясняет эти различия и способен дать неверные выводы о скорости или задержке.

Grafana как клиент источников

Grafana получает три datasources с фиксированными UID. Панели ссылаются на UID, а не на случайно введённое отображаемое имя. Это делает конфигурацию переносимой между лабораторными состояниями. Источники находятся в серверной сети Compose; адрес http://tempo:3200 доступен Grafana, хотя браузер пользователя не умеет разрешать имя tempo. Браузер обращается к Grafana, а её proxy выполняет запрос к backend.

Полный файл datasources.yaml состояния 08:

apiVersion: 1
datasources:
  - name: Prometheus
    uid: pulse-prom
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
  - name: Tempo
    uid: pulse-tempo
    type: tempo
    access: proxy
    url: http://tempo:3200
  - name: Loki
    uid: pulse-loki
    type: loki
    access: proxy
    url: http://loki:3100

Grafana публикуется только на loopback 3000 и требует заданный пароль администратора; anonymous access отключён. Пустые значения в .env.example требуют самостоятельного заполнения. Доступ к Grafana — доступ к операционным сведениям приложения, даже если мы исключили PII. Поэтому для команды поддержки вводят подходящие роли и право видеть только нужные источники, а не раздают административный пароль всем участникам.

Collector удаляет несколько известных опасных атрибутов перед экспортом. Это дополнительный рубеж, а не универсальная очистка лог body. Безопасная модель продолжает начинаться в приложении, где не собираются Authorization, query, payload и SQL-параметры. Сохранение данных в backend делает позднее удаление сложнее, поэтому надежда на скрытие колонок интерфейса не заменяет ограничение collection.

Ожидаемый результат восьмого состояния — Grafana имеет три источника, trace pipeline направлен в Tempo, logs в Loki, metrics доступны через Prometheus scrape. Числа, найденные записи и загрузка дисков не заявлены как полученные нами результаты. Следующая глава соединит эти источники в дашборд диагностики, сохраняя отдельную возможность проверить каждый участок пути при пустом или устаревшем графике.

Предыдущий урок: OpenTelemetry Collector и OTLP · Следующий урок: Дашборд для диагностики задержки

Оглавление серии · Исходники всех состояний.

Документация: Loki native OTLP, Prometheus exporter 0.123.0.