XLOG_ACTUAL_IMPL

Helper macro used to implement XLOG() and XLOGF()

Synopsis

Declared in <folly/logging/xlog.h>

#define XLOG_ACTUAL_IMPL(level, cond, always_fatal, type, ...)

Description

Beware that the level argument is evaluated twice.

This macro is somewhat tricky:

  • In order to support streaming argument support (with the << operator), the macro must expand to a single ternary ? expression. This is the only way we can avoid evaluating the log arguments if the log check fails, and still have the macro behave as expected when used as the body of an if or else statement.

  • We need to store some static-scope local state in order to track the LogCategory to use. This is a bit tricky to do and still meet the requirements of being a single expression, but fortunately static variables inside a lambda work for this purpose.

Inside header files, each XLOG() statement defines two static variables:

  • the LogLevel for this category

  • a pointer to the LogCategory

If the INCLUDE_LEVEL macro is available (both gcc and clang support this), then we we can detect when we are inside a .cpp file versus a header file. If we are inside a .cpp file, we can avoid declaring these variables once per XLOG() statement, and instead we only declare one copy of these variables for the entire file.

  • We want to make sure this macro is safe to use even from inside static initialization code that runs before main. We also want to make the log admittance check as cheap as possible, so that disabled debug logs have minimal overhead, and can be left in place even in performance senstive code.

In order to do this, we rely on zero-initialization of variables with static storage duration. The LogLevel variable will always be 0-initialized before any code runs. Therefore the very first time an XLOG() statement is hit the initial log level check will always pass (since all level values are greater or equal to 0), and we then do a second check to see if the log level and category variables need to be initialized. On all subsequent calls, disabled log statements can be skipped with just a single check of the LogLevel.

Parameters

NameDescription
levelThe folly::LogLevel value at which to log.
condA predicate; the message is logged only when it is true.
always_fatalWhether the statement always aborts the program.
typeThe LogStreamProcessor append or format mode.