abumq / easyloggingpp

C++ logging library. It is extremely powerful, extendable, light-weight, fast performing, thread and type safe and consists of many built-in features. It provides ability to write logs in your own customized format. It also provide support for logging your classes, third-party libraries, STL and third-party containers etc.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Date-based log rotation?

DarrenCook opened this issue · comments

I've been using datestamp in the log filename:
FILENAME = "%datetime{%Y%M%d}.log"

For long-running processes this means it is still writing to 20140915.log a few days later. What is the recommended way to deal with this?

I can trigger a timer to run at midnight, but then I'm not sure what command to run to tell it to start a new log file, with a new filename.

Have a look at Log file rolling and see if helps

Thanks Majid. That is not quite what I'm after: what I want to do is at a certain point of time is just change the filename of the log file that is being written to. The current size of the existing file does not matter. E.g. in a simple C-style logging system, where I have a global FILE* log_fp, what I would do (inside a mutex lock) is:

 newFilename = "...";  //Make based on current timestamp
 fclose(log_fp);
 log_fp = fopen(newFilename,"w");

I imagine there is something inside Easylogging++ that does what I need, but is any of it exposed in the public API?

There is no internal timer that does it but you can certainly do what you are asking for using file rolling - this is theory so may want to test things

Write your PreRollOutCallback which will:

  1. check change of date and reconfigure logger with new filename if needed
  2. you may need to reinitiate logger.
  3. backups current file (check this out)

If your application is multithreaded, ensure you test that it doesn't deadlock any locks

Thanks Majid. I already have the timer, what I don't know how to do is tell the logger to close and re-open a file. Poking through the source, I think what I need is this function:

void closeAndReopenLogs(){
foreach(level){
  base::type::fstream_t* fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get();
  if(fs == nullptr)continue;
  std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename");
  fs->close();
  fs->open(fname, std::fstream::out | std::fstream::app);
  }
}

I don't actually want to do it for each level, though, just once per log file. However, I've only found functions that take level so far.

The std::fstream::app is important: if the filename has not changed I want it to carry on logging to the same file, and not lose any data. I could then call closeAndReopenLogs() hourly, happily ignorant of whether my end user has configured a logging filename of:

FILENAME = "%datetime{%Y%M%d}.log"

or:

FILENAME = "%datetime{%Y%M%d%H}.log"

or even one file per month:

FILENAME = "%datetime{%B%Y}.log"

There is no such way but I am accepting this as suggestion since some libraries support it.

In your timer, use Loggers::reconfigureAllLoggers(ConfigurationType::Filename, "path/to/logs/my-new-date.log")

This will reconfigure all the loggers with new file name and it will now write to new log file.

I finally got to looking at this, and wrote a blog post (with a complete test program):
http://darrendev.blogspot.com/2015/06/easylogging-how-to-get-one-log-file-per.html

I keep my filename in an external config file, so used a slightly different approach to your above suggestion. But it appears to be working nicely. :-)

Does reconfigure handle closing the file stream?
I'm observing the old files remain opened. (I used lsof.)

@abumusamq I see the roll-out.cpp. It's a single-thread program. What if multi-thread ? Does the callback need to be locked ? system call would do mv operation, which may be problematic under multi-thread situation. Moreover, static global variable idx is also need to be protected. Right?