nginxnginx-config

Why nginx log rotation works on access but not on error log


I know that I can use logrotate to rotate the logs of NGINX, but for me it represents an additional configuration file to deploy, so if it can be avoided its better...

I found some answers to include the date on nginx logs:

http {

    map $time_iso8601 $year {
        default '0000';
        "~^(\d{4})-(\d{2})-(\d{2})" $1;
    }
    map $time_iso8601 $month {
        default '00';
        "~^(\d{4})-(\d{2})-(\d{2})" $2;
    }

    error_log  /var/log/nginx/error.$year-$month.log;
    access_log  /var/log/nginx/access.$year-$month.log;

}

or

server {

    if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})") {
        set $year $1;
        set $month $2;
        set $day $3;
    }

    access_log  /home/site1/data/logs/access.$year-$month.log;
    error_log   /home/site1/data/logs/error.$year-$month.log;

}

and it actually works for the access_log, but for the error log it just don't work.. For the error log I always get error.$year-$month.log as filename, even if it is defined before the access log.

Is there any work around to solve this?

Thank you


Solution

  • A general guideline for nginx documentation is that if a directive allows the use of variables in its parameter(s), this will be explicitly mentioned in the directive’s description.

    The access_log directive documentation explicitly states this, but I suggest you to read the relevant documentation section carefully:

    The file path can contain variables (0.7.6+), but such logs have some constraints:

    • the user whose credentials are used by worker processes should have permissions to create files in a directory with such logs;
    • buffered writes do not work;
    • the file is opened and closed for each log write. However, since the descriptors of frequently used files can be stored in a cache, writing to the old file can continue during the time specified by the open_log_file_cache directive’s valid parameter
    • during each log write the existence of the request’s root directory is checked, and if it does not exist the log is not created. It is thus a good idea to specify both root and access_log on the same configuration level:
      server {
          root       /spool/vhost/data/$host;
          access_log /spool/vhost/logs/$host;
          ...
      

    Given the above, I do not recommend using variables in the access log filename. You'd better configure logrotate utility to rotate logs at the beginning of each month and add date information to the archived log files.

    In contrast to access_log, the error_log directive documentation does not mention that variables can be used to specify the error log filename. Moreover, I suppose this limitation is due to nginx’s internal architecture, as the error log is created at the very early stage of nginx startup, whereas variables only exist within the request processing context.