Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Loki: агрегация логов для разработчиков
loki_fundamentals

Loki: агрегация логов для разработчиков

Архитектура Loki, отличие от Elasticsearch, сбор и поиск логов

Loki: агрегация логов для разработчиков

«Метрики говорят что происходит, логи — почему»

#Зачем нужен Loki

Prometheus отлично справляется с метриками, но не хранит логи.

Метрики — это числа во времени (CPU 75%, 100 запросов/сек). Логи — это текстовые записи о событиях («User 123 failed login at 14:32:01»).

Когда алерт сработал, вы смотрите на метрику и видите: «Error rate вырос до 10%». Но почему? Ответ в логах.

#Loki vs Elasticsearch

ХарактеристикаLokiElasticsearch (ELK)
ИндексацияТолько метаданные (лейблы)Полнотекстовая индексация всего контента
ХранениеСжатые чанки в объектном хранилищеИндексы на диске
ЗапросыLogQL (похож на PromQL)Lucene query language
РесурсыНизкие требованияТребует много RAM и CPU
Use caseАгрегация логов, отладкаПолнотекстовый поиск, аналитика

Loki проще и дешевле, потому что:

  • Не индексирует содержимое логов (только лейблы)
  • Хранит данные в сжатых чанках
  • Масштабируется горизонтально

Когда Loki:

  • Нужна агрегация логов для отладки
  • Хотите связать логи с метриками Prometheus
  • Ограниченные ресурсы

Когда Elasticsearch:

  • Нужен полнотекстовый поиск по логам
  • Сложная аналитика и корреляции
  • Уже есть инфраструктура ELK

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

┌─────────────────────────────────────────────────────────────┐
│                     Promtail / Agent                         │
│  (сбор логов с файлов, Docker, Kubernetes)                   │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                        Loki                                  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │ Distributor │  │ Ingester    │  │ Querier             │  │
│  │ (приём)     │  │ (чанки)     │  │ (запросы)           │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
│                           │                                   │
│                           ▼                                   │
│                  ┌─────────────────┐                         │
│                  │ Object Storage  │                         │
│                  │ (S3, GCS, disk) │                         │
│                  └─────────────────┘                         │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
                    ┌──────────┐
                    │ Grafana  │
                    │ (запросы)│
                    └──────────┘

Компоненты:

  1. Promtail — агент, который собирает логи с файлов, Docker, Kubernetes и отправляет в Loki
  2. Loki — сервер, который принимает, индексирует и хранит логи
  3. Grafana — интерфейс для запросов и визуализации логов

#Концепции Loki

#Лог-линии и потоки

Лог-линия — одна строка лога:

2026-03-18T14:30:00Z INFO User 123 logged in

Поток (Stream) — группа лог-линий с одинаковыми лейблами:

Stream: {app="api", env="production"}
  └─ 2026-03-18T14:30:00Z INFO User 123 logged in
  └─ 2026-03-18T14:30:01Z DEBUG Processing request
  └─ 2026-03-18T14:30:02Z INFO Request completed

#Лейблы

Лейблы — метаданные для фильтрации и агрегации.

Примеры лейблов:

  • app="api" — имя приложения
  • env="production" — окружение
  • instance="server1" — конкретный инстанс
  • level="error" — уровень логирования

Важно: Loki индексирует только лейблы, не содержимое логов. Поэтому выбор лейблов критичен.

Хорошие лейблы:

  • app, env, instance, level
  • Низкая кардинальность (ограниченное количество уникальных значений)

Плохие лейблы:

  • user_id, request_id (высокая кардинальность — миллионы значений)
  • Содержимое лога (например, error_message)

#Job и Instance

По аналогии с Prometheus:

  • Job — группа источников логов (например, все контейнеры одного сервиса)
  • Instance — конкретный источник (конкретный контейнер)

#LogQL: язык запросов Loki

LogQL похож на PromQL, но для логов.

#Базовый запрос

{app="api", env="production"}

Возвращает все логи с указанными лейблами.

#Фильтрация по содержимому

# Логи содержащие "error" {app="api"} |= "error" # Логи НЕ содержащие "debug" {app="api"} !~ "debug" # Регулярное выражение {app="api"} |~ "User \d+ logged in" # Несколько фильтров {app="api"} |= "error" |= "database"

Операторы:

  • |= — содержит (case-sensitive)
  • != — не содержит
  • =~ — совпадение с regex
  • !~ — не совпадает с regex

#Фильтрация по уровню логирования

# Только ошибки {app="api"} |= "level=error" # Ошибки и предупреждения {app="api"} |= "level=error" or |= "level=warn"

#Агрегации

LogQL поддерживает агрегации, похожие на PromQL:

# Количество лог-линий за период count_over_time({app="api"}[5m]) # Количество ошибок за период count_over_time({app="api"} |= "error"[1h]) # Первая строка лога first_over_time({app="api"}[5m]) # Последняя строка лога last_over_time({app="api"}[5m])

#Rate логов

# Логи в секунду rate({app="api"}[5m]) # Ошибки в секунду rate({app="api"} |= "error"[5m])

#Развёртывание Loki в Docker

Добавим Loki в наш docker-compose.

#docker-compose.yml

version: '3.8' services: prometheus: # ... (без изменений) grafana: # ... (без изменений) loki: image: grafana/loki:2.9.0 container_name: loki ports: - "3100:3100" volumes: - ./loki/loki-config.yml:/etc/loki/local-config.yaml - loki_data:/loki command: -config.file=/etc/loki/local-config.yaml restart: unless-stopped promtail: image: grafana/promtail:2.9.0 container_name: promtail volumes: - ./promtail/promtail-config.yml:/etc/promtail/config.yml - /var/log:/var/log:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro - /var/run/docker.sock:/var/run/docker.sock command: -config.file=/etc/promtail/config.yml restart: unless-stopped volumes: prometheus_data: grafana_data: loki_data:

