LogQL
Loki's query language. Pick log streams by label, filter lines, parse out fields, and turn matching lines into counts you can graph and alert on.
#What it is
LogQL is how you ask Loki questions, usually from Grafana's Explore view in Code mode. If you've used Splunk's SPL, the shape will feel familiar: choose the data, filter it, extract fields, then aggregate.
#The building blocks
- Stream selector:
{job="pihole"}picks which logs to read. Always first. - Line filter:
|= "gravity blocked"keeps lines containing the text (!=excludes,|~is regex). - Parser:
| jsonfor JSON lines, or| regexpwith named groups like(?P<domain>\S+)for plain text, pulls fields out of each line. - Label filter:
| src_host != ""filters on an extracted field. - Metric query: wrap it in
count_over_time(... [24h]), then aggregate withsum by (field)ortopk(10, ...).
#Queries I actually use
# Everything Pi-hole blocked
{job="pihole"} |= "gravity blocked"
# Top 10 blocked domains, last 24h
topk(10, sum by (domain) (count_over_time({job="pihole"} |= "gravity blocked" | regexp `gravity blocked (?P<domain>\S+)` [24h])))
# Who is asking for what
{job="pihole"} |= "query[" | regexp `query\[(?P<qtype>\w+)\] (?P<domain>\S+) from (?P<client>\S+)`
# Honeypot hits (skips startup noise)
{job="opencanary"} | json | src_host != ""The last one, turned into a count over two minutes, is the whole honeypot alert rule:
sum by (src_host, dst_port) (count_over_time({job="opencanary"} | json | src_host != "" [2m]))#Tips
- Turn Live off and set a time range while writing queries.
- Filter lines (
|=) before parsing. It's much cheaper to throw lines away early.