Loki & LogQL
New here? Start with the Quickstart to launch Icelake + Grafana locally and wire up the Loki datasource in 5 minutes.
Overview
Section titled “Overview”Icelake implements the Loki push API for log ingestion and supports LogQL for querying. This makes it a drop-in replacement for Grafana Loki with S3-native storage.
Getting Started
Section titled “Getting Started”1. Configure Log Shipping
Section titled “1. Configure Log Shipping”Send logs to Icelake using the Loki push API endpoint. Authentication is HTTP Basic auth — username is your client ID, password is your API key (ilk_…):
# Loki Push API endpointPOST https://api.icelake.eu/loki/api/v1/push
# Authentication header (Basic base64("client_id:api_key"))Authorization: Basic <base64>2. Fluent Bit Configuration
Section titled “2. Fluent Bit Configuration”Configure Fluent Bit to ship logs to Icelake:
[OUTPUT] Name loki Match * Host api.icelake.eu Port 443 URI /loki/api/v1/push Labels job=fluent-bit HTTP_User your-client-id HTTP_Passwd ilk_your-api-key-here TLS on3. Grafana Logs Drilldown
Section titled “3. Grafana Logs Drilldown”Add Icelake as a Loki datasource in Grafana:
Name: Icelake LogsType: LokiURL: https://api.icelake.eu/lokiAuthentication: Basic auth User: your-client-id Password: ilk_your-api-key-hereLogQL Query Reference
Section titled “LogQL Query Reference”Stream Selectors
Section titled “Stream Selectors”Filter logs by label matchers:
# Exact match{service="api-gateway"}
# Regex match{service=~"api-.*"}
# Not equal{service!="debug"}
# Multiple labels{service="api-gateway", environment="production"}Line Filters
Section titled “Line Filters”Further filter log lines by content:
# Contains string{service="api-gateway"} |= "error"
# Does not contain{service="api-gateway"} != "debug"
# Regex match on line{service="api-gateway"} |~ "status=[45]\\d{2}"Aggregations
Section titled “Aggregations”Aggregate log data for dashboards:
# Count logs per service over 5 minutescount_over_time({job="fluent-bit"}[5m])
# Rate of error logsrate({service="api-gateway"} |= "error" [1m])
# Top 10 services by log volumetopk(10, sum by(service) (rate({job="fluent-bit"}[5m])))Log Format
Section titled “Log Format”Logs are stored as Parquet files on S3:
s3://icelake-data/└── logs/ └── tenant=default/ ├── 2026/02/20/ │ ├── logs_001.parquet │ └── compacted_001.parquet └── 2026/02/21/ └── logs_001.parquetEach Parquet file contains:
| Column | Type | Description |
|---|---|---|
| timestamp | INT64 | Unix nanoseconds |
| message | STRING | Log line content |
| labels | MAP | Key-value label pairs |
| tenant_id | STRING | Tenant identifier |
Loki Push API Format
Section titled “Loki Push API Format”Send logs in the Loki JSON format:
{ "streams": [ { "stream": { "service": "api-gateway", "environment": "production" }, "values": [ ["1708000000000000000", "GET /api/health 200 12ms"], ["1708000001000000000", "POST /api/data 201 45ms"] ] } ]}Query API Endpoints
Section titled “Query API Endpoints”| Endpoint | Method | Description |
|---|---|---|
/loki/api/v1/push | POST | Ingest log streams |
/loki/api/v1/query | GET | Instant LogQL query |
/loki/api/v1/query_range | GET | Range LogQL query |
/loki/api/v1/labels | GET | List label names |
/loki/api/v1/label/<name>/values | GET | List label values |
Best Practices
Section titled “Best Practices”Performance Tip: Use structured logging with consistent label schemas for optimal query performance.
- Keep label cardinality low (avoid unique IDs as labels)
- Use line filters to narrow down results before aggregations
- Set appropriate retention policies per tenant
- Configure compaction for log-heavy workloads
Related docs
Section titled “Related docs”- Quickstart — end-to-end Icelake + Grafana setup in 5 minutes
- OpenTelemetry — alternative path if you’re standardising on OTLP
- Query Interfaces — Grafana, pgwire SQL, REST, and the Loki Query API