使用ProGuard删除调试日志

时间:2017-01-09 11:45:28

标签: java logging proguard

在我们正在进行的应用程序中,有如此多的调试和跟踪日志记录,即使日志记录级别将其关闭,创建消息参数数组的唯一开销也成为我们的一些问题。时间敏感的算法。现在,我们不想完全删除日志(因为它们在开发和测试环境中显然很有用),但我们确实希望以某种方式减少它们的运行时开销。我们考虑了几个选项:

  • 抛弃Slf4j API并使用具有延迟日志记录的Log4j2需要过多的重构和手工劳动。自定义记录器包装器和使用if语句包装所有记录器调用也是如此..
  • 代码后处理器可以自动用条件语句包装所有日志(因此永远不会创建参数数组)或完全删除它们。
  • ProGuard可以删除所有记录器电话。

由于我们还没有找到任何可以开箱即用的代码后处理器,因此我们决定使用ProGuard解决方案。这是我们基本的ProGuard设置:

-optimizations code/removal/simple,code/removal/advanced
-dontobfuscate
-dontshrink
-keep class *
-keepclassmembers class * {
  *;
}
-assumenosideeffects class org.slf4j.Logger {
  void trace(...);
  void debug(...);
}

解决方案部分工作。确实删除了大多数调试日志,但调试日志参数调用的所有方法都不受影响。例如,这一行:

log.debug("Evidence {} is unverifiable for product {}", evidence, product.getData().getName());

......将转变为:

product.getData().getName()

具有讽刺意味的是,它还会保留所有对象数组的启动:

log.debug("{} {} {}", first, second, third);
// ...becomes:
Object[] var10000 = new Object[]{first, second, third};

现在,我知道这种事情应该通过JIT优化(未使用的变量删除) - 我更担心第一种情况,其中所有被调用的方法都不会随着日志记录而被删除。这些可能包括无害(简单的getter调用)到稍差(size()对并发集合的调用)。

当前的ProGuard解决方案已经足够好了#34;但我想知道是否可以完全删除日志记录调用(及其副作用)。我们可以通过ProGuard配置实现这一目标,还是有现成的工具来实现这一目标?

1 个答案:

答案 0 :(得分:0)

一个疯狂的想法:如何创建自己的界面&实现与slf4j具有相同的接口,但具有展开的varargs?基本上你分叉slf4j以满足你的要求。

另一个想法是构建SLF4J-to-Log4j2迁移工具。如果您的公司同意您可以将此建议作为对Log4j2项目的贡献,那么您不必维护它。 : - )