#Конфигурация Loki (loki/loki-config.yml)

auth_enabled: false server: http_listen_port: 3100 grpc_listen_port: 9096 common: instance_addr: 127.0.0.1 path_prefix: /loki storage: filesystem: chunks_directory: /loki/chunks rules_directory: /loki/rules replication_factor: 1 ring: kvstore: store: inmemory query_range: results_cache: cache: embedded_cache: enabled: true max_size_mb: 100 schema_config: configs: - from: 2020-10-24 store: tsdb object_store: filesystem schema: v13 index: prefix: index_ period: 24h ruler: alertmanager_url: http://localhost:9093 limits_config: retention_period: 168h # Хранить логи 7 дней

#Конфигурация Promtail (promtail/promtail-config.yml)

server: http_listen_port: 9080 grpc_listen_port: 0 positions: filename: /tmp/positions.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: # Логи Docker контейнеров - job_name: containers docker_sd_configs: - host: unix:///var/run/docker.sock refresh_interval: 5s relabel_configs: - source_labels: ['__meta_docker_container_name'] target_label: 'container' - source_labels: ['__meta_docker_container_log_stream'] target_label: 'logstream' - source_labels: ['__meta_docker_container_label_com_docker_compose_service'] target_label: 'service' # Системные логи (если доступны) - job_name: system static_configs: - targets: - localhost labels: job: varlogs __path__: /var/log/*log

Что делает Promtail:

  1. Подключается к Docker socket
  2. Находит все контейнеры
  3. Читает их логи
  4. Добавляет лейблы (container, service)
  5. Отправляет в Loki

#Интеграция с Grafana

После запуска стека:

docker compose up -d

#Настройка источника данных

  1. Откройте Grafana (http://localhost:3000)
  2. ⚙️ Settings → Data sources → Add data source
  3. Выберите Loki
  4. URL: http://loki:3100
  5. Save & test

#Запрос логов в Explore

  1. Нажмите 🧭 Explore (левая панель)
  2. Выберите источник Loki
  3. Введите запрос:
{container="prometheus"}
  1. Нажмите Run

Вы увидите:

  • Список лог-линий справа
  • Гистограмму распределения логов во времени сверху
  • Фильтры для уточнения запроса

#Фильтрация в UI

Grafana предлагает интерактивные фильтры:

  • Кликните на строку лога → «Filter for value»
  • Выберите уровень (INFO, ERROR) → «Add filter»
  • Введите текст → «Search»

#Практические примеры запросов

#Пример 1: Логи конкретного контейнера

{container="api-app"}

#Пример 2: Только ошибки

{container="api-app"} |= "ERROR"

#Пример 3: Ошибки с паттерном

{container="api-app"} |= "ERROR" |~ "database.*connection"

#Пример 4: Количество ошибок за период

count_over_time({container="api-app"} |= "ERROR"[1h])

#Пример 5: Логи по сервису Docker Compose

{service="api"} |= "request"

#Пример 6: Rate логов

rate({container="api-app"}[5m])

Показывает, сколько логов в секунду генерирует контейнер. Резкий скачок может указывать на проблему.

#Пример 7: Агрегация по уровню

sum by (level) (count_over_time({app="api"} |= "level="[1h]))

Показывает распределение логов по уровням (INFO, WARN, ERROR) за час.


#Best practices работы с логами

#1. Структурированные логи

Используйте JSON формат для логов:

{"timestamp":"2026-03-18T14:30:00Z","level":"INFO","message":"User logged in","user_id":123}

Вместо:

2026-03-18T14:30:00Z INFO User 123 logged in

Преимущества:

  • Легче парсить
  • Можно извлекать поля через pipeline operators
  • Меньше ложных совпадений

#2. Разумные лейблы

Хорошо:

{app="api", env="production", level="error"}

Плохо:

{user_id="12345", request_id="abc-123-xyz"} # Высокая кардинальность!

#3. Уровни логирования

Используйте стандартные уровни:

  • DEBUG — отладочная информация
  • INFO — нормальная работа
  • WARN — предупреждения
  • ERROR — ошибки

#4. Ротация логов

Настройте ротацию, чтобы логи не заполнили диск:

# В loki-config.yml limits_config: retention_period: 168h # 7 дней

#5. Не логируйте чувствительные данные

  • Пароли
  • Токены
  • Персональные данные (PII)
  • Номера карт

#Отладка проблем с логами

#Проблема: логи не появляются

Причины:

  • Promtail не запущен
  • Неправильный путь к логам
  • Loki недоступен

Решение:

# Проверьте статус контейнеров docker compose ps # Посмотрите логи Promtail docker logs promtail # Проверьте подключение к Loki curl http://localhost:3100/ready

#Проблема: слишком много логов

Причины:

  • Логирование на уровне DEBUG в production
  • Нет фильтрации

Решение:

  • Измените уровень логирования приложения на INFO
  • Настройте фильтры в Promtail

#Проблема: медленно работают запросы

Причины:

  • Большой временной диапазон
  • Нет фильтрации по лейблам

Решение:

  • Уменьшите диапазон времени
  • Добавьте фильтры по лейблам перед фильтрацией по содержимому

Далее: Интеграция Loki с Grafana: логи рядом с метриками