审计日志

一个简单的更改日志,旨在易于编写且非侵入性。

2004 年 3 月 7 日

这是我在 2000 年代中期进行的 进一步企业应用程序架构开发 编写的一部分。不幸的是,此后太多其他事情吸引了我的注意力,因此我没有时间进一步处理它们,而且在可预见的未来我也没有看到太多时间。因此,这些材料非常草稿形式,在我能够抽出时间再次处理它们之前,我不会进行任何更正或更新。

工作原理

审计日志是最简单,也是最有效的跟踪时间信息形式之一。其理念是,每当发生任何重要事件时,您都会写入一些记录,指示发生了什么以及何时发生。

审计日志可以采用多种物理形式。最常见的形式是文件。但是,数据库表也可以成为一个很好的审计日志。如果您使用文件,则需要一种格式。ASCII 形式有助于在没有特殊软件的情况下使其对人类可读。如果它是一个简单的表格结构,那么制表符分隔的文本既简单又有效。更复杂的结构可以通过 XML 很好地处理。

审计日志 易于编写,但难以阅读,尤其是在它变得很大时。偶尔的临时读取可以通过肉眼和简单的文本处理工具完成。更复杂或重复的任务可以通过脚本自动化。许多脚本语言非常适合处理文本文件。如果您使用数据库表,则可以保存 SQL 脚本以获取信息。

当您使用 审计日志 时,您应该始终考虑写出实际日期和记录日期。它们很容易生成,即使它们在 99% 的时间里可能相同,但 1% 的时间可以拯救您的生命。当您这样做时,请记住记录日期始终是当前处理日期。

何时使用它

审计日志 的魅力在于它的简单性。当您将 审计日志 与其他模式(例如 时间属性时间对象)进行比较时,您会很快意识到这些替代方案为对象模型增加了许多复杂性,尽管这两种方法通常都比在所有地方使用 有效性 更擅长隐藏这种复杂性。

但正是处理 审计日志 的难度限制了它的使用。如果您每周根据历史数据的组合生成账单,那么所有用于处理日志的代码都将很慢且难以维护。因此,这一切都取决于时间信息的访问与您的常规软件流程的集成程度。集成越紧密,审计日志 的用处就越小。

请记住,您可以在模型的某些部分使用 审计日志,而在其他地方使用其他模式。您还可以使用 审计日志 来处理一个时间维度,而使用其他模式来处理另一个时间维度。因此,您可以使用 时间属性 处理属性的实际时间历史,并使用 审计日志 处理记录历史。

示例(Java)

一个简单的 审计日志 可以非常简单。

class Customer...

  private String phone;
  public String getPhone() {
    return (phone == null) ? "none" : phone;}
  public void setPhone(String arg, MfDate changeDate) {
    log (changeDate, this, "change of phone", phone, arg);
    phone = arg;
  }
  public void setPhone(String arg) {
    setPhone(arg, MfDate.today());
  }
  private static void log (MfDate validDate, Customer customer, String description, Object oldValue, Object newValue) {
    try {
      logfile().write(validDate.toString() + customer.name() + "\t" + description + 
        "\t" + oldValue + "\t" + newValue + "\t" + MfDate.today() + "\n");
      logfile().flush();
    } catch (IOException e) {throw new ApplicationException ("Unable to write to log");}
  }

请注意,即使设置方法只使用实际时间,我也将记录日期 (MfDate.today) 添加到日志中。我认为始终添加两个日期都是明智的,因为这样做很容易,而且如果您不添加它,您以后就无法重建它。

我将把在某个任意日期查找我的电话号码的脚本留作读者的练习。(显然,它太简单了,我无法在这里写出来……)