views:

1052

answers:

3

I have a logger system which basically is a fancy way of writing my data to std::clog in a thread safe way.

I also, redirect std::clog to a file like this:

int main() {
    std::ofstream logfile(config::logname, std::ios::app);
    std::streambuf *const old_buffer = std::clog.rdbuf(logfile.rdbuf());

    // .. the guts of the application

    std::clog.rdbuf(old_buffer);
}

This works great... however, my application also produces a very large amount of logs. I was wondering what would be a good way to properly rotate my log files. Is there a safe way to switch out the file via a cron task? I would guess no.

The only thing I can think of that would definitely work is if I had the application itself open a new file, and redirect the rdbuf of clog to that while holding the logging mutex. But that feels like a cheap solution, and I would need to check so see if it is time to rotate logs fairly often for it to be effective. There has got to be a better way.

+10  A: 

You can use the built-in log rotation method configured in /etc/logrotate.conf and/or /etc/logrotate.d/ - it's common to have logrotate send your app a SIGUSR1 as a signal to close and re-open all your log files.

Paul Tomblin
So basically what you are saying is I add a SIGUSR1 handler which does a close/reopen while holding the logging lock and logrotate will signal my app with that periodically?
Evan Teran
Even, only if you configure logrotate to rotate your logs, and set it to send a SIGUSR1 to your app. It doesn't happen automatically.
Paul Tomblin
+5  A: 

Or just use syslog instead of your custom logging scheme and the logs get rotated by logrotate anyway. -- depending on how it's configured but on most desktop/server systems it's already set to rotate them.

Steve Lazaridis
Good answer, but at this point I'd prefer to stick to my current logging scheme.
Evan Teran
A: 

You can use something similar to the following, and move the log file away whichever way (logrotate, cron script, etc.) (providing Cish sample, should be easily convertible)

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

void logworker()
{
    ino_t inode = 0;
    FILE *logfile;

    logfile = fopen(logfilename, "a+");
    while(running)
    {
        struct stat mystat;

        if (stat(logfilename, &mystat)!=0 || mystat.st_ino != inode)
        {
            logfile = freopen(logfilename, "a+", logfile);
            inode = mystat.st_ino;
        }

        while (stuff_in_buffer)
        {
            fwrite(); /* etc */
        }
        fflush(logfile);

        /* sleep until something interesting happens */
    }
}

It is safe to write to a file after it has been moved, so there's no need for extra caution

Hasturkun