Menu

What is the simplest way to always include Line numbers, File and function names?

Help
2014-12-12
2014-12-12
  • Mario Knezović

    Mario Knezović - 2014-12-12

    Hi Andrey,

    I am trying to create a logging facility which always and if possible, automatically includes line numbers, file and function names in the output.

    So far I have played with 2 variants, but with none of which I am really satisfied:

    Quick and dirty: Simply output the attributes with the stream, basically a macro which expands to something like:

        BOOST_LOG(lg) << "Hello" << " [" << __FILE__ << ":" << __LINE__ << ";" << __FUNCTION__ << "()]";
    

    What I dislike with this is that in every log call the compiler needs to insert a few stream operations.

    Using named scopes (BOOST_LOG_NAMED_SCOPE macro and such):

    What I dislike with this is that I would have to put a zillion of BOOST_LOG_NAMED_SCOPE macros all around the place - and the scope name I specify in the macro is totally superfluous for my purposes. Actually it feels like a total misuse of a different feature.

    In contrast, e.g. with the ThreadID (which I also need to log), I was able to implement such an automatic attribute insertion with something along these lines:

    // include attribute with every log record spawned from this logger
    lg.add_attribute("ThreadID", attrs::current_thread_id());
    // then use in formatter
    [...] expr::attr<attrs::current_thread_id::value_type>("ThreadID") [...]
    

    ...and voilà: Exactly what I need!

    Is there something similar I can do with the line/file/function infos I need?

    If there's no out-of-the-box solution, what would be the way to go to implement such a kind of automatic attribute?

    (According to a couple of pages I googled while trying to find this out, I noticed that many people seem to have the same requirements, but all seem to hack their ways around this.)

    Thank you!

    Mario

     

    Last edit: Mario Knezović 2014-12-12
  • Andrey Semashev

    Andrey Semashev - 2014-12-12

    The question is what line numbers you want to see in logs. BOOST_LOG_NAMED_SCOPE and similar macros are designed to mark scopes (including functions), and it is the way to go if that is what you need. Yes, you have to add these macros to your code, and it does incur a very small performance penalty, but it also offer benefits such as the stack backtrace, which you can also use with exceptions.

    If instead you want to see line numbers of particular log records then the best way is to define a custom macro which you will use to write logs. In that macro, you can add the file name and line number as attributes to the record (you can use manipulators for that). Note that in this case you won't be able to use these attributes in filters, but you probably don't need that.

     
  • Mario Knezović

    Mario Knezović - 2014-12-12

    Andrey, as usual, thank you for your super fast reply!

    I need the line numbers of the log records and I neither need exception stack traces nor filtering.

    I am not familiar yet with manipulators. Before I dig into it: Would your suggestion require the line/file/function attribute to be added in every single log call (by the new macro)?

    Or could it somehow be made to work like the automatic solution I briefly mentioned with the ThreadID example? ("Telling" a logger to automatically always do it. I want those infos always, not only sometimes.)

     
  • Andrey Semashev

    Andrey Semashev - 2014-12-12

    Yes, the macro will add attribute values to every log record (that is, every one that passes filtering).

    There is no way to obtain source file position or function name from an unrelated place in code, such as an attribute implementation. You do have to capture that information at the log record site. You can store it as attribute values, as I suggested, or inject into the log message itself - either way you have to do something while constructing the record.

     
  • Mario Knezović

    Mario Knezović - 2014-12-12

    Understood. Thanks again!

    (I'll go with the quick solution I already implemented for now - inject into the log message with a macro - and put the manipulator version into my refactoring backlog.)

     

Log in to post a comment.