【问题标题】:Implementing an orthogonal log level that gets dumped into a socket实现被转储到套接字中的正交日志级别
【发布时间】:2026-02-05 16:05:01
【问题描述】:

我正在使用 boost 日志并希望实现一个独立于现有日志级别的额外日志级别。

如果有监听客户端连接到守护进程套接字(独立于当前配置的日志级别),则该日志级别将按需激活。

这可以实现吗?

我怀疑按需功能可以通过自定义接收器来实现,该接收器将丢弃或发送数据。但是如何将其与其余的日志记录代码集成呢?

【问题讨论】:

    标签: c++ sockets boost-log


    【解决方案1】:

    让我们将您想要实现的目标分开。如果我理解正确:

    1. 您希望将一些日志记录通过套接字发送到另一个进程。
    2. 只需要发送选择的日志记录,其他不需要。
    3. 您想在运行时启用或禁用此功能。

    这些点中的每一个都可以通过扩展或自定义 Boost.Log 的不同部分来实现。让我们看看如何实现这些目标。

    1。创建自定义接收器后端。

    Boost.Log 使用sinks 来处理日志记录。它不提供通过套接字发送记录的接收器,因此您是正确的,因为您需要编写一个。这上面有一个tutorial。请注意,您只需要编写一个后端,即实际发送记录的部分。实现线程同步和过滤的部分已经由库以几个前端的形式提供,您可以与自定义后端一起使用。

    这里的重要决定是您希望通过网络发送日志记录的格式。最容易实现的是基于文本的格式,因为您可以使用库提供的formatters 来组合日志记录中的字符串。如果您需要二进制格式,那么您必须自己实现序列化(也许,在Boost.Serialization 或其他库的帮助下)。您最有可能要做的是从log record views 中提取属性值,以便将它们序列化为适合发送的二进制形式。我们稍后会回到属性。

    当您的接收器后端实现后,您可以选择一个合适的前端并将您的接收器添加到the logging core。这可以在您的应用程序启动时完成一次,即使此时不需要发送日志记录也可以完成。

    2。用属性标记日志记录。

    您想要记录的任何类型的数据都用attributes 表示。这包括时间戳、严重性级别,甚至日志消息本身。日志记录基本上是由这些属性生成的值的集合,以及相关的属性名称。如果您想将某些日志记录与其他日志记录区分开来(在您的情况下选择性地通过您的接收器发送它们),您必须用不同的属性标记它们。严重性级别不适合此操作,因为正如您所说,您希望发送记录而不管其级别如何。

    您可以使用channels 作为将一些日志记录路由到新接收器的方法。通道是另一个属性(通常是字符串),filters 可以对其进行分析,以阻止某些接收器的日志记录并传递给其他接收器。通道、严重性级别以及任何其他属性都可以一起使用以形成您传递给库的日志记录。例如,here 是一个常用的记录器,它同时支持通道和严重级别。

    还有其他方法可以标记您的日志记录。例如,您可以使用scoped attributes 来标记具有属性的特定范围内的日志记录。这种方法的优点是,您可以标记通过任何记录器生成的任何日志记录,甚至无需访问该记录器。

    3。配置过滤器。

    正如我已经提到的,为了选择哪些日志记录进入您的接收器,您必须为接收器设置一个filter。过滤器由接收器前端管理,因此您不必在后端实现它。过滤器将检查您的应用程序发出的每条日志记录的属性值,并仅通过那些满足条件的记录。例如,您可以设置一个过滤器,该过滤器将仅通过附加了通道属性的特定值的记录。或者您可以设置一个始终返回 false 的过滤器,从而有效地禁用通过您的接收器进行日志记录。您可以随时设置过滤器,以便根据请求修改日志记录行为。您只需要将指向您的接收器的指针保留在某个可用的地方,以便能够在需要时为其设置过滤器。

    【讨论】:

    • 感谢精彩的概述。如果需要进一步说明,我会回来报告。