Boost.Log,在配置文件的文件名或目标值中使用自定义属性

Boost.Log, using custom attributes in filename or target value of configuration file

我在C++中使用Boost.Log来记录,并使用配置文件。我添加了一些自定义属性并在配置文件中使用它们。下面是C++中属性的注册:

namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;

attr1 myProcessID("");
attr2 myThreadID("");
attr3 myThreadIndex("")
attr4 theCorrelationId("");
attr5 theMiscInfos("");

slg_mt::get().add_attribute("Process_ID", myProcessID);
slg_mt::get().add_attribute("Thread_ID", myThreadID);
slg_mt::get().add_attribute("Thread_Index", myThreadIndex);
slg_mt::get().add_attribute("Correlation_ID",  theCorrelationId);
slg_mt::get().add_attribute("MiscInfos",  theMiscInfos);

我定义了一个配置文件,并使用 boost::log::init_from_stream.

以正常方式初始化配置文件

如果我使用以下配置,效果很好:

[Sinks.TRACE]
Destination="TextFile"

Asynchronous="true"
AutoFlush="true"
Format="[TimeStamp %TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][UpTime 
%Uptime(format=\"%O:%M:%S.%f\")%][ProcessID: %Process_ID%][ThreadID: %Thread_ID% %Thread_Index%] %Message%"
Target="C:\BoostLogTrace"
FileName="C:\BoostLogTrace\REST_%N.log"
RotationSize="10485760"
ScanForFiles="Matching"
Filter="%Severity% = trace" 

一切正常。除了我不仅想在日志条目中使用我的自定义属性,而且还想在日志目标和文件名中使用。

当我尝试使用以下文件名时,它不起作用:

FileName="C:\BoostLogTrace\REST_%THREAD_ID%.log"

有没有办法使用自定义属性更改目标和文件名,属性值从一个日志条目更改为另一个?

从更高的角度来看,我需要将每个单独的用户会话记录在不同的日志文件中。我怎样才能用 Boost.log 做到这一点?

谢谢!

您可以使用 multi-file sink backend 登录到单独的文件。该后端支持从附加到日志记录的属性生成文件名。

但是默认不支持从配置文件初始化。你将不得不 register a factory for this sink backend and implement configuring this sink from parsed settings。您可以重用过滤器和格式化程序解析器,也可以使用格式化程序解析器来构造文件名生成器。

class multifile_factory :
    public logging::sink_factory< char >
{
public:
    // Creates the sink with the provided parameters
    boost::shared_ptr< sinks::sink > create_sink(settings_section const& settings)
    {
        boost::shared_ptr< sinks::text_multifile_backend > backend =
            boost::make_shared< sinks::text_multifile_backend >();

        // Read sink parameters
        if (boost::optional< std::string > param = settings["FileName"])
        {
            backend->set_file_name_composer(sinks::file::as_file_name_composer(
                logging::parse_formatter(*param)));
        }
        else
            throw std::runtime_error("No target file name specified in settings");

        typedef sinks::synchronous_sink< sinks::text_multifile_backend > sink_t;
        boost::shared_ptr< sink_t > sink = boost::make_shared< sink_t >(backend);

        if (boost::optional< std::string > param = settings["Filter"])
            sink->set_filter(logging::parse_filter(*param));

        if (boost::optional< std::string > param = settings["Format"])
            sink->set_formatter(logging::parse_formatter(*param));

        return sink;
    }
};

logging::register_sink_factory("TextMultifile",
    boost::make_shared< multifile_factory >());

然后您可以使用“TextMultifile”作为配置文件中的“Destination”参数值。您可以像以前一样解析配置文件,通过调用 init_from_streaminit_from_settings,初始化例程将调用工厂来创建和配置接收器。

请注意 text_multifile_backend 不支持日志文件轮换,因为它不跟踪它生成的单个文件。如果您仍然需要文件轮换和管理轮换的文件,那么您还必须实现自己的接收器后端。