简体   繁体   中英

__func__ and logging

I am implementing a log handler in C++, and it works good and all, however there is one thing which I would find usable and that is where the logger got the output from.

I guess this isn't really a big issue, but I stumbled on the __func__ identifier, which basically will keep the function name of the current function.

So I have a static function in my Log class called Write , it takes a log level, and a vary list. So I would call it as such:

Log::Write(LOG_DEBUG, "this is an integer: %d", 10);

and it will print:

2013-01-02 => 10:12:01.366 [DEBUG]: this is an integer: 10

However I was thinking that it could be useful to also have the caller in the message, to produce something like this:

2013... => 10:12:... (functionName) [DEBUG]: blah

So what I can do (of course) is to add the __func__ as a parameter to Log::Write , however that would mean that any time I call Log::Write I need to also send __func__ which will always be the same and I feel like it should be possible to do it without explicitly saying so.

So what I want is the functionality which would be provided with:

Log::Write(LOG_DEBUG, __func__, "message");

without needing to explicitly type out func every time.

I don't know if this really is possible, the best bet I've got is that there is some way to dereference the caller inside of the function Write , it doesn't seem likely that I can just "infer" a parameter like that. But worth asking at least and maybe I can see what options there are.

Thanks.

This is usually done with macros, along with the filename __FILE__ and line number __LINE__ .

void Log::Write(Level l,
                char const* function,
                char const* file,
                int line,
                char const* format,
                ...);

is wrapped into a macro:

#define LOG(Level_, Format_, ...) \
    Log::Write(Level_, __func__, __FILE__, __LINE__, Format_, __VA_ARGS__);

Note that you may want to "save" some computing by having a check for whether to log at that level or not:

// suppose availability of "bool Log::Enabled(Level l)"
#define LOG(Level_, Format_, ...)   \
    while (Log::Enabled(Level_)) {  \
      Log::Write(Level_, __func__, __FILE__, __LINE__, Format_, __VA_ARGS__);  \
      break;  \
    }

The use of a while instead of if is to avoid the dangling else issue.

Note: you may wish to investigate the use of streams for logging. The issue with printf style is that it is not composable. With streams, you can overload std::ostream& operator<<(std::ostream&, X const&) for any X and then only write once a method to dump its content in the logs.

#define WRITE_LOG(X,...) Log::Write(LOG_DEBUG, __func__, (X),__VA_ARGS__);

Use this macro to write logs instead of the function, and it will automatically add the func parameter. As Mat mentions, this is the typical way, I cant think of any way to avoid macros in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM