You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Boost Log自定义格式化器中访问add_common_attributes()添加的属性?

Boost Log自定义格式化器访问公共属性问题解决

问题背景

原本使用Boost Log的默认格式化配置时,通过add_common_attributes()添加的TimeStamp、ThreadID等属性可以正常输出,日志格式如下:

[2023-01-31 08:08:13.300149] [0x00007f66a048d000] [info] My message

但切换为自定义着色格式化器后,无法正确访问这些公共属性,最终仅输出: My message,核心问题出在属性提取的类型匹配和访问方式上。

原自定义格式化器代码存在的问题:

void coloring_formatter(const boost::log::record_view& record, boost::log::formatting_ostream& stream) {
    auto severity = record[boost::log::trivial::severity];
    assert(severity);

    switch (severity.get()) {
    case boost::log::trivial::severity_level::trace:
        stream << "\e[97m";
        break;
    case boost::log::trivial::severity_level::debug:
        stream << "\e[34m";
        break;
    case boost::log::trivial::severity_level::info:
        stream << "\e[32m";
        break;
    case boost::log::trivial::severity_level::warning:
        stream << "\e[93m";
        break;
    case boost::log::trivial::severity_level::error:
        stream << "\e[91m";
        break;
    case boost::log::trivial::severity_level::fatal:
        stream << "\e[41m";
        break;
    }

    stream /* << boost::log::extract<boost::posix_time::ptime>("TimeStamp", record) << ": " */ // 编译失败
           << boost::log::extract<unsigned int>("ThreadID", record) << ": " // 提取为空
           << record[boost::log::expressions::message]; // 仅该部分正常工作

    if (severity) {
        stream << "\033[0m";
    }
    
}

解决方法

1. 匹配正确的属性类型

add_common_attributes()添加的属性有固定类型,错误的类型会导致提取失败或编译错误:

  • TimeStamp:类型为boost::posix_time::ptime(对应Boost版本的本地时钟值类型)
  • ThreadID:类型为boost::log::attributes::current_thread_id::value_type(本质是平台相关的线程ID类型,如pthread_t或std::thread::id,而非unsigned int)

2. 安全提取属性并输出

使用boost::log::extract或直接通过record[]访问属性时,需先检查属性是否存在,避免空输出。以下是修正后的格式化器代码:

#include <boost/log/attributes/current_thread_id.hpp>
#include <boost/log/attributes/local_clock.hpp>

void coloring_formatter(const boost::log::record_view& record, boost::log::formatting_ostream& stream) {
    auto severity = record[boost::log::trivial::severity];
    assert(severity);

    // 根据日志级别设置终端颜色
    switch (severity.get()) {
    case boost::log::trivial::trace:
        stream << "\e[97m";
        break;
    case boost::log::trivial::debug:
        stream << "\e[34m";
        break;
    case boost::log::trivial::info:
        stream << "\e[32m";
        break;
    case boost::log::trivial::warning:
        stream << "\e[93m";
        break;
    case boost::log::trivial::error:
        stream << "\e[91m";
        break;
    case boost::log::trivial::fatal:
        stream << "\e[41m";
        break;
    }

    // 提取并输出TimeStamp
    auto timestamp = boost::log::extract<boost::posix_time::ptime>("TimeStamp", record);
    if (timestamp) {
        stream << "[" << *timestamp << "] ";
    }

    // 提取并输出ThreadID
    using thread_id_type = boost::log::attributes::current_thread_id::value_type;
    auto thread_id = boost::log::extract<thread_id_type>("ThreadID", record);
    if (thread_id) {
        stream << "[" << *thread_id << "] ";
    }

    // 输出日志级别和消息
    stream << "[" << severity << "] " << record[boost::log::expressions::message];

    // 重置终端颜色
    stream << "\033[0m";
}

3. 简化的属性访问方式

也可以直接通过属性名称的关键字访问,代码更简洁:

// 访问TimeStamp
auto timestamp = record[boost::log::attributes::local_clock::get_name()];
if (timestamp) {
    stream << "[" << timestamp << "] ";
}

// 访问ThreadID
auto thread_id = record[boost::log::attributes::current_thread_id::get_name()];
if (thread_id) {
    stream << "[" << thread_id << "] ";
}

修正后,日志输出会恢复原有的TimeStamp、ThreadID字段,并根据级别显示对应颜色。

内容的提问来源于stack exchange,提问作者Dominic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 02:50:43