boost::log close log file and open a new one
Asked Answered
R

1

5

I'm using boost::log to simultaneously log to a file as well as the console. It's initialized like so:

void Init() {
logging::core::get()->set_filter
    (
        // set logging level to one of trace, debug, info, warning, error, fatal
        logging::trivial::severity >= logging::trivial::trace
    );
logging::add_common_attributes(); // enables timestamps and such
logging::add_file_log
    (
        keywords::file_name     = logfile + "_%N.log",
        keywords::rotation_size = 1024 * 1024 * 50, // 50MB log file max
        //       keywords::format = "[%TimeStamp%]: %Message%"
        keywords::format        = "%Message% #[%TimeStamp%]"
    );

logging::add_console_log(std::cout,
                         keywords::format = "%Message%"
);
}

At certain points in my program I'd like to change the log file manually. I can change the "logfile" string in the above code and call that Init() again, but then it continues to write to the old log file and starts the new one, and starts doubling the output on the console log.

Is there some kind of corresponding "remove_file_log" I'm missing, or manually tell it to stop logging to the original log and move to the next one?

Ribonuclease answered 1/1, 2017 at 23:32 Comment(0)
O
8

Every call to add_file_log registers a new file sink in the logging core, which results in multiple files being written at the same time. The existing sinks are not replaced. Depending on what you actually want to do, there are multiple things you could do.

First, if you look at add_file_log reference, you will notice that it returns the pointer to the created sink. You can pass that pointer to core::remove_sink when you want that sink to stop being used. Upon being destroyed, the sink will close the log file it was using.

typedef sinks::synchronous_sink< sinks::text_file_backend > sink_t;
boost::shared_ptr< sink_t > g_file_sink;

void Init() {
    // ...
    g_file_sink = logging::add_file_log
    (
        keywords::file_name     = logfile + "_%N.log",
        keywords::rotation_size = 1024 * 1024 * 50, // 50MB log file max
        keywords::format        = "%Message% #[%TimeStamp%]"
    );

    // ...
}

void StopFileLogging() {
    logging::core::get()->remove_sink(g_file_sink);
    g_file_sink.reset();
}

Second, the text_file_backend which is created and returned by add_file_log has the ability to rotate log files. If you just want to switch the log file at certain points of the program, this is what you're probably looking for. You can add the named parameters such as keywords::rotation_size to the add_file_log call and they will be used to set up automatic file rotation in the backend. You can also rotate the file manually by calling text_file_backend::rotate_file on the sink backend.

void RotateLogFile() {
    g_file_sink->locked_backend()->rotate_file();
}

Note that in this case you don't have to remove the sink from the core; it stays active after the file has been rotated.

Organo answered 2/1, 2017 at 0:27 Comment(1)
can i reset backend to null to reform it with new log file ??and if it is member of struct which is put in multiindex container, the iterator to struct is const,which makes error when trying to reset back end shared pointer,how can i convert const shared pointer to backend into non const reference to shared pointer to back end??Asseverate

© 2022 - 2024 — McMap. All rights reserved.