Install Loki Locally and Query Nginx Logs with LogQL
This guide walks through installing Loki and Promtail in local mode, configuring Nginx to emit JSON logs, adjusting Promtail settings, and using LogQL’s JSON extraction (with and without parameters) to build queries that count successful Nginx requests over a selectable time range.
Install Loki (Local mode)
Visit the Loki release page: https://github.com/grafana/loki/releases/ and select a version (e.g., v2.1.0).
Download the Loki binary and the Promtail binary; Loki is the log engine, Promtail ships logs to Loki.
Create a directory on the host to store the two binaries.
Download the default configuration files:
wget https://raw.githubusercontent.com/grafana/loki/master/cmd/loki/loki-local-config.yaml
wget https://raw.githubusercontent.com/grafana/loki/master/cmd/promtail/promtail-local-config.yamlStart Loki with the local config:
./loki-linux-amd64 -config.file=loki-local-config.yamlCollect Nginx logs
Modify the default Nginx access log to output JSON and store it in a dedicated directory, then let Promtail read that file.
server {
server_name loki.test.com; # domain
listen 8888;
access_log /var/log/nginx/loki_access.log promtail_json;
location / {
return 200 "It's ok!";
}
}Define a JSON log format named promtail_json:
log_format promtail_json '{"@timestamp":"$time_iso8601","@version":"Promtail json","server_addr":"$server_addr","remote_addr":"$remote_addr","host":"$host","uri":"$uri","body_bytes_sent":$body_bytes_sent,"bytes_sent":$body_bytes_sent,"request":"$request","request_length":$request_length,"request_time":$request_time,"status":"$status","http_referer":"$http_referer","http_user_agent":"$http_user_agent"}';After reloading Nginx, a sample log entry looks like:
{"@timestamp":"2021-03-06T01:54:42-05:00","@version":"Promtail json","server_addr":"127.0.0.1","remote_addr":"192.168.65.130","host":"127.0.0.1","uri":"/","body_bytes_sent":8,"bytes_sent":8,"request":"GET / HTTP/1.1","request_length":78,"request_time":0.000,"status":"200","http_referer":"-","http_user_agent":"curl/7.29.0"}Promtail configuration
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/loki-positions.yaml # record read positions
sync_period: 5s # sync every 5 seconds
clients:
- url: http://localhost:3100/loki/api/v1/push
scrape_configs:
- job_name: Loki
static_configs:
- labels:
job: Loki-nginx
host: localhost
app: nginx
__path__: /var/log/nginx/loki_access.logLogQL JSON extraction
LogQL can extract JSON fields using the |json operator. Two modes exist:
Without parameters : |json parses the entire JSON payload. Nested keys are flattened with an underscore (e.g., request_method), and arrays are ignored.
With parameters : |json label="expr", another="expr" extracts only the specified fields, reducing processing overhead. Multiple parameters are allowed.
Example without parameters (simplified output):
"protocol" => "HTTP/2.0"
"request_time" => "6.032"
"request_method" => "GET"
"request_host" => "foo.grafana.net"
"request_size" => "55"
"response_status" => "401"
"response_size" => "228"Example with parameters:
"first_server" => "129.0.1.1"
"ua" => "curl/7.68.0"Writing a LogQL expression
A complete LogQL query consists of two parts:
A log stream selector that matches logs by label (e.g., {job="Loki-nginx"}).
A log pipeline that processes the selected logs (e.g., | json | status = 200).
Sample pipeline that filters Nginx logs with status 200 and counts them over the current interval:
sum(count_over_time({job="Loki-nginx"} | json | status = 200 __error__="" [$__interval]))Step‑by‑step query construction
Select the Nginx logs: {job="Loki-nginx"}.
Parse the JSON payload: | json.
Filter for status = 200. Because status is a string, add __error__="" to silence conversion errors.
Apply count_over_time with the built‑in interval variable [$__interval] to count entries in the chosen time window.
Wrap the count with sum to collapse multiple series into a single number for Grafana panels.
The final expression is:
sum(count_over_time({job="Loki-nginx"} | json | status = 200 __error__="" [$__interval]))Original article: https://kirakirazone.com/2021/03/06/Loki%E6%97%A5%E5%BF%97%E6%9C%8D%E5%8A%A101/
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack DevOps & Kubernetes
Focused on sharing DevOps, Kubernetes, Linux, Docker, Istio, microservices, Spring Cloud, Python, Go, databases, Nginx, Tomcat, cloud computing, and related technologies.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
