标签: logback

为什么不使用java.util.logging?

这是我生命中的第一次,我发现自己处于一个可以开源的Java API的位置.希望被包括在许多其他项目中.

对于日志记录我(以及与我一起工作的人)总是使用JUL(java.util.logging)并且从未遇到任何问题.但是现在我需要更详细地了解我应该为我的API开发做些什么.我已经对此做了一些研究,并且我得到的信息让我感到更加困惑.因此这篇文章.

由于我来自JUL,我对此持偏见态度.我对其余的知识并不是那么大.

从我所做的研究中我得出了人们不喜欢JUL的原因:

  1. "在Sun发布JUL之前,我开始使用Java进行开发,而且我更容易继续使用logging-framework-X而不是学习新东西".嗯.我不是在开玩笑,这实际上就是人们所说的.有了这个论点,我们都可以做COBOL.(但我当然可以说这是一个懒惰的家伙)

  2. "我不喜欢JUL中日志记录级别的名称".好吧,说真的,这还不足以成为引入新依赖的理由.

  3. "我不喜欢JUL输出的标准格式".嗯.这只是配置.你甚至不需要做任何代码方面的事情.(确实,过去你可能不得不创建自己的Formatter类来实现它).

  4. "我使用其他也使用logging-framework-X的库,所以我觉得使用那个更容易".这是一个循环论证,不是吗?为什么'每个人'都使用logging-framework-X而不是JUL?

  5. "其他人都在使用logging-framework-X".这对我来说只是上面的一个特例.多数并不总是正确的.

所以真正的大问题是为什么不是JUL?.我错过了什么?伐木立面的存在理由(SLF4J,JCL)是历史上存在多种伐木实施,其原因可以追溯到JUL之前的时代,正如我所看到的那样.如果JUL是完美的那么伐木外墙将不存在,或者什么?我们不应该首先质疑为什么它们是必要的而不是拥抱它们?(看看这些原因是否仍然存在)

好吧,到目前为止我的研究已经导致我可以看到的一些事情可能是JUL的真正问题:

  1. 表现.有人说SLF4J的表现优于其他表现.在我看来,这是一个过早优化的案例.如果你需要每秒记录数百兆字节,那么无论如何我都不确定你是否在正确的路径上.JUL也在不断发展,你在Java 1.4上做的测试可能不再适用.你可以在这里阅读它,这个修复已经成为Java 7.许多人还谈到了日志记录方法中字符串连接的开销.但是,基于模板的日志记录可以避免这种成本,并且它也存在于JUL中.我个人从来没有真正编写基于模板的日志记录 太懒了.例如,如果我使用JUL执行此操作:

    log.finest("Lookup request from username=" + username 
       + ", valueX=" + valueX
       + ", valueY=" + valueY));
    
    Run Code Online (Sandbox Code Playgroud)

    我的IDE会警告我并请求允许它将其更改为:

    log.log(Level.FINEST, "Lookup request from username={0}, valueX={1}, valueY={2}", 
       new Object[]{username, valueX, valueY});
    
    Run Code Online (Sandbox Code Playgroud)

    ..我当然会接受.许可授予 !谢谢您的帮助.

    所以我自己并没有自己编写这样的语句,这是由IDE完成的.

    关于性能问题的结论我没有发现任何迹象表明JUL的表现与竞争对手相比并不好.

  2. 从类路径配置.开箱即用的JUL无法从类路径加载配置文件.要做到这一点,需要几行代码.我可以看出为什么这可能很烦人,但解决方案简短而简单.

  3. 输出处理程序的可用性.JUL带有5个开箱即用的输出处理程序:控制台,文件流,套接字和内存.这些可以扩展或可以编写新的.例如,这可能是写入UNIX/Linux Syslog和Windows事件日志.我个人从来没有这个要求,也没有看过它,但我当然可以说明为什么它可能是一个有用的功能.例如,Logback附带了Syslog的附加程序.我仍然会争辩

    1. JUL开箱即用的产品涵盖99.5%的输出目的地需求.
    2. 特殊需求可以通过JUL之上的自定义处理程序来满足,而不是在其他方面.对我而言,没有任何迹象表明为JUL编写Syslog输出处理程序需要花费更多时间,而不是为另一个日志框架编写.

我真的很担心我忽略了一些东西.除了JUL之外,使用伐木外墙和伐木实施是如此普遍,我必须得出结论,我只是不明白.那恐怕不是第一次.:-)

