首页 > 解决方案 > 从日志消息中去除静态文本并仅保存变量

问题描述

我知道有一种方法可以从日志消息中删除静态文本,并且只将消息的变量部分保留在内存中。但我不确定它是如何完成的。

举一个具体的例子来说明我的意思:

这是客户端的一些代码:

#include <stdio.h>
#include "my_logging.h"
int main() {
   MY_CUSTOM_LOGGING_TECHNIQUE("This is message %d", int, 1);
   MY_CUSTOM_LOGGING_TECHNIQUE("This is message %d", int, 2);
   return 0;
}

以及应该怎么做:

  1. 在编译/构建期间:

在编译/构建期间生成 XML 文件,为每条消息提供 ID:

<xml>

<message params=1>
<id>123456</id>
<text>This is message %d</text>
<param>int</param>
</message>

<message params=1>
<id>456342</id>
<text>This is message %d</text>
<param>int</param>
</message>

</xml>
  1. 在运行时:只有消息的 ID 与参数值一起存储在适当的结构中(此处显示为数组“messages_array”):messages_array:

消息数组

  1. 在后处理期间:在运行时保存的值被迭代并与在构建期间保存的 XML 文件相结合。此后处理步骤将生成日志文件:

这是消息 1
这是消息 2

我在这里试图解决的主要问题是“不必在运行时将静态文本写入文件。相反,只有消息的 ID 和消息中发送的参数的值。

那么,我该怎么做呢?

标签: c++cgccg++

解决方案


恐怕如果没有一些额外的预处理/后处理,C 就不可能做到这一点。

一种解决方案是使用__COUNTER__结合了 -E gcc 参数和后处理的宏来生成 XML 文件。看这个例子:

#define MY_LOG(string, ...) logPlaceholder(__COUNTER__, string); logFunction(__VA_ARGS__)

void logPlaceholder(int a, const char* str) {}

void logFunction(int param)
{
    printf("%d\n", param);
}

int main()
{
    MY_LOG("hello%d", 1);
    MY_LOG("world%d", 2);
    return 0;
}

您可以用logFunction一些可变参数函数替换以接受更多参数。

logPlaceholder将被优化,因为它是空函数 - 输出二进制文件中不会出现字符串。

当使用 -E 参数编译时,它会在标准输出中生成类似这样的内容:

int main()
{
    logPlaceholder(0, "hello%d"); logFunction(1);
    logPlaceholder(1, "world%d"); logFunction(2);
    return 0;
}

当您将 gcc 输出重定向到您可以后处理的文件时 - 查找logPlaceholder字符串并生成带有消息编号、字符串和所有参数的 XML。

但是__COUNTER__是编译器特定的(非标准的)并且对于所有宏都是全局的。


推荐阅读