在严重性较低时使用未构建的消息实现日志记录
Implementing logging with messages not constructed when severity is low
我想知道是否有任何方法可以确保不会构造日志行中定义的消息。在某些情况下,我会添加 'trace' 严重性的日志记录,但我担心无论如何都会构造消息(无论严重性是高还是低)。让我们考虑以下简化的日志系统:
template<class... Msg>
void logMessage(LogLevel logLevel, Msg... msg) {
if (logLevel == LogLevel::Info) {
auto test = fmt::format(std::forward<Msg>(msg)...);
}
}
与客户通话:
logMessage(LogLevel::Info, "this is sample message: {}", 123);
据我所知,即使日志级别不等于 'Info',也不能保证编译器会对此进行优化。因此无法保证“这是示例消息:{}”字符串不会构造为临时右值变量。
实现目标的唯一方法是:
template<class... Msg>
void logMessage(Msg... msg) {
auto test = fmt::format(std::forward<Msg>(msg)...);
}
但是每个客户调用看起来像这样:
LogLevel level = LogLevel::Info;
if (level == LogLevel::Debug) {
logMessage("this is sample message: {}", 123);
}
我想知道是否有任何聪明的宏使用方法或 constexpr 以便进行干净的一行日志记录 API 并同时确保当严重性较低时甚至参数都不是建? (严重性仍然需要在运行时配置)
序言:我认为这是一个坏主意。表达式的执行顺序是语言的核心基础属性,为了节省几行代码而以透明的方式搞乱它只是在寻求惊喜、意外的程序行为和多余的认知负担。
话虽如此,如果您无论如何都想沿着这条路走下去,获得您想要的行为所需的宏并不是特别复杂:
#define logMessage(level, ...) \
if(level >= gCurrentLogLevel) logMessageImpl(__VA_ARGS__)
用法:
int bar();
void foo() {
logMessage(LogLevel::Info, "Some message: {}", bar());
}
在这种情况下,无论好坏,只有在 gCurrentLogLevel
至少为 LogLevel::Info
时才会调用 bar()
。
我想知道是否有任何方法可以确保不会构造日志行中定义的消息。在某些情况下,我会添加 'trace' 严重性的日志记录,但我担心无论如何都会构造消息(无论严重性是高还是低)。让我们考虑以下简化的日志系统:
template<class... Msg>
void logMessage(LogLevel logLevel, Msg... msg) {
if (logLevel == LogLevel::Info) {
auto test = fmt::format(std::forward<Msg>(msg)...);
}
}
与客户通话:
logMessage(LogLevel::Info, "this is sample message: {}", 123);
据我所知,即使日志级别不等于 'Info',也不能保证编译器会对此进行优化。因此无法保证“这是示例消息:{}”字符串不会构造为临时右值变量。 实现目标的唯一方法是:
template<class... Msg>
void logMessage(Msg... msg) {
auto test = fmt::format(std::forward<Msg>(msg)...);
}
但是每个客户调用看起来像这样:
LogLevel level = LogLevel::Info;
if (level == LogLevel::Debug) {
logMessage("this is sample message: {}", 123);
}
我想知道是否有任何聪明的宏使用方法或 constexpr 以便进行干净的一行日志记录 API 并同时确保当严重性较低时甚至参数都不是建? (严重性仍然需要在运行时配置)
序言:我认为这是一个坏主意。表达式的执行顺序是语言的核心基础属性,为了节省几行代码而以透明的方式搞乱它只是在寻求惊喜、意外的程序行为和多余的认知负担。
话虽如此,如果您无论如何都想沿着这条路走下去,获得您想要的行为所需的宏并不是特别复杂:
#define logMessage(level, ...) \
if(level >= gCurrentLogLevel) logMessageImpl(__VA_ARGS__)
用法:
int bar();
void foo() {
logMessage(LogLevel::Info, "Some message: {}", bar());
}
在这种情况下,无论好坏,只有在 gCurrentLogLevel
至少为 LogLevel::Info
时才会调用 bar()
。