OK, for a real-time app, whatever you do has to be FAST, and if the resources aren't available for your processing thread to do the logging, I'm assuming you'll just have to skip logging that event.
Just as importantly, whatever logging you add, the performance has to be deterministic - it takes the same overhead to do the logging for a processing thread every single time you do the logging. That number should be as small as possible, but it can't be good most every time, with an occasional long-running hang waiting for resources.
So something like Boost is probably the last thing you should be looking into using. Do you know what's going on inside the Boose libraries? And how using it will impact your real-time processing in every single case? No, you don't. If you could get the entire Boost development team and have them answer, "Tell me exactly what happens when I use this Boost functionality in every possible use case.", even the Boost developers themselves almost certainly wouldn't be able to tell you.
Using syslog() might meet your needs, but I'd measure the overhead of doing so.
If I were to roll my own, I'd probably try something like this:
- Define a binary structure:
struct timed_event
{
int event_id;
time_t event_start;
time_t event_end;
time_t current_time;
}
-
Define event ids for all the events you want to collect data from.
-
Create a pipe of some kind - named pipe, SYS V message queue, etc.
-
For each event you time, fill in one of those structures.
-
After filling in the structure, write the binary structure to the pipe. Write using a non-blocking low-level call such as a simple write(). Do NOT use C++ functionality, for a lot of reasons. Again, this needs to be non-blocking so if whatever pipe/queue you're writing to is full, you don't wait. It also needs to be atomic - which is why YOU need to make the write() call (or whatever) directly in YOUR code.
-
Write another process that reads the binary data from the pipe (should be easy since the reader knows the size of the binary structure - read() the proper number of bytes and get a filled-in struct), translates it into a readable log message, and logs it. Or maybe you just log the raw binary data and translate it offline later depending on your space needs.
You might want to add more data to the structure.
One thing to watch out for, especially if you implement something like a simple write() to a Unix pipe: partial write()'s. For example, if your structure comes out to be 32 bytes, maybe the pipe is almost full and write() only puts 24 bytes in the pipe. You might want do so something like start each structure with a magic number int field and put something in there that hopefully can't be duplicated in any other field. Then the reading/logging process can use that magic number field to try to sync up the binary stream of data.
Another issue: make sure your processing code and your logging code use the same size for the binary structure. Compiler optimization flags can change data alignments, which can change structure sizes. So if you aggressively optimize the processing code but not the logging code, the processing code could be using a binary structure that's 48 bytes because of alignment padding while the logging process could be using a non-padded structure that's 32 bytes.