那我该怎么办?我希望它成功.我当然可以"顺其自然"并实施SLF4J(这些日子似乎最受欢迎)但是为了我自己的缘故,我仍然需要明白今天的JUL究竟出了什么问题才能保证所有的模糊?我会为我的图书馆选择JUL来破坏自己吗?

测试性能

(nolan600于2012年7月7日添加的部分)

下面有一篇来自Ceki的参考文献,其中提到SLF4J的参数化比JUL快10倍或更快.所以我开始做一些简单的测试.乍一看,这种说法肯定是正确的.以下是初步结果(但请继续阅读!):

  • 执行时间SLF4J,后端Logback:1515
  • 执行时间SLF4J,后端JUL:12938
  • 执行时间JUL:16911

上面的数字是msecs,所以越少越好.因此,10倍的性能差异实际上非常接近.我最初的反应:这是很多!

这是测试的核心.可以看出,整数和字符串是在循环中构造的,然后在log语句中使用:

    for …
Run Code Online (Sandbox Code Playgroud)

java logging logback slf4j

333
推荐指数
4
解决办法
6万
查看次数

记录级别 - Logback - 经验法则以分配日志级别

我在我当前的项目中使用了logback.

它提供六个级别的日志记录:TRACE DEBUG INFO WARN ERROR OFF

我正在寻找一个经验法则来确定常见活动的日志级别.例如,如果线程被锁定,则应将日志消息设置为调试级别或信息级别.或者,如果正在使用套接字,则应在调试级别还是跟踪级别记录其特定标识.

我将欣赏每个日志记录级别的更多示例的答案.

logging logback

250
推荐指数
4
解决办法
14万
查看次数

log4j vs logback

我们在自制包装器后面使用log4j.我们现在计划使用它的更多功能.

我们应该更新到logback吗?

(我的意思是框架不是像SLF4J那样的外观)

java logging log4j logback

148
推荐指数
5
解决办法
10万
查看次数

如何配置Logback以将记录器的不同级别记录到不同的目标?

如何配置Logback以将记录器的不同级别记录到不同的目标?

例如,给定以下Logback配置,Logback会将INFO消息记录到STDOUTERROR消息STDERR吗?

(请注意,此示例是第3章:Logback配置中logback-examples/src/main/java/chapters/configuration/sample4.xml显示的示例的变体).

<configuration>
  <appender name="STDOUT"
   class="ch.qos.logback.core.ConsoleAppender">
   <encoder>
     <pattern>
        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
      </pattern>
    </encoder>
  </appender>
  <appender name="STDERR"
   class="ch.qos.logback.core.ConsoleAppender">
   <encoder>
     <pattern>
        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
      </pattern>
    </encoder>
    <target>System.err</target>
  </appender>
  <!-- What is the effective level of "chapters.configuration"? -->
  <logger name="chapters.configuration" level="INFO" additivity="false">
    <appender-ref ref="STDOUT" />
  </logger>
  <logger name="chapters.configuration" level="ERROR" additivity="false">
    <appender-ref ref="STDERR" />
  </logger>

  <!-- turn OFF all logging (children can override) --> …
Run Code Online (Sandbox Code Playgroud)

java logging logback

147
推荐指数
9
解决办法
13万
查看次数

注销以将不同的消息记录到两个文件

我正在使用logback/slf4j进行日志记录.我想解析我的日志文件来分析一些数据,所以我想要有两个记录器实例,每个记录器实例都记录到一个单独的文件中,而不是解析一个很棒的大文件(主要由调试语句组成); 一个用于分析,一个用于所有目的的日志记录.有没有人知道这是否可以使用Logback或任何其他记录器?

java logging logback slf4j

139
推荐指数
2
解决办法
8万
查看次数

如何以编程方式更改根日志记录级别

我有以下logback.xml文件:

<configuration debug="true"> 

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
<encoder>
  <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<root level="debug">
  <appender-ref ref="STDOUT" />
</root>
</configuration>
Run Code Online (Sandbox Code Playgroud)

现在,在发生特定事件时,我想以编程方式将根记录器的级别从调试更改为错误.我不能使用变量替换,我必须在代码中执行此操作.

怎么做到呢 ?谢谢.

java logging logback

134
推荐指数
5
解决办法
13万
查看次数

如何防止logback在每个日志开始时输出自己的状态?

