1. Overview

Nginx is a popular web server that we can also use as a proxy and load balancer. Notably, it has a flexible logging mechanism that outputs incoming HTTP requests to log files. Furthermore, we can define the entry format in the server’s configuration files.

In this tutorial, we’ll learn how we can print variables in the log files by using the access log as an example. In addition, we’ll demonstrate this feature with some sample configurations.

2. The Access Log

The access log file is defined in the configuration files. In Ubuntu systems, the default location is /var/log/nginx/access.log, but it can be set in the nginx.conf file. Let’s send a test request and view the log:

$ curl http://localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
$ tail -n 1 /var/log/nginx/access.log
::1 - - [19/Dec/2022:16:34:00] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0"

As we can see, we sent an HTTP request with curl to get the index page of the Nginx server. In addition, we printed the last line of the access log. Indeed, we can see that our HTTP request was logged.

The access_log directive defines the file path of the access log:

access_log /var/log/nginx/access.log;

This is the default setting of the access log. In particular, we can find this line in the nginx.conf file. We can use the access_log directive in many configuration levels:

  • http
  • server
  • location

Each configuration level inherits the settings of its parent, but it can override them. For example, if we’ve defined an access log in the http block, all child server blocks will output requests to the same path. Nevertheless, a server block can override the parent access log and define its own. In the case above, the server block will output requests only to its access log and will ignore the parent log.

3. The log_format Directive

Nginx defines a default log record format called combined, which includes metadata and remote client information. Optionally, we may also set the record format. The log_format directive defines an entry record format:

log_format alogformat "$time_local $scheme://$host:$server_port$request_uri";

Here, we created a new log format with the name alogformat. We can place the above line in the nginx.conf file inside the http block. The format string consists of the timestamp for the time the request was received and the request URL. We output the request URL using some Nginx predefined variables:

  • $scheme, for example, http or https
  • $host and $port, the host and the port of the request
  • $request_uri, the request path

Until now, we’ve defined a log format string, and we’ve given it a name. To use an entry format, we’ve to assign it to an access log after the access_log directive:

access_log /var/log/nginx/access.log alogformat;

Here, we set our log format to the default access log of our server in the nginx.conf file. To test, we’ve to reload our configuration:

$ sudo nginx -s reload

Now, we’re ready to send an HTTP request and view the log:

$ curl  http://localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
$ tail -n 1 /var/log/nginx/access.log
20/Dec/2022:10:33:36 http://localhost:80/

As expected, we see the modified log record, which uses our custom log format.

4. Nginx Variables

In addition to predefined variables, we can print user-defined variables as well.

First, we can define a variable with the set directive. For instance, let’s create a new server block with two child location blocks in the nginx.conf file:

server {
   listen 8001;
   location /location-a {
      set $location_path 'location-a';
      return 200 "OK\n";
   }
   location /location-b {
      set $location_path 'location-b';
      return 200 "OK\n";
   }
}

In this case, our new virtual server listens to port 8001. There are two location blocks:

  • first matches URLs starting with the /location-a string.
  • second matches URLs starting with the /location-b string

Moreover, we set the value of the user-defined variable $location_path to the location prefix string in both location blocks. Finally, both return the 200 HTTP status code with the OK string.

Furthermore, let’s modify the log format that we created in the previous section:

log_format alogformat "$time_local [location: $location_path] $scheme://$host:$server_port$request_uri";

As can be seen, we’ve added the $location_path variable in brackets so we get the selected location in the access log. Notably, this setting may help us in cases where we want to debug our location configuration.

Following this, we can reload our configuration and test with a URL that matches the first location:

$ sudo nginx -s reload
$ curl  http://localhost:8001/location-a
OK
$ tail -n 1 /var/log/nginx/access.log
20/Dec/2022:11:26:59 [location: location-a] http://localhost:8001/location-a

As we expected, the request matched the location-a location, and the server returned the HTTP status 200 with the OK string. Further, we can verify that we printed the $location_path variable in the brackets to the access log.

Similarly, we can test to match location-b:

$ curl  http://localhost:8001/location-b
OK
$ tail -n 1 /var/log/nginx/access.log
20/Dec/2022:11:34:15 [location: location-b] http://localhost:8001/location-b

Again, we can see that the value of the $location_path variable was location-b. So, we’ve verified that the request matched the location-b location.

5. Conclusion

In this article, we learned how to print a variable’s content to the access log. Firstly, we examined the access_log and log_format directives. Secondly, we demonstrated an example where we modified the default log format. Finally, in the last example, we created a variable and printed its content to the access log.