使用注释进行跟踪日志记录

时间:2011-04-09 12:06:09

标签: java logging annotations trace aspects

我一直在使用一个公司的代码库,该公司的策略是编写大量的跟踪日志记录。因此,几乎每个方法都有一段代码,如下所示:

String LOG_METHOD = "nameOfMethod(String,List<Long>):void";
if(logger.isTraceEnabled()) { 
    Object[] params = new Object[] { string, list };
    logger.trace(CompanyMessages.newMethodInstanceMessage(this, LOG_METHOD, params)); 
}

并以此结尾(在finally - 子句中或仅在方法结束时结束:

if(logger.isTraceEnabled()) { 
    logger.trace(CompanyMessages.leaveMethodInstanceMessage(this, LOG_METHOD)); 
}

实际上有更多的代码,但这是基本的想法。 这使代码变得混乱,其他编码人员不断地使用他们自己的解释来搞乱它,这些解释不使用特定的CompanyMessages - 类来格式化监视工具要读取的消息。所以我正在寻找一种方法来摆脱上面的所有代码,并提供所有需要跟踪记录的方法,注释如下:@LogBefore('logLevel')&amp; @LogAfter('logLevel')

我选择此解决方案的原因是为了使其他开发人员不必学习任何新东西,而是使用注释而不是代码。我在一个服务器环境中工作,我们部署了数百个Web应用程序和数十个开发人员。所以我一直在寻找一种在Web应用程序中实现它的方法,而无需额外的编码或额外的大型库。这意味着我正在寻找一个小的,稳定的AOP实现,使用类似于我提出的注释,在每个Web应用程序中易于配置。表现也很重要。用AOP实现这个的最简单的例子是什么?

编辑:我确实找到了something very similar我正在寻找的东西,但这有几个问题。必须配置所有需要日志记录的类,这比仅使用注释更耗费资源。弹簧配置<aop:aspectj-autoproxy/>会解决这个问题吗?

3 个答案:

答案 0 :(得分:5)

看起来面向方面编程(AOP)可以真正帮助你解决这个问题。它非常适合解决诸如日志记录和跟踪等跨领域问题,它支持您需要的注释。

查看AspectJ或Spring AOP。

它将涉及一些AOP原则和您选择的API的学习,但它绝对值得付出努力。特别是日志记录和跟踪是您将遇到的第一个AOP教程之一,而且无需深入就可以轻松完成。

答案 1 :(得分:5)

注释和AOP点都有效。使用注释来警告AOP框架有关日志记录。

我要做的另一件事是修复记录器。

你有:

String LOG_METHOD = "nameOfMethod(String,List<Long>):void"
if(logger.isTraceEnabled()) { 
    Object[] params = new Object[] { string, list };
    logger.trace(CompanyMessages.newMethodInstanceMessage(this, LOG_METHOD, params) ); 
}

相反,请考虑这样的事情:

logger.trace(this, LOG_METHOD, string, list);

你可以像这样实现它:

public void trace(Object obj, Object args...) {
    if (parentLogger.isTraceEnabled()) {
        logger.trace(CompanyMessages.newMethodInstanceMessage(obj, LOG_METHOD, args);
    }
}

大多数日志记录实用程序是在我们使用Java编写varargs之前编写的,因此我们仍然会看到类似于您编写的内容。

我们还希望防范在没有启用时阻止调用日志,但主要动机是因为过去的大多数人会做你做过的事情,或者更糟糕的是:

logger.trace("My message: " + string + " with list " + list);

无论是否启用跟踪,都有一个昂贵的表达。

但是通过利用varargs,你可以获得两者。只需使用像MessageFormat这样的东西(你可能已经在做),你就可以轻松获得:

logger.trace("My message: {0} with list {1}", string, list);

禁用跟踪,这是一个通过3个指针的廉价方法调用。因此,保护​​它并使代码混乱的动力要小得多。

大多数现代记录器都没有很好地覆盖,所以你通常必须封装它而不是简单地扩展它。

它不直接解决您的问题,动态生成跟踪信息。但这是一个简单的中间立场,可以轻松地,逐步地清理现有的代码库。

此外,还有其他2个选项。

一个是使用运行代码的后处理器,并将登录添加到尚不存在的位置。这样可以节省您手动输入的负担,但它会使代码混乱(因为它仍然存在于任何地方)。

二,是在编译时使用注释处理器。这更复杂。但它的作用是在编译期间,它在编译时通过信息运行并扩充您的类。好的是你的代码是干净的(除了注释之外),但是所有的工作都是在编译时完成的。没有运行时影响而不是Object工厂的花哨类加载器。一旦构建完毕,您就可以将处理器丢弃,在运行时根本不需要它。

有一个项目,谁的名字逃脱了我,利用这个。它会在编译时自动将setter / getter添加到您的代码中。我听说过这件好事。

AOP框架可能会在编译时为你做这件事,我对他们不太熟悉,但无论如何,这种技术值得探索。

但至少要包装你的记录器。它是增量的,安全的,并且会逐渐清理您的代码并帮助您记录注释可能对您不起作用。

答案 2 :(得分:3)

我不认为注释是解决方案。注释类或实例意味着在运行时向类提供附加信息,本身它不会做任何事情。您需要一些代码来处理带注释的类,并在运行时根据这些注释在每个方法之前和之后添加代码。

所以没有办法添加注释并准备好了,你的类开始记录他们的方法。

解决方案应该是AOP - 这就是AOP首先发明的问题。定义每个方法的类/方法/操作,然后解决问题。

好吧,可能你可以在运行时使用注释和修改类,但你最终会得到自制的AOP: - )

相关问题