In this post we will be setting up a analytical dashboard using grafana to visualize our nginx access logs.
In this tutorial I will be using my other blog
sysadmins.co.za which is being served on nginx. We will also be setting up the other components such as filebeat, logstash, elasticsearch and redis, which require if you would like to follow along.
The End Result
We will be able to analyze our Nginx Access logs to answer questions such as:
- Whats the Top 10 Countries accessing your website in the last 24 hours
- Who’s the Top 10 Referers?
- Whats the most popular page for the past 24 hours?
- How does the percentage of 200’s vs 404’s look like?
- Ability to view results based on status code
- Everyone loves a World Map to view hotspots
At the end of the tutorial, your dashboard will look similar to this:
High Level Overview
Our infrastructure will require Nginx with Filebeat, Redis, Logstash, Elasticsearch and Grafana and will look like this:
I will drill down how everything is connected:
- Nginx has a custom
log_formatthat we define, that will write to
/var/log/nginx/access_json.log, which will be picked up by Filebeat as a input.
- and Filebeat has an output that pushes the data to Redis
- Logstash is configured with Redis as an input with configured filter section to transform the data and outputs to Elasticsearch
- From Grafana we have a configured Elasticsearch datasource
- Use the grafana template to build this awesome dashboard on Grafana
Let’s build all the things
I will be using LXD to run my system/server containers (running ubuntu 18), but you can use a vps, cloud instance, multipass, virtualbox, or anything to host your servers that we will be deploying redis, logstash, etc.
Servers provisioned for this setup:
For our in-memory data store, I will be securing my redis installation with a password as well.
Generate a password:
In your redis config
/etc/redis/redis.conf, you need to change the following:
1 2 3 4 5 6 7
Restart redis to activate your changes:
and then set and get a key using your password:
1 2 3
On the logstash server, install the requirements:
1 2 3
Now the repository for elastic is setup now we need to update and install logstash:
Once logstash is installed, we need to provide logstash with a configuration, in our scenario we will have a input for redis, a filter section to transform and output as elasticsearch.
Just make sure of the following:
- Populate the connection details of redis (we will define the key in filebeat later)
- Ensure that
GeoLite2-City.mmdbis in the path that I have under filter
- Populate the connectiond details of Elasticsearch and choose a suitable index name, we will need to provide that index name in Grafana later
Create the config:
/etc/logstash/conf.d/logs.conf and my config will look like the following. (config source)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
On our nginx server we will install nginx and filebeat, then configure nginx to log to a custom log format, and configure filebeat to read the logs and push it to redis.
Next we will configure nginx to log to a seperate file with a custom log format to include data such as the, request method, upstream response time, hostname, remote address, etc.
http directive in your
/etc/nginx/nginx.conf, configure the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Restart nginx to activate the changes:
Next we need to configure filebeat to read from our nginx access logs and configure the output to redis. Edit the filebeat config:
And configure filebeat with the following and make sure to change the values where you need to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
When you make a request to your nginx server, you should see a similar logline like below:
On the grafana server, install grafana:
1 2 3 4
Now we need to install a couple of grafana plugins that we require for our dashboards:
1 2 3
Now reload systemd and restart grafana:
If you would like to setup nginx as a reverse proxy to grafana, you can have a look at this blogpost on how to do that.
If you don’t have Prometheus installed already, you can view my blogpost on setting up Prometheus.
To verify if everything works as expected, make a request to your nginx server, then have a look if your index count on elasticsearch increases:
1 2 3
If you dont, make sure that all the processes are running on the servers, and that each server is able to reach each other on the targeted ports.
The Fun Part: Dashboarding
Now that we have everything in place, the fun part is to build the dashboards, first we need to configure elasticsearch as our datasource and specify the index we want to read from. Open grafana on
http://ip.of.grafana.server:3000, default user and password is admin.
Select config on the left and select datasources, add a datasource, select elasticsearch and specify your datasource name, mine is es-nginx in this example, the url of your elasticsearch endpoint, if you have secured your elasticsearch cluster with authentication, provide the auth, then provide your index name as as provided in logstash.
My configured index will look like
logstash-nginx-sysadmins-YYYY-MM-dd, therefore I specified index name as
logstash-nginx-sysadmins-* and my timefield as
@timestamp, the version, and select save and test, which would look like this:
Now we will import our dashboard template (Once again a massive thank you to Shenxiang, Qingkong and Ruixi which made this template available!), head over to dashboards and select import, then provide the ID:
11190, after that it will prompt what your dashboard needs to be named and you need to select your Elasticsearch and Prometheus datasource.
The description of the panels is in Chinese, if you would like it in english, I have translated mine to english and made the dashboard json available in this gist
Tour of our Dashboard Panels
Looking at our hotspot map:
The summary and top 10 pages:
Page views, historical trends:
Top 10 referers and table data of our logs:
I hope this was useful, if you have any issues with this feel free to reach out to me. If you like my work, please feel free to share this post, follow me on Twitter at @ruanbekker or visit me on my website