NGINX is a high-performance and reliable web server, capable of handling huge amounts of traffic for the internet’s busiest websites. When troubleshooting, you need a way to make sense of traffic and NGINX provides flexible logging features to capture valuable details and help you understand the behavior of your web server.
NGINX offers two different files for logging valuable web server data. Those two files are error_log and access_log. access_log is used for storing information about web client requestsand error_log stores other unexpected or informative messages.
Configuring access_log
The access_log file collects all client requests immediately after the request is processed, providing a great way to log which pages users are requesting from your web server. You can choose where the acess_log data is written to using the following configuration file syntax:
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Specifying format allows you to use a custom format in your logs by using variables such as number of bytes sent to the client ($bytes_sent) or the request length ($request_length).
Normally, NGINX will log every transaction it processes in access_log. The if=condition parameter provides a powerful way to perform conditional logging so it only stores log access log messages if some condition is true. For example, if you only want to record requests returning a HTTP 404 status code you can use the following snippet:
map $status $should_log {
404 1;
default 0;
}
access_log logs/access.log combined if=$should_log;
With this change any requests completed successfully (2xx), redirected to another page (3xx) or encountered a server error (5xx) will not be logged in logs/access.log—only 404 errors will be logged.
If you have more than one virtual host or multiple http, server, or location directives thensometimes it’s handy to be able to disable logging for at the current directive level, and the special off value was created for this purpose. The following configuration line shows how you can prevent NGINX from writing access information to any access_log target at the current level:
access_log off;
For a fuller explanation of the configuration options, check out the NGINX access_log documentation.
NGINX Log Severity Levels
NGINX supports a wide range of severity levels to make it easy to log the information you care about. Each of these levels can be used with the error_log directive to set the minimum level at which messages are logged. Here are the supported levels in lowest to highest order, along with a guide on how they’re used:
- Debug – Debugging messages that are not useful most of the time.
- Info – Informational messages that might be good to know.
- Notice – Something normal but significant happened and it should be noted.
- Warn – Something unexpected happened, however it’s not a cause for concern.
- Error – Something failed.
- Crit – A critical condition occurred.
- Alert – Immediate action is required.
- Emerg – The system is unusable.
Configuring error_log
By default, the error_log file captures all log messages at the error severity level which means it’s primarily used for understanding fatal or critical messages to help with troubleshooting. The default location for error_log is logs/error.log. The way NGINX stores error messages is flexible and—along with allowing you to write messages to a file—it also supports sending error_log messages to stderr or the syslog daemon. If you’re running NGINX open source 1.5.2 or newer, you can also send error_log messages to more than one place at a time by specifying multiple error_log directives on the same configuration level.
If you want to log all messages at or above the warn log severity make the following configuration change:
error_log logs/error.log warn;
Logging to Syslog With NGINX
Both the access_log and error_log directives support sending messages to a syslog daemon by using the syslog: string in your configuration. The following snippet shows the syntax for using either of the directives with a syslog daemon:
http {
error_log syslog:server[,facility=][,tag=][,severity=];
…
}
For example, if you want to direct all error_log messages with warn or higher severity to the syslog daemon use this directive line:
error_log syslog:server=192.168.1.1 severity=warn;
You can further customize the syslog configuration to suit your environment by using the syslog parameter described in the NGINX syslog documentation.
Frustration-free log management. (It’s a thing.)
Aggregate, organize, and manage your logs with PapertrailThings to Watch Out For
The flexibility NGINX logging provides comes at a cost, and there are some things to watch out for when writing your configuration file. We’ve already covered NGINX’s ability to override logging configurations at the directive level, and this feature is extremely useful for logging extra information whenever users access specific paths, e.g., logging extra traffic information for any users accessing the /private URI. However, using nested access logs can quickly become complex and you should be careful not to use this feature too much.
Writing access_log entries to a file on disk can degrade server performance and increase the response latency for user requests. For web servers needing to maintain high performance, NGINX provides a way to write log messages to a cyclic buffer in memory, completely bypassing the disk. Extracting these logs is more involved than reading a file, so you should only use this if performance is critical for your workload.
To use this feature, your version of NGINX needs to be configured using the—with-debug option. You can check if this is the case by doing this:
$ nginx -V 2>&1 | grep—‘—with-debug’
configure arguments: --with-debug
Inside the configuration file you can enable writing log entries to memory with the following snippet:
error_log memory:32m debug;
...
http {
...
}
This will write all log messages at the debug level. Extracting the log messages from memory involves using gdb to connect to the NGINX process and copy and paste the following script at the prompt:
set $log = ngx_cycle->log
while $log->writer != ngx_log_memory_writer
set $log = $log->next
end
set $buf = (ngx_log_memory_buf_t *) $log->wdata
dump binary memory debug_log.txt $buf->start $buf->end
Then quit GDB using Ctrl-D. The above script will write the contents of memory to the debug_log.txt file where you can read it like normal.
Conclusion
NGINX allows you to collect logs for both routine accesses and unexpected errors into separate files for later analysis and troubleshooting. The format of the access_log file can be extensively customized to include detailed information about requests such as the number of bytes sent to the client or the request length, and the error_log directive allows you to control the minimum severity level required for messages to be logged. Both the access_log and error_log directives can transmit log entries to a syslog daemon, which can be extremely handy for developers working with multiple web servers.
And if all of those features aren’t enough for you, you can even write error_log entries to a memory buffer to avoid writing to disk and reduce the performance impact for busy servers.