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 1 pre-built dashboard to help monitor and visualize Nginx metrics and logs.

Grafana Alloy configuration

Before you begin

For the integration to work, you must configure a custom JSON access log in the Nginx configuration:

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 geoip_country_code to the access log:

<snip>
'"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;

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 dashboard 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, copy and paste the snippets to your configuration file and follow subsequent instructions.

Advanced logs snippets

darwin

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

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

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

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

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

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 configuration

Before you begin

For the integration to work, you must configure a custom JSON access log in the Nginx configuration:

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 geoip_country_code to the access log:

<snip>
'"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;

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 dashboard to your Grafana Cloud instance, and you can start monitoring your Nginx setup.

Post-install configuration for the Nginx integration

After enabling the JSON-formatted access log generation, instruct Grafana Agent to scrape it.

To scrape it, add the provided snippet to your agent configuration file.

The agent must have local access to the log file. Alternatively, it may be configured to fetch logs from Kubernetes using a kubernetes_sd_config.

Make sure to change the host label to a value that reflects your environment. It will be used to filter this instance in the dashboard.

Configuration snippets for Grafana Agent

Below logs.configs.scrape_configs, insert the following lines according to your environment.

yaml
    - job_name: integrations/nginx
      static_configs:
      - targets:
        - localhost
        labels:
          host: <http_hostname>
          __path__: <path to json nginx access log>
          instance: '<your-instance-name>'

Full example configuration for Grafana Agent

Refer to the following Grafana Agent configuration for a complete example that contains all the snippets used for the Nginx integration. This example also includes metrics that are sent to monitor your Grafana Agent instance.

yaml
integrations:
  prometheus_remote_write:
  - basic_auth:
      password: <your_prom_pass>
      username: <your_prom_user>
    url: <your_prom_url>
  agent:
    enabled: true
    relabel_configs:
    - action: replace
      source_labels:
      - agent_hostname
      target_label: instance
    - action: replace
      target_label: job
      replacement: "integrations/agent-check"
    metric_relabel_configs:
    - action: keep
      regex: (prometheus_target_sync_length_seconds_sum|prometheus_target_scrapes_.*|prometheus_target_interval.*|prometheus_sd_discovered_targets|agent_build.*|agent_wal_samples_appended_total|process_start_time_seconds)
      source_labels:
      - __name__
  # Add here any snippet that belongs to the `integrations` section.
  # For a correct indentation, paste snippets copied from Grafana Cloud at the beginning of the line.
logs:
  configs:
  - clients:
    - basic_auth:
        password: <your_loki_pass>
        username: <your_loki_user>
      url: <your_loki_url>
    name: integrations
    positions:
      filename: /tmp/positions.yaml
    scrape_configs:
      # Add here any snippet that belongs to the `logs.configs.scrape_configs` section.
      # For a correct indentation, paste snippets copied from Grafana Cloud at the beginning of the line.
    - job_name: integrations/nginx
      static_configs:
      - targets:
        - localhost
        labels:
          host: <http_hostname>
          __path__: <path to json nginx access log>
          instance: '<your-instance-name>'
metrics:
  configs:
  - name: integrations
    remote_write:
    - basic_auth:
        password: <your_prom_pass>
        username: <your_prom_user>
      url: <your_prom_url>
    scrape_configs:
      # Add here any snippet that belongs to the `metrics.configs.scrape_configs` section.
      # For a correct indentation, paste snippets copied from Grafana Cloud at the beginning of the line.
  global:
    scrape_interval: 60s
  wal_directory: /tmp/grafana-agent-wal

Dashboards

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

  • Loki NGINX Service Mesh - JSON version

Changelog

md
# 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.