这似乎是一个疏忽错误,但我似乎无法找到原因.使用logback/slf4j进行日志记录(最新版本为slf4j-api-1.6.1,logback core/classic 0.9.24).最简单的测试日志配置是:

<configuration>
 <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
  <layout class="ch.qos.logback.classic.PatternLayout">
   <!-- DONT USE THIS FORMATTER FOR LIVE LOGGING THE %L LINE NUMBER OUTPUTTER IS SLOW -->
   <pattern>%le %-1r [%c{1}:%L] %m%n</pattern>
  </layout>
 </appender>
 <root level="DEBUG">
  <appender-ref ref="stdout" />
 </root>
</configuration>
Run Code Online (Sandbox Code Playgroud)

每个日志设置都以logback的内部状态行开头:

11:21:27,825 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
11:21:27,826 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml] at [file:.../logback-test.xml]
11:21:28,116 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
11:21:28,124 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender] …
Run Code Online (Sandbox Code Playgroud)

logback

132
推荐指数
6
解决办法
5万
查看次数

如何在线程池中使用MDC?

在我们的软件中,我们广泛使用MDC来跟踪会话ID和Web请求的用户名等内容.这在原始线程中运行时工作正常.但是,有很多事情需要在后台处理.为此,我们使用java.concurrent.ThreadPoolExecutorjava.util.Timer类以及一些自动异步执行服务.所有这些服务都管理自己的线程池.

这就是Logback的手册在这样的环境中使用MDC所要说的:

映射的诊断上下文的副本不能始终由来自启动线程的工作线程继承.当java.util.concurrent.Executors用于线程管理时就是这种情况.例如,newCachedThreadPool方法创建一个ThreadPoolExecutor,就像其他线程池代码一样,它具有复杂的线程创建逻辑.

在这种情况下,建议在将任务提交给执行程序之前,在原始(主)线程上调用MDC.getCopyOfContextMap().当任务运行时,作为其第一个操作,它应调用MDC.setContextMapValues()以将原始MDC值的存储副本与新的Executor托管线程相关联.

这样会很好,但是很容易忘记添加这些调用,并且没有简单的方法来识别问题,直到为时已晚.Log4j的唯一标志是您在日志中丢失了MDC信息,而使用Logback,您会收到过时的MDC信息(因为胎面池中的线程从其上运行的第一个任务继承其MDC).两者都是生产系统中的严重问题.

我不认为我们的情况有任何特殊之处,但我在网上找不到这个问题.显然,这不是很多人碰到的东西,所以必须有办法避免它.我们在这做错了什么?

java logging logback slf4j mdc

128
推荐指数
5
解决办法
5万
查看次数

在SLF4J/Logback中使用标记的最佳实践

我们在我们的项目中使用SLF4J + Logback组合已经有一段时间了,并且对它非常满意,但是我们的日志记录策略相当简单,使用简单的基于类的记录器并且没有像MDC或Markers这样的花哨的东西.

我想知道的是,社区中是否有人实际使用这些功能以及它们如何用于改进日志记录/过滤.

我特别感兴趣的是在哪里,为什么以及如何使用[1]标记进行记录.他们认为这是一个非常简洁的功能,可以在记录中添加语义上下文 - 例如,当一个类可能正在处理多个问题时,可以使用任务/关注特定标记来区分日志语句.

在日志记录中创建和使用标记的最佳实践,约定或策略可能是什么.

更新:我想,我真正追求的不是为什么使用标记,而是如何使用标记- 是否有一些命名标记的好方法(例如使用带空格的明文或短划线/下划线/标点符号分隔的关键字样式名称),是否应该有某种"标准名称"池,根据业务功能命名.我可以为自己解决的问题,但如果我想系统地使用这些功能并将它们介绍给开发人员团队,那么就可以制定一些可正式的指导方针......


[1] - 通过询问如何使用标记我并不是真的问如何使用API​​(它确实非常直接) - 我更倾向于指出如何设置使用标记一致地记录的更一般级别

java logging logback markers slf4j

118
推荐指数
4
解决办法
5万
查看次数

登录Java有什么用?

为什么人们会使用以下其中一个而不是另一个?

  • Java日志记录
  • Commons Logging
  • Log4j的
  • SLF4J
  • 的logback

java logging log4j logback slf4j

115
推荐指数
4
解决办法
1万
查看次数

标签 统计

logback ×10

logging ×9

java ×8

slf4j ×5

log4j ×2

markers ×1

mdc ×1