Having log entries separated by category and priority and stored to different files as appropriate is a good start but there is still a problem with the long-term scalability of our solution. More specifically, the more time that passes the larger our log files will become.
This can lead to a whole host of problems, and not just when it comes to locating log events recorded over a particular time frame in a given log file. If we are intending to perform automated log analysis, and we probably should be on a production server, how will we know which log entries to process? How will we stop our log files consuming all the available space on the log partition?
Automated log rotation is the answer to all these problems and more.
Traditionally on UNIX systems, and by implication Linux systems, log rotation has been performed by the, rather obviously named, logrotate application. It is usually run from a cron entry once per day whereupon it will examine its configuration files for the list of files it is to rotate and the rotation policy and then move, compress, delete, or email, the files accordingly.
Another method of performing log rotation, and the one we shall examine here as this is a guide to system logging with syslog-ng, is to use the built-in macros provided by the syslog-ng daemon. These macros allow the various parameters of a log message, including the time and date it was generated, to be used to make up part of the path to the log file and are therefore perfectly designed for automated log rotation.
As we mentioned in the previous section the syslog-ng daemon provides a number of macros which expand to various elements of the log entry and can thus be used to perform log rotation. A brief description of the most commonly used of these macros is given below.
These macros can, amongst other things, be placed in the path specifier for file destinations as shown in the following example. This would cause the syslog-ng daemon to create files with the current date as their name, grouped in specified directories by log level, with the .log extension.
destination d_maildebug { file("/var/log/mail/debug/$DATE.log"); };
destination d_mailinfo { file("/var/log/mail/info/$DATE.log"); };
destination d_mailwarn { file("/var/log/mail/warn/$DATE.log"); };
destination d_mailerr { file("/var/log/mail/error/$DATE.log"); };
Alternatively we could place the $DATEmacro so that log files are grouped by date first, then priority level, as shown in the example below. This would cause the syslog-ng daemon to create files named level.log grouped in directories named with the current date.
destination d_maildebug { file("/var/log/mail/$DATE/debug.log"); };
destination d_mailinfo { file("/var/log/mail/$DATE/info.log"); };
destination d_mailwarn { file("/var/log/mail/$DATE/warn.log"); };
destination d_mailerr { file("/var/log/mail/$DATE/error.log"); };
While the above configuration entries will allow us to record log entries in files organised according to the date of their occurrence as well as their facility code and priority level it is still missing some of the more important functionality of the standard syslog and logrotate combination. Most importantly it lacks functionality to archive log files in a compressed form and ultimately delete them when they are over a predefined age.
Unfortunately the syslog-ng service does not contain the required functionality to perform either of these functions. Thankfully it is a trivial task to write a simple script to replicate this functionality. This script can then be run from a cron entry in the same way as the logrotate program.
For your convenience a simple bash script which performs these functions is provided in the appendix.