Настройка централизованного логирования с Loki и Grafana

Логи разбросаны по десятку серверов — поиск причины падения превращается в недельный квест. При пиковых нагрузках логи теряются, а поиск ошибки занимает часы. Мы решаем это за день: ставим централизованный сбор на Grafana Loki и Promtail. В отличие от ELK, Loki не индексирует содержимое, только метк

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Настройка централизованного логирования с Loki и Grafana
Средний
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1422
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    984
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1249
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    986
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    1000

Логи разбросаны по десятку серверов — поиск причины падения превращается в недельный квест. При пиковых нагрузках логи теряются, а поиск ошибки занимает часы. Мы решаем это за день: ставим централизованный сбор на Grafana Loki и Promtail. В отличие от ELK, Loki не индексирует содержимое, только метки. На практике это даёт до 70% экономии на хранении и в два-три раза меньшую операционную нагрузку. На одном из проектов с 50 микросервисами (10 млн запросов в день) мы сократили time-to-detect с 2 дней до 15 минут. За 7 лет мы развернули более 40 production-стеков на Loki. Свяжитесь с нами — выполним настройку в течение 2-3 дней.

Почему Loki лучше Elasticsearch?

Согласно официальным данным Grafana Labs, Loki обеспечивает до 70% экономии на хранении по сравнению с ELK. При объеме логов 500 ГБ в сутки экономия может достигать $10 000 в месяц. Loki хранит логи в сжатых чанках без инвертированного индекса. Скорость запросов по меткам — миллисекунды. Если вам не нужна сложная агрегация по произвольным полям, Loki — правильный выбор. Экономия на инфраструктуре может составлять от $5 000 до $15 000 ежемесячно в зависимости от объема логов.

Критерий Loki ELK
Стоимость хранения Низкая (сжатые чанки) Высокая (инвертированный индекс)
Скорость поиска по меткам Высокая Средняя
Full-text поиск Ограниченный Полноценный
Операционная сложность Низкая (одна конфигурация) Высокая (три стека)
Интеграция с Grafana Нативная Через доп. плагин

Как мы разворачиваем стек?

Используем Docker Compose для быстрого развёртывания. Конфигурация включает три сервиса:

version: '3.8' services: loki: image: grafana/loki:3.0.0 ports: - "3100:3100" volumes: - ./loki-config.yml:/etc/loki/local-config.yaml - loki_data:/loki command: -config.file=/etc/loki/local-config.yaml promtail: image: grafana/promtail:3.0.0 volumes: - /var/log:/var/log:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro - ./promtail-config.yml:/etc/promtail/config.yml command: -config.file=/etc/promtail/config.yml grafana: image: grafana/grafana:11.0.0 ports: - "3000:3000" environment: - GF_AUTH_ANONYMOUS_ENABLED=false - GF_SECURITY_ADMIN_PASSWORD=admin_password volumes: - grafana_data:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning volumes: loki_data: grafana_data: 

Конфигурация Loki

auth_enabled: false server: http_listen_port: 3100 grpc_listen_port: 9096 common: path_prefix: /loki storage: filesystem: chunks_directory: /loki/chunks rules_directory: /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: retention_period: 744h # 31 день ingestion_rate_mb: 16 ingestion_burst_size_mb: 32 max_query_length: 721h compactor: working_directory: /loki/compactor retention_enabled: true delete_request_store: filesystem 

Конфигурация Promtail

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: - job_name: nginx static_configs: - targets: [localhost] labels: job: nginx env: production __path__: /var/log/nginx/access.log pipeline_stages: - regex: expression: '^(?P<ip>\S+) - (?P<user>\S+) \[(?P<timestamp>[^\]]+)\] "(?P<method>\S+) (?P<path>\S+) \S+" (?P<status>\d+) (?P<bytes>\d+)' - labels: status: method: - timestamp: source: timestamp format: "02/Jan/2006:15:04:05 -0700" - job_name: laravel static_configs: - targets: [localhost] labels: job: laravel-app env: production __path__: /var/www/app/storage/logs/laravel.log pipeline_stages: - multiline: firstline: '^\[\d{4}-\d{2}-\d{2}' max_wait_time: 3s - regex: expression: '^\[(?P<timestamp>[^\]]+)\] (?P<env>\w+)\.(?P<level>\w+): (?P<message>.*)' - labels: level: env: - timestamp: source: timestamp format: "2006-01-02 15:04:05" - job_name: docker 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 
Развертывание в Kubernetes Для Kubernetes используйте Helm-чарты: `helm install loki grafana/loki-stack` — это поднимет Loki, Promtail и Grafana с настройками по умолчанию. Для production настройте retention, метки и pipeline_stages через values.yaml.

