Menu
Grafana Cloud

Nginx integration for Grafana Cloud

NGINX is open source software for web serving, reverse proxying, caching, load balancing, media streaming, and more. It started out as a web server designed for maximum performance and stability. In addition to its HTTP server capabilities, NGINX can also function as a proxy server for email (IMAP, POP3, and SMTP) and a reverse proxy and load balancer for HTTP, TCP, and UDP servers.

This integration includes 2 pre-built dashboards to help monitor and visualize Nginx metrics and logs.

Before you begin

For this integration to work, you must first configure a custom JSON access log in the NGINX configuration, as well as enable the Stub Status Module and configure the nginx-prometheus-exporter.

First, to enable the logging, place the following configuration within the http block, by the # Logging Settings line:

log_format json_analytics escape=json '{'
'"msec": "$msec", ' # request unixtime in seconds with a milliseconds resolution
'"connection": "$connection", ' # connection serial number
'"connection_requests": "$connection_requests", ' # number of requests made in connection
'"pid": "$pid", ' # process pid
'"request_id": "$request_id", ' # the unique request id
'"request_length": "$request_length", ' # request length (including headers and body)
'"remote_addr": "$remote_addr", ' # client IP
'"remote_user": "$remote_user", ' # client HTTP username
'"remote_port": "$remote_port", ' # client port
'"time_local": "$time_local", '
'"time_iso8601": "$time_iso8601", ' # local time in the ISO 8601 standard format
'"request": "$request", ' # full path no arguments if the request
'"request_uri": "$request_uri", ' # full path and arguments if the request
'"args": "$args", ' # args
'"status": "$status", ' # response status code
'"body_bytes_sent": "$body_bytes_sent", ' # the number of body bytes exclude headers sent to a client
'"bytes_sent": "$bytes_sent", ' # the number of bytes sent to a client
'"http_referer": "$http_referer", ' # HTTP referer
'"http_user_agent": "$http_user_agent", ' # user agent
'"http_x_forwarded_for": "$http_x_forwarded_for", ' # http_x_forwarded_for
'"http_host": "$http_host", ' # the request Host: header
'"server_name": "$server_name", ' # the name of the vhost serving the request
'"request_time": "$request_time", ' # request processing time in seconds with msec resolution
'"upstream": "$upstream_addr", ' # upstream backend server for proxied requests
'"upstream_connect_time": "$upstream_connect_time", ' # upstream handshake time incl. TLS
'"upstream_header_time": "$upstream_header_time", ' # time spent receiving upstream headers
'"upstream_response_time": "$upstream_response_time", ' # time spent receiving upstream body
'"upstream_response_length": "$upstream_response_length", ' # upstream response length
'"upstream_cache_status": "$upstream_cache_status", ' # cache HIT/MISS where applicable
'"ssl_protocol": "$ssl_protocol", ' # TLS protocol
'"ssl_cipher": "$ssl_cipher", ' # TLS cipher
'"scheme": "$scheme", ' # http or https
'"request_method": "$request_method", ' # request method
'"server_protocol": "$server_protocol", ' # request protocol, like HTTP/1.1 or HTTP/2.0
'"pipe": "$pipe", ' # "p" if request was pipelined, "." otherwise
'"gzip_ratio": "$gzip_ratio"'
'}';

access_log /var/log/nginx/json_access.log json_analytics;

To use country mapping, you must enable the GeoIP2 module, and add the relevant geoip_country_code configuration to the access log, replacing the last few lines of the previous snippet with the following, starting at "gzip_ratio":

'"gzip_ratio": "$gzip_ratio", '
'"geoip_country_code": "$geoip_country_code"'
'}';

geoip_country /etc/nginx/GeoLite2-Country.mmdb {
  $geoip_country_code default=US source=$remote_addr country iso_code;
}

access_log /var/log/nginx/json_access.log json_analytics;

Then, to enable scraping metrics from your NGINX instance, enable the Stub Status Module in your NGINX configuration.

server {
  listen 127.0.0.1:8080;
  server_name localhost;

  location /stub_status {
    stub_status on;
    # Optionally restrict access to IP addresses if needed
    # allow 127.0.0.1;
    # deny all;
  }
}

The nginx-prometheus-exporter should then be configured to scrape NGINX. Adjust the stub_status module as required for your environment.

Install Nginx integration for Grafana Cloud

  1. In your Grafana Cloud stack, click Connections in the left-hand menu.
  2. Find Nginx and click its tile to open the integration.
  3. Review the prerequisites in the Configuration Details tab and set up Grafana Agent to send Nginx metrics and logs to your Grafana Cloud instance.
  4. Click Install to add this integration’s pre-built dashboards to your Grafana Cloud instance, and you can start monitoring your Nginx setup.

Configuration snippets for Grafana Alloy

Advanced mode

The following snippets provide examples to guide you through the configuration process.

To instruct Grafana Alloy to scrape your Nginx instances, manually copy and append the snippets to your alloy configuration file, then follow subsequent instructions.

Advanced metrics snippets

alloy
discovery.relabel "metrics_integrations_integrations_nginx" {
	targets = [{
		__address__  = "localhost:9113",
	}]

	rule {
		target_label = "instance"
		replacement  = constants.hostname
	}
}

prometheus.scrape "metrics_integrations_integrations_nginx" {
  targets    = discovery.relabel.metrics_integrations_integrations_nginx.output
  forward_to = [prometheus.remote_write.metrics_service.receiver]
  job_name   = "integrations/nginx"
}

