LogQL Basics
LogQL is Loki's query language. It is modeled after PromQL and uses a pipeline syntax — start with a stream selector, then chain filter and parse expressions. LogQL has two query types: log queries (return log lines) and metric queries (return time series computed from logs).
Query Types
Log Queries
Return matching log lines with timestamp and labels. Used in Grafana Logs panels and Explore. Always start with a stream selector.
Metric Queries
Compute time series from log data — e.g., count log entries per minute, extract numeric values from log lines. Used in Grafana Time Series panels and alert rules.
Stream Selectors
A stream selector is mandatory. It matches log streams by their labels. Without a stream selector, Loki would have to scan all logs — which is not allowed.
# Exact match — most efficient
{job="processengine"}
# Multiple labels — AND logic
{job="processengine", environment="production", level="error"}
# Regex match on label value
{job=~"processengine|edgestream"}
# Negative match
{job="processengine", level!="debug"}
Filter Expressions
After the stream selector, apply filters to narrow down log lines within the matched streams:
# Contains substring (case-sensitive)
{job="processengine"} |= "execution failed"
# Does not contain
{job="processengine"} != "health check"
# Regex match
{job="processengine"} |~ "error|exception|fail"
# Case-insensitive regex
{job="processengine"} |~ "(?i)timeout"
# Multiple filters (AND logic — both must match)
{job="processengine"} |= "error" |= "DataFetchNode"
Parsing Expressions
Parse log line content into structured fields for further filtering or metric extraction:
# JSON parser — extract fields from JSON log lines
{job="processengine"} | json
# After JSON parsing, filter on extracted fields
{job="processengine"} | json | level="error" | nodeType="DataFetchNode"
# Pattern parser — extract by positional pattern
{job="processengine"} | pattern "<timestamp> <level> <message>"
# Logfmt parser — for key=value format logs
{job="legacy-service"} | logfmt | level="error"
# Line format — reshape the output
{job="processengine"} | json | line_format "{{.level}}: {{.message}} [{{.executionId}}]"
Metric Queries
# Count log lines per minute
count_over_time({job="processengine"}[1m])
# Rate of error logs per second (for alerting)
rate({job="processengine"} | json | level="error" [5m])
# Sum error rate across all tenants
sum(rate({job="processengine", level="error"}[5m])) by (tenant_id)
# P50 of a numeric field extracted from logs
quantile_over_time(0.5, {job="processengine"} | json | unwrap duration_ms [5m])
# Log volume per level over time
sum(count_over_time({job="processengine"}[5m])) by (level)
Time Range Syntax
| Range | Meaning | Use Case |
|---|---|---|
[1m] | Last 1 minute | High-frequency alerting |
[5m] | Last 5 minutes | Standard alert smoothing window |
[15m] | Last 15 minutes | Trend detection |
[1h] | Last 1 hour | Hourly dashboard panels |
[24h] | Last 24 hours | Daily aggregates |
Grafana's Explore view provides LogQL autocomplete — press Ctrl+Space to see available labels and values. The label browser on the left panel lets you click to build a stream selector without typing. For learning LogQL, start in Explore with the autocomplete — it also validates your query syntax in real-time.