Как интегрировать Laravel с Loki через Monolog?

Пишем кастомный Monolog-хендлер, который отправляет записи в Loki по HTTP API. Он работает fire-and-forget — не блокирует запрос.

// app/Logging/LokiHandler.php namespace App\Logging; use Monolog\Handler\AbstractProcessingHandler; use Monolog\LogRecord; class LokiHandler extends AbstractProcessingHandler { public function __construct( private string $lokiUrl, private array $labels = [] ) { parent::__construct(); } protected function write(LogRecord $record): void { $timestamp = (string)($record->datetime->getTimestamp() * 1_000_000_000); $payload = [ 'streams' => [[ 'stream' => array_merge($this->labels, [ 'level' => $record->level->getName(), 'channel' => $record->channel, ]), 'values' => [[$timestamp, $record->formatted]], ]], ]; $context = stream_context_create(['http' => [ 'method' => 'POST', 'header' => 'Content-Type: application/json', 'content' => json_encode($payload), 'timeout' => 1, ]]); @file_get_contents("{$this->lokiUrl}/loki/api/v1/push", false, $context); } } // config/logging.php 'loki' => [ 'driver' => 'monolog', 'handler' => App\Logging\LokiHandler::class, 'with' => [ 'lokiUrl' => env('LOKI_URL', 'http://loki:3100'), 'labels' => [ 'app' => 'web-app', 'env' => env('APP_ENV', 'production'), ], ], ], 

Пошаговая настройка сбора логов с Laravel

  1. Создайте класс LokiHandler как указано выше.
  2. Зарегистрируйте канал loki в config/logging.php.
  3. Добавьте переменную окружения LOKI_URL в .env.
  4. Проверьте доставку логов через LogQL: {job="laravel-app"}.
  5. При необходимости настройте pipeline_stages для парсинга multi-line исключений.

Как писать запросы LogQL?

LogQL похож на PromQL. Основные паттерны:

# Все ошибки Laravel за последний час {job="laravel-app", level="error"} |= "Exception" # Nginx 5xx {job="nginx"} | json | status >= 500 # Rate ошибок по минутам rate({job="laravel-app", level="error"}[1m]) # Топ медленных запросов (если request_time в логе) {job="nginx"} | regexp `request_time=(?P<rt>[0-9.]+)` | unwrap rt | quantile_over_time(0.95, [5m]) by (path) # Подсчёт ошибок по типу sum by (level) ( count_over_time({job="laravel-app"}[5m]) ) 

Как настроить алерты на рост ошибок?

Создаём правило алерта через provisioning YAML. Пример условия: sum(rate({job="laravel-app", level="error"}[5m])) > 0.1. При превышении порога более 2 минут срабатывает уведомление. Настраивается в grafana/provisioning/alerting/alert_rules.yml. Также добавляем алерт на резкий рост 5xx ошибок Nginx.

Процесс и сроки работы

Этап Что делаем Срок
Аналитика Определяем источники логов, метки, retention 0.5 дня
Проектирование Выбираем конфигурацию Promtail, Loki, datasource 0.5 дня
Реализация Развёртываем стек, настраиваем сбор, дашборды, алерты 0.5 дня
Тестирование Проверяем корректность доставки, работу запросов 0.5 дня
Деплой Передаём документацию, доступы, проводим обучение включено

Итого: 2-3 дня на весь стек. Стоимость рассчитывается индивидуально в зависимости от объёма логов и количества источников. Получите консультацию по вашему проекту — оценим и предложим решение.

Что входит в работу

  • Развёрнутый стек Loki + Promtail + Grafana в Docker Compose или на bare metal.
  • Конфигурация retention, меток и pipeline_stages под ваши источники.
  • Кастомный Monolog-хендлер для Laravel (или аналогичный для других фреймворков).
  • Дашборды в Grafana с визуализацией ошибок, трендов, top endpoints.
  • Правила алертов на рост ошибок, 5xx, медленные запросы.
  • Документация по эксплуатации и восстановлению.
  • Передача доступов и обучение команды (1 час).
  • Гарантия корректной работы стека в течение месяца после деплоя.

Частые проблемы при настройке и их решение

  • Неправильная настройка retention — забывают включить compactor, логи не удаляются. Всегда проверяйте compactor.retention_enabled: true.
  • Отсутствие pipeline_stages — метки не парсятся, сложно фильтровать. Для Laravel обязательно используйте multiline stage.
  • Слишком много меток — каждая новая метка создаёт индекс, замедляя запись. Ограничьте число меток до 5-7 на источник.

Подробнее о логировании читайте на Wikipedia. Закажите настройку и получите консультацию по вашему проекту.