Cloud Native 11 min read

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.

Full-Stack DevOps & Kubernetes
Full-Stack DevOps & Kubernetes
Full-Stack DevOps & Kubernetes
Install Loki Locally and Query Nginx Logs with LogQL

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.yaml

Start Loki with the local config:

./loki-linux-amd64 -config.file=loki-local-config.yaml

Collect 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.log

LogQL 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/
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

KubernetesloggingNGINXLokiPromtailLogQL
Full-Stack DevOps & Kubernetes
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.