你觉得java.util.logging足够了吗?
根据标题,您是否发现默认的Java日志框架足以满足您的需求?
你使用替代日志logging服务,如log4j或其他? 如果是这样,为什么? 我希望听到关于不同types项目中的日志logging要求的任何build议,并且在集成框架实际上是必要的和/或有用的时候。
logging与第三方库的依赖关系
在大多数情况下,Java JDK日志本身并不足够。 但是,如果您有一个使用多个开放源代码第三方库的大型项目,那么您很快就会发现其中许多项目具有不同的日志依赖性。
正是在这种情况下,从日志实现中抽象日志API的需求变得非常重要。 我build议使用slf4j或logback (使用slf4j API)作为您的API,如果您想坚持使用Java JDK日志logging,您仍然可以! Slf4j可以输出到许多不同的logging器实现没有问题。
在最近的一个项目中发生了一个具体的例子:我们需要使用需要log4j的第三方库,但是我们不想同时运行两个日志框架,所以我们使用了slf4j log4j api包装库和问题解决了。
总之,Java JDK日志logging很好,但是在我的第三方库中使用的标准化API将为您节省时间。 试着想象重构每个日志logging语句!
java.util.logging(jul)从一开始就是不必要的。 只要忽略它。
朱尔本身有以下缺点:
- 在Java 1.4中引入jul的时候,已经有一个广泛使用的日志框架:LOG4J
- 预定义的日志级别是:严重,警告,信息,configuration,精细,精细,最好。 我不会告诉你我个人对这些预定义级别的看法,以保持这个答案是半客观的。
- 可以定义更多的级别。 JUL支持多达4G不同的日志级别,稍微矫枉过正,恕我直言。 有时候更less。
-
最重要的一点是: 如果你敢定义你自己的日志级别,你可能会遇到内存泄漏问题!
随意阅读这里的效果:- 类加载器泄漏:可怕的“java.lang.OutOfMemoryError:PermGen空间”exception
- 如何解决可怕的“java.lang.OutOfMemoryError:PermGen空间”exception(类加载器泄漏)
这是一个非常有趣的阅读,即使你不打算使用自定义级别,顺便说一句,因为这个问题是一个广泛的,不只适用于JULI。
- 它驻留在java。*命名空间中,所以实现不能在运行时交换。 这有效地防止了在commons.logging和LOG4J的情况下将它桥接到SLF4J上的可能性。 桥接为jul完成的方式会对性能产生影响。 这使得JUL成为最不灵活的日志框架。
- Sun通过引入Jul隐含地将其定义为“标准的Java日志框架”。 这导致了一个普遍的误解:一个“好的Java公民”应该在他们的图书馆或应用程序中使用jul。
情况正好相反。
如果您使用commons.logging或LOG4j,则可以通过桥接到SLF4J来交换实际使用的日志logging框架(如果需要的话)。 这意味着使用commons.logging,LOG4J或SLF4J的库都可以login到相同的日志logging目标,例如文件。
我个人build议使用SLF4J + Logback组合来进行所有的日志logging。 这两个项目都是由LOG4J后面的人CekiGülcü负责协调的。
SLF4J是一个值得的(但非官方的,因为它不是来自同一个群体)commons.logging的继任者。 它比CL更不成问题,因为它静态地parsing了实际使用的日志logging后端。 另外,它具有比CL更丰富的API。
另一方面,Logback是LOG4J的(非)正式inheritance者。 它本身实现了SLF4J,所以没有任何包装引起的开销。
如果你还认为我应得的话, 现在你可能会低估我。 ;)
SLF4J是新的孩子。 我已经做了一些工作,这很好。 它的主要优点是参数化日志 ,这意味着你这样做:
logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);
而不是:
logger.debug("The new entry is " + entry + ". It replaces " + oldEntry + ".");
所有的string操作只有在语句被实际logging的时候才能完成。 看起来也干净。
应该指出的是,SLF4J是一个类似于commons-logging的包装,尽pipe它声称不太容易出现commons-logging的类加载器问题。
我们始终使用java.util.logging。 也适用于大型项目。 有几件事情你应该调整(例如默认的格式),但这不符合实际情况。 我发现Java中的日志框架的数量以及它们实现的function蠕变让Java社区感到烦恼和尴尬。 关于伐木的热烈讨论的水平是一个肯定的迹象,一些严重错误的事情。
JUL给你的是一个简单但足够的API,并且可以configuration一个地方来configuration你想查看的日志输出(logging.properties或JMX …)。 它永远在那里,稳定。
所有想要logging的代码都应该遵循标准的约定(默认级别是INFO),否则就不要再使用有意义名称的logging器(例如包或类名),你就可以。
除非有令人信服的理由来使用JDK之外的东西,否则我更喜欢使用Sun提供的东西。
许多使用Log4J日志logging的项目在“标准”日志loggingAPI存在之前使用它。
JDK日志工具一直做我所需要的 – 从来没有遇到过问题。
对我而言,第三方日志工具既不必要也不可取。
我无法弄清楚如何控制java.util.logging框架中各个类的日志logging级别,这在log4j中是可能的。 如果我在诊断错误方面遇到问题,或者有一个logging重要信息的高stream量类,我可以更改单个类的级别以logging更多信息,而让我的其他课程相对安静。
注意这可能是我不知道如何去做,或者java.util.logging可能已经改变,因为我试过了。
java.util.logging很好,但没有一个默认从类path中获取的configuration。 这对我们来说是一个痛苦的时刻,因为我们有很多不共享日志loggingconfiguration的部署,而且这样做在jul
Log4j目前还没有开发太多,所以如果后端部分需要开发的话,logback在我看来是最有活力的select。
(警告:涉及slf4j和logback的一些模糊的发展,但这是由于,而不是导致我上面的声明:))
我以为我会使用log4j – 正如@ ScArcher2所提到的,只是因为每个人都这么做。 但是在处理这两个选项之后,我发现java.util.logging足够满足我的大部分需求 – 而且我正在讨论一个包含许多扩展组件的巨大系统。
所以,在我看来,没有必要使用替代服务。 对于大多数情况来说,Java.util.logging已经足够强大了。
我们使用log4j和commons logging 。 我想我们只是使用它们,因为其他人都这么做。 这和我们在jdk支持日志之前使用log4j。
编辑:只是因为其他人都是一个笑话,但可能是为什么我开始与log4j和公共日志logging。
以下是使用公共日志logging的一些原因。
编写一个jul
LogManager
类非常简单,它将把所有日志logging推迟到使用Log4J的定制实现。 这意味着你可以使用log4j,但是仍然有很好的function,即使用JULlogging的库可以被控制为 – 如果它们使用了Log4J。
既然使用了(和commons-logging),我不得不说真正令我非常恼火的是:
log4j.error("An Exception", e); jul.severe("An Exception", e); // GRRR! no such method jul.log(Level.SEVERE, "An Exception", e); //Must use this method
他们为什么select这个devise? 为什么? 另一件事是没有与PatternFormatter
附带的PatternFormatter
– 你必须推出自己的。
也就是说,我从现在起就错误地使用了jul
,因为它减less了外部依赖,并且使用起来也不复杂。
在我工作的项目中,我们倾向于使用Jakarta的commons-logging。 这不是一个日志系统本身,而是能够包装一些最常见的日志logging器 – log4j,java.util.logging或其他。
因此,基于部署应用程序的环境,开发人员可能相对容易地进行切换(开发人员可能希望在他的机器上使用simplelog或java.util.logging,因为易于维护,而在SIT系统上,log4j可以部署所有应用程序的通用configuration等)
这一切都取决于你的logging要求是什么。 应用程序开发人员使用的API不仅仅是您所看到的,坦率地说,这是问题最less的问题,因为大多数情况下,无论您select哪种select,大多数日志loggingAPI都很容易适应。
重要的部分是你需要什么样的日志configuration操作 ,他们应该告诉你他们需要什么。
- 它可以像滚动的文本文件一样简单。
- 像login到JMS或数据库可能更复杂。
- 它可能需要单独的日志进行性能,审计等。
- 在发生日志事件时,可能需要电子邮件的详细信息。
在他们的VAR包中的Log4J已经支持这些和更多,并用他们的API进行testing。 现在使用java.util.logging,你应该可以下载它们,但是它们不像Log4J那样常见,而且可能很难find信息。
另一个要考虑的是你正在使用的供应商API。 大多数供应商为您“强制”一个日志API。 Spring是其中之一,它需要commons-logging。
作为一名开发人员,如果我可以为自己的东西,我会尝试使用java.util.logging,但在现实世界的情况下,你必须撼动他们将在操作中需要什么,并让它驱动你的select,因为他们是谁在应用程序上线时使用这些日志。 它既不是应用程序架构师,也不是应该做出这个select的开发者,尽pipe他们应该提出build议。
有一件事没有人在这个线程中提到 – java.util.logging不支持开箱即用的syslog。 这对我来说是一个破坏性的事情(并且引起了我一阵惊愕,不得不重构java.util.logging的东西来代替更多的果汁。
以下是我今天遇到的情况:
-
http://logging.apache.org/log4j/1.2/ – 唯一的,虽然它似乎老化一点。
-
http://slf4j.org/ – 正在尝试采取log4j的冠,它看起来有一些桥接/redirect的行为..它可能适合一个直接replace,但我找不到任何明确的例子。 我应该花更多的时间在这个。
-
http://syslog4j.org/ – 它的syslogs,但没有一个drop-in更换(似乎没有,做java人不syslog很多或什么?)
-
http://people.apache.org/~psmith/logging.apache.org/sandbox/jul-log4j-bridge/apidocs/org/apache/logging/julbridge/JULLog4jBridge.html – jul-log4j-bridge宣传其a放弃更换,看起来很有希望,占地面积很小。
我在所有日志框架中遇到的一个问题是,除非你的团队中的每个人都花时间精确地设置和控制它,否则你永远不知道给定的debugging语句是否会打印出来。
您可能已closures一个级别(debugging),或者您可能closures了一个程序包。
我浪费了太多的时间,假设一个debugging语句将打印,而不是。 现在我主要依靠System.out.println(),只需要完成debugging,然后删除或转换它们。
我知道这并不能回答你的问题 – 我只是想说,在增加复杂性之前,你可能要考虑你有多less理由。
日志logging不是那么复杂,在大多数大型项目当然是合理的。
我个人使用简单logging器 ,但在工作中,我使用我们的企业包装到JDKlogging器。 我使用简单的logging器,由于易于获得它的设置,并且它支持Fatal和Ludicrous之间的7级logging。
如果你需要login你的应用程序,那么你可能做的东西真的是错的。 我认为,报告偶尔出现的问题是可以的,但是在很多具有逻辑的类中进行debugging,信息等语句显然是错误的。 任何大型应用程序在其大部分逻辑填充类中都有logging语句,即使只select正确的logging器,也会造成信息过载。 大多数情况下,信息将不完整,嘈杂或您需要的实际信息是完全丢失。
我基本上说,你应该只需要编写debugging语句来通知用户程序对外部因素的反应
- 在基于文本的configuration文件中格式化问题。
- 打开或查找所需文件时出现问题。
- 如何使用Spring MVC正确logginghttp请求
- 为什么logcat不显示任何东西在我的Android?
- 我在哪里configurationJUnittesting类中的log4j?
- 我如何configurationSpring和SLF4J,以便能够logging日志?
- 如何禁用和重新启用在Python中的控制台日志logging?
- 如何做一个logging器中的消息断言JUnit
- logging错误到stderr和debugging信息到log4j的标准输出
- log4j.properties文件 – 同一类中的多个logging器
- 我怎样才能从我的程序中的DbContext.SaveChanges()生成SQL?