Centralized Logging Setup with Loki and Grafana

Are logs scattered across servers, turning the search for a failure cause into a long quest? We set up centralized logging with Grafana Loki and Promtail, collecting data in one place. Our team delivers the project turnkey—from configuration to creating user-friendly dashboards—ensuring reliable operation and ongoing support.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1344
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1307
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1050
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1100
  • Website development for SBH Partners
    Website development for SBH Partners
    1171
  • Website development for Red Pear
    Website development for Red Pear
    596

With 7+ years of experience and over 40 production deployments, we deliver robust Loki stacks. Logs scattered across dozens of servers — finding the root cause of a crash turns into a week-long quest. Under peak loads, logs get lost, and searching for an error takes hours. We solve this in a day: set up centralized logging with Grafana Loki and Promtail. Unlike ELK, Loki does not index content, only labels. In practice, this yields up to 70% savings on storage and two to three times less operational overhead. On one project with 50 microservices (10 million requests per day), we reduced time-to-detect from 2 days to 15 minutes. Contact us — we'll complete the setup in 2-3 days. Basic setup cost starts at $500 for the stack (Loki, Promtail, Grafana on Docker; one log source).

Why Loki is Better than Elasticsearch

According to official Grafana Labs data, Loki provides up to 70% storage savings compared to ELK. With 500 GB of logs per day, monthly savings can reach $10,000. Loki stores logs in compressed chunks without an inverted index. Query speed by labels is milliseconds. If you do not need complex aggregation over arbitrary fields, Loki is the right choice. Infrastructure savings can range from $5,000 to $15,000 per month depending on log volume.

Criteria Loki ELK
Storage cost Low (compressed chunks) High (inverted index)
Search speed by labels Fast Medium
Full-text search Limited Full
Operational complexity Low (single binary) High (three stacks)
Grafana integration Native Via plugin

How We Deploy the Stack

We use Docker Compose for rapid deployment. The configuration includes three services:

---
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 Configuration

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 days
  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 Configuration

---
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
Deployment in Kubernetes For Kubernetes, use Helm charts: `helm install loki grafana/loki-stack` — this will deploy Loki, Promtail, and Grafana with default settings. For production, adjust retention, labels, and pipeline_stages via values.yaml.

How to Integrate Laravel with Loki via Monolog

We write a custom Monolog handler that sends log entries to Loki via HTTP API. It works fire-and-forget — does not block the request.

// 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'),
        ],
    ],
],

Step-by-Step Setup for Collecting Laravel Logs

  1. Create the LokiHandler class as shown above.
  2. Register the loki channel in config/logging.php.
  3. Add the LOKI_URL environment variable in .env.
  4. Verify log delivery via LogQL: {job="laravel-app"}.
  5. Optionally configure pipeline_stages for parsing multi-line exceptions.

How to Write LogQL Queries

LogQL is similar to PromQL. Basic patterns:

# All Laravel errors in the last hour
{job="laravel-app", level="error"} |= "Exception"

# Nginx 5xx
{job="nginx"} | json | status >= 500

# Error rate per minute
rate({job="laravel-app", level="error"}[1m])

# Top slow requests (if request_time is in the log)
{job="nginx"} | regexp `request_time=(?P<rt>[0-9.]+)` | unwrap rt | quantile_over_time(0.95, [5m]) by (path)

# Error count by type
sum by (level) ( count_over_time({job="laravel-app"}[5m]) )

How to Set Up Alerts on Error Spikes

Create an alert rule via provisioning YAML. Example condition: sum(rate({job="laravel-app", level="error"}[5m])) > 0.1. The alert fires if threshold exceeded for over 2 minutes. Configured in grafana/provisioning/alerting/alert_rules.yml. Also add an alert on sudden spike of Nginx 5xx errors.

Process and Timelines

Stage What We Do Duration
Analysis Identify log sources, labels, retention 0.5 day
Design Choose Promtail, Loki configuration, datasource 0.5 day
Implementation Deploy stack, configure collection, dashboards, alerts 0.5 day
Testing Verify correct delivery, query functionality 0.5 day
Deployment Deliver documentation, credentials, train team included

Total: 2-3 days for the full stack. Pricing starts at $500 for the basic stack (Loki, Promtail, Grafana on Docker; one log source). Get a consultation on your project — we'll assess and propose a solution.

What's Included

  • Deployed Loki + Promtail + Grafana stack in Docker Compose or on bare metal.
  • Configuration of retention, labels, and pipeline_stages for your sources.
  • Custom Monolog handler for Laravel (or similar for other frameworks).
  • Grafana dashboards visualizing errors, trends, top endpoints.
  • Alert rules on error spikes, 5xx, slow queries.
  • Operations and recovery documentation.
  • Handover and team training (1 hour).
  • One-month warranty of correct stack operation after deployment.

Common Issues and Their Solutions

  • Incorrect retention setup — compactor forgotten, logs not deleted. Always check compactor.retention_enabled: true.
  • Missing pipeline_stages — labels not parsed, filtering difficult. For Laravel, always use multiline stage.
  • Too many labels — each new label creates an index, slowing writes. Limit labels to 5-7 per source.

Learn more about logging on Wikipedia. Order the setup and get a consultation on your project.