日志消息中事件id的实现意见


Opinions on implemention of event IDs in log messages

我有一个日志记录器类(在PHP中,但这并不重要),它输出日志消息。日志记录器是一个自定义实现,运行良好。但是,我想扩展它,为日志消息的每个类型提供一个事件ID。例如,"用户登录消息"是事件ID 1,"表单验证失败"是事件ID 2。

此事件ID的目的是在查看长日志列表时过滤不重要的事件。我相信按事件ID对日志进行分类和查询比在数据库中进行子字符串搜索更快。

我有以下的想法,但欢迎可行的替代方案。我在这个例子中使用了PHP,但一些足够通用的东西,可以应用于大多数语言,如PHP/Java/c#等,将是有用的。

1)在日志函数调用中隐式包含ID:

abstract class EventId {
    const LOGIN = 1;
    const VALIDATION_FAILURE = 2;
    // etc 
}
Logger::messageDebug(EventID::LOGIN, $username . " logged in"); 
Logger::messageWarning(EventID::VALIDATION_FAILURE, "Form failed to validate, etc.");

这样做的优点是简单,但我担心它会变得有点乱。

2)将变量参数作为单独的参数传递给日志消息,然后对第一个字符串

进行散列
Logger::messageDebug("%s logged in", $username);
Logger::messageWarning("The %s form failed to validate", $form); 

优点是简单,缺点是事件ID依赖于第一个字符串的散列(或其他函数)来区分日志消息的类型。

3)回溯和做一些肮脏

function messageDebug($message)  {
    $trace = obtainTraceOfCallToMessageDebug();
    $callToMessageDebug = $trace[0];
    $eventId = "";
    $eventId .= $eventId->file;
    $eventId .= $eventId->line;
    $eventId = sha1($eventId);  
    messageImpl($eventId, $message);
}

这是相当讨厌的,但它确实有一个优点,即不需要更改现有的日志消息,另外,在编写新的日志消息时,它不那么脆弱。在PHP中,获得回溯很容易,也很便宜,而在其他语言中,你可能不得不抛出一个异常,这非常糟糕。不管怎样,这是个好主意。

期待您的意见。我的主要要求是可维护性而不是速度。我目前正朝着第1 -保持简单。

我会选择第一个稍微修改的:

假设您使用以下语句调用记录器:

Logger::messageWarning($message)

换成

Logger::messageWarning($message, EventId:someconstant)

和定义你的EventId类为

abstract class EventId {
    const UNSPECIFIED = 1;
    const LOGIN = 2;
    const VALIDATION_FAILURE = 3;
    // etc 
}

和您的记录器函数将接受第二个参数,但使用默认值EventId:UNSPECIFIED

class Logger {
...
  function messageWarning($message, $message_type = EventId:UNSPECIFIED) {
    ...
  }
}

这样你就不会破坏现有的代码,不需要做第3条中概述的hack,并且可以通过添加事件类型来随时随地替换日志调用。