Operations 8 min read

Quickly Visualize Nginx Access Logs with Loki and Grafana

This guide shows how to collect Nginx access logs, convert them to JSON, store them in Loki, and create real‑time dashboards in Grafana, covering installation, configuration, Docker deployment, and required plugins for a complete monitoring solution.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Quickly Visualize Nginx Access Logs with Loki and Grafana

A client needed to view website access statistics without using Google or Baidu analytics, so the solution is to collect Nginx logs and display them via Loki and Grafana.

For a small site, the stack chosen is

Nginx + Promtail + Loki + Grafana

.

Promtail and Loki are installed by downloading the appropriate binary files, extracting them, and starting them with a configuration file.

<code>server:
  http_listen_port: 9080
  grpc_listen_port: 0
positions:
  filename: /tmp/positions.yaml
clients:
  - url: http://localhost:3100/loki/api/v1/push
scrape_configs:
  - job_name: nginx
    pipeline_stages:
      - replace:
          expression: '(?:[0-9]{1,3}\.){3}([0-9]{1,3})'
          replace: '***'
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx_access_log
          host: expatsxxxxs
          agent: promtail
          __path__: /var/log/nginx/expatshxxxxs.access.log</code>

The Nginx log format is changed to JSON to make it compatible with Loki:

<code>log_format json_analytics escape=json '{'
  "msec": "$msec",
  "connection": "$connection",
  "connection_requests": "$connection_requests",
  "pid": "$pid",
  "request_id": "$request_id",
  "request_length": "$request_length",
  "remote_addr": "$remote_addr",
  "remote_user": "$remote_user",
  "remote_port": "$remote_port",
  "time_local": "$time_local",
  "time_iso8601": "$time_iso8601",
  "request": "$request",
  "request_uri": "$request_uri",
  "args": "$args",
  "status": "$status",
  "body_bytes_sent": "$body_bytes_sent",
  "bytes_sent": "$bytes_sent",
  "http_referer": "$http_referer",
  "http_user_agent": "$http_user_agent",
  "http_x_forwarded_for": "$http_x_forwarded_for",
  "http_host": "$http_host",
  "server_name": "$server_name",
  "request_time": "$request_time",
  "upstream": "$upstream_addr",
  "upstream_connect_time": "$upstream_connect_time",
  "upstream_header_time": "$upstream_header_time",
  "upstream_response_time": "$upstream_response_time",
  "upstream_response_length": "$upstream_response_length",
  "upstream_cache_status": "$upstream_cache_status",
  "ssl_protocol": "$ssl_protocol",
  "ssl_cipher": "$ssl_cipher",
  "scheme": "$scheme",
  "request_method": "$request_method",
  "server_protocol": "$server_protocol",
  "pipe": "$pipe",
  "gzip_ratio": "$gzip_ratio",
  "http_cf_ray": "$http_cf_ray",
  "geoip_country_code": "$geoip_country_code"
}';</code>

Because the JSON log format uses the GeoIP module, the required packages are installed with:

<code>yum -y install GeoIP GeoIP-data GeoIP-devel</code>

Nginx is then recompiled with the

--with-http_geoip_module

flag and reloaded using

kill -USR2

. After recompilation, the new

log_format

works without errors.

Sample JSON log entries are shown to confirm correct formatting.

Grafana is deployed quickly via Docker:

<code>docker run -d -p 3000:3000 grafana/grafana</code>

After logging in with the default admin/admin credentials and resetting the password, a Loki data source is added.

Using Grafana’s Explore view confirms that logs are being stored in Loki.

A dashboard is imported by ID, but the world‑map panel is missing, so the required plugin is installed:

<code>grafana-cli plugins install grafana-worldmap-panel</code>

Grafana is restarted, and the dashboard now displays the map (external map images may need a reverse proxy to load).

In summary, combining Loki and Grafana provides a fast and effective way to present detailed website access information.

DockerNginxGrafanaLog MonitoringLokiPromtail
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

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