To monitor your NGINX instance, you must use a discovery.relabel component to discover your nginx-prometheus-exporter endpoint and apply appropriate labels, followed by a prometheus.scrape component to scrape it.

Configure the following properties within each discovery.relabel component:

  • __address__: The address to your NGINX Prometheus exporter metrics endpoint.
  • instance label: constants.hostname sets the instance label to your Grafana Alloy server hostname. If that is not suitable, change it to a value uniquely identifies this NGINX instance.

If you have multiple NGINX servers to scrape, configure one discovery.relabel for each and scrape them by including each under targets within the prometheus.scrape component.

Advanced logs snippets

darwin

alloy
local.file_match "logs_integrations_integrations_nginx" {
	path_targets = [{
		__address__ = "localhost",
		__path__    = "<path to json nginx access log>",
		host        = "<http_hostname>",
		instance    = constants.hostname,
		job         = "integrations/nginx",
	}]
}

loki.source.file "logs_integrations_integrations_nginx" {
	targets    = local.file_match.logs_integrations_integrations_nginx.targets
	forward_to = [loki.write.grafana_cloud_loki.receiver]
}

To monitor your Nginx instance logs, you will use a combination of the following components:

  • local.file_match defines where to find the log file to be scraped. Change the following properties according to your environment:

    • __address__: The Nginx instance address
    • __path__: The path to the log file.
    • instance label: constants.hostname sets the instance label to your Grafana Alloy server hostname. If that is not suitable, change it to a value uniquely identifies this Nginx instance.
  • loki.source.file sends logs to Loki.

linux

alloy
local.file_match "logs_integrations_integrations_nginx" {
	path_targets = [{
		__address__ = "localhost",
		__path__    = "<path to json nginx access log>",
		host        = "<http_hostname>",
		instance    = constants.hostname,
		job         = "integrations/nginx",
	}]
}

loki.source.file "logs_integrations_integrations_nginx" {
	targets    = local.file_match.logs_integrations_integrations_nginx.targets
	forward_to = [loki.write.grafana_cloud_loki.receiver]
}

To monitor your Nginx instance logs, you will use a combination of the following components:

  • local.file_match defines where to find the log file to be scraped. Change the following properties according to your environment:

    • __address__: The Nginx instance address
    • __path__: The path to the log file.
    • instance label: constants.hostname sets the instance label to your Grafana Alloy server hostname. If that is not suitable, change it to a value uniquely identifies this Nginx instance.
  • loki.source.file sends logs to Loki.

windows

alloy
local.file_match "logs_integrations_integrations_nginx" {
	path_targets = [{
		__address__ = "localhost",
		__path__    = "<path to json nginx access log>",
		host        = "<http_hostname>",
		instance    = constants.hostname,
		job         = "integrations/nginx",
	}]
}

loki.source.file "logs_integrations_integrations_nginx" {
	targets    = local.file_match.logs_integrations_integrations_nginx.targets
	forward_to = [loki.write.grafana_cloud_loki.receiver]
}

To monitor your Nginx instance logs, you will use a combination of the following components:

  • local.file_match defines where to find the log file to be scraped. Change the following properties according to your environment:

    • __address__: The Nginx instance address
    • __path__: The path to the log file.
    • instance label: constants.hostname sets the instance label to your Grafana Alloy server hostname. If that is not suitable, change it to a value uniquely identifies this Nginx instance.
  • loki.source.file sends logs to Loki.

Grafana Agent static configuration (deprecated)

The following section shows configuration for running Grafana Agent in static mode which is deprecated. You should use Grafana Alloy for all new deployments.

Dashboards

The Nginx integration installs the following dashboards in your Grafana Cloud instance to help monitor your system.

  • NGINX Logs
  • NGINX Overview

Metrics

The most important metrics provided by the Nginx integration, which are used on the pre-built dashboards, are as follows:

  • nginx_connections_accepted
  • nginx_connections_active
  • nginx_connections_handled
  • nginx_connections_reading
  • nginx_connections_waiting
  • nginx_connections_writing
  • nginx_http_requests_total
  • nginx_up
  • up

Changelog

md
# 1.1.2 - November 2024

- Add missing metrics scrape snippet

# 1.1.1 - November 2024

- Update status panel check queries

# 1.1.0 - October 2024

* Update mixin to latest
  * Add metric dashboard based on nginx-prometheus-exporter
* Update Alloy scrape config

# 1.0.1 - August 2024

* Update mixin to latest
  * Update queries to use `$__interval` instead of hardcoded time ranges

# 1.0.0 - June 2024

* Update mixin to latest
  * Update all `cluster` queries to be conditional
  * Remove news panel
* Update installation instructions
* Add missing job label to Alloy snippet

# 0.0.5 - September 2023

* New Filter Metrics option for configuring the Grafana Agent, which saves on metrics cost by dropping any metric not used by this integration. Beware that anything custom built using metrics that are not on the snippet will stop working.

# 0.0.4 - August 2023

* Add regex filter for logs datasource

# 0.0.3 - July 2023

* Update mixin to latest version:
  - Add cluster variable to support Kubernetes clusters
* Added Grafana Agent Operator configuration snippet to support nginx in a Kubernetes cluster.

# 0.0.2 - September 2022

* Update mixin to latest version:
  - Update queries to use $__rate_interval

# 0.0.1 - May 2021

* Initial release

Cost

By connecting your Nginx instance to Grafana Cloud, you might incur charges. To view information on the number of active series that your Grafana Cloud account uses for metrics included in each Cloud tier, see Active series and dpm usage and Cloud tier pricing.