java日志记录的复杂性和对MessageFormat性能的关注
我的应用程序使用log4j进行日志记录,通常我通过检查是否启用了特定级别来进行日志记录,然后按照以下方式进行日志记录
if(Logger.isApplicationDebugEnabled()){
Logger.logApplicationDebug("something"+values);
}
现在,这个if检查减少了jUnit测试期间的分支覆盖率。为了克服这个问题,我的朋友建议取消日志的“如果”检查
- 首先,我的一个朋友建议删除if检查并直接登录。这种方法的问题是,它可能会由于字符串的形成而减慢应用程序的速度,而这些字符串无论如何都不会出现在日志文件中李>
我想到的第二种方法与SLF4j非常相似
记录器。调试(“编号{0},日期{1,日期}”,1234,新日期())
这感觉非常有吸引力和简单。(此解决方案在内部使用MessageFormat.format(str,object[])方法。但我担心这可能会有什么表现。还要注意,“Logger”是我的内部实用程序类,在它的每个日志方法中,都有一个日志启用检查。 你们有什么建议?我浏览了velocity模板,但它需要参数图。是否有任何轻量级解决方案仅根据参数索引位置替换值,或者该解决方案可以吗
# 1 楼答案
好的,我将问一个显而易见的问题:为什么不在运行单元测试时启用调试日志记录——或者实际上启用所有级别的日志记录?这样做的好处是增加了代码覆盖率测试和日志问题测试(这远远不是不可能的)
检查是否启用日志记录是有原因的:不仅构造最终日志字符串可能很昂贵(在大循环中),而且构造单个参数本身也可能很昂贵。使用MessageFormat或java。util。格式化程序或任何东西都无法解决第二个问题。我真的鼓励你保持沉默
# 2 楼答案
我可以强烈推荐用于log4j的slf4j facade,它允许您使用这种语法
日志。信息(“你好,{}来自,{}”,“世界”,“我”)
只有在确定事件实际上应该被记录之后,字符串才会展开,这样您就不必指定ifEnabled包装器。然后使用log4j作为slf4j的后端
此外,与MessageFormatter相比,它的速度要快得多
# 3 楼答案
知道的唯一方法是测量。对性能的猜测几乎总是错误的:)
就我个人而言,我可能会坚持使用您最初的log4j代码——不要对覆盖率太过担心。防止对始终遵循的代码路径进行太多的日志调用是合理的,但我不会为错误条件之类的事情而烦恼,因为在这种情况下,您已经处于一种奇怪的、希望是罕见的情况。在这里面,编写最可读的代码,然后确保你的应用程序按你需要的方式运行如果没有,则对其进行分析以找出问题所在如果它在日志代码中,则对其进行优化
# 4 楼答案
事实上,我已经在一个项目上完成了你的建议,我对这种方法有着积极的经验。我在commons日志上创建了一个附加层,允许在引擎盖下使用
MessageFormat
进行消息格式化这些是我在测量了与您描述的几乎相同的使用模式后得到的结果,10000次调用类似:
^{pr1}$isDebugEnabled()
然而,产生的日志代码现在更加清晰,我们的整个团队最终生成了更有用、更详细的消息。在此之前,使用单独的方法来构造更长的记录器消息并不少见
考虑到关闭日志记录时几乎没有额外的性能影响,我可以预见自己将来会使用这种技术