原始 MediaWiki 页面

我知道编辑这个网站吗?
核心 SciJava 软件库本页介绍与 核心 SciJava 软件库 相关的内容。点击徽标查看详情。

记录

自迁移出 MediaWiki 以来,本页内容尚未经过审查。如果您愿意帮忙,请查看帮助指南

如果您是一名 Java 开发人员,那么您很可能“喜欢”日志记录。至少,这是新 Java 开发人员不可避免地必须得出的结论,因为 97.3% 的 Java 库都是日志框架。考虑到日志记录的复杂性,很容易对任何给定项目的日志记录工作方式以及实际上整个 Java 软件生态系统中的日志记录工作方式感到困惑。幸运的是,这个友好的 wiki 页面可以帮助您一劳永逸地了解日志记录。

什么是日志记录?

日志记录是一种在程序执行期间报告消息和/或事件的技术。它可用于多种用途:调试、通知用户事情、永久记录所发生的事情等。

进一步阅读请参阅Wikipedia’s article on Java logging frameworks

另请参阅这篇好文章:The State of Logging in Java(2018 年 5 月)。

为什么使用日志框架? System.out.println 有什么问题吗?

首先,System.out.println相当冗长。但更重要的是,它有点不灵活:您无法显式指定元数据,例如消息的“严重性”或“级别”、关联的异常堆栈跟踪、消息的来源或其他详细信息。并且您无法根据上下文自定义日志记录行为(例如,将某些类型的消息记录到文件中,而其他消息则记录到标准输出)。

由于这些原因,几乎每个人和他们的狗要么使用日志框架,要么发明自己的日志框架。 SciJava Common 项目选择了两者:SciJava 应用程序框架提供了LogService 来抽象和封装所有日志记录。该服务的默认核心实现称为StderrLogService,并且简单地将所有日志消息发送到标准错误流。这样做是为了避免依赖于任何外部日志框架或外观,并提供足够丰富的日志 API。

SLF4J 怎么样?

SLF4J项目是一个好主意:它不是另一个日志框架,而是日志框架的外观。也就是说:它是一个接口驱动的 API,可以通过专用的绑定库由您希望的任何日志框架支持。理论上,如果每个人都只使用 SLF4J,他们只需添加对 org.slf4j:slf4j-api 的编译时依赖项,并在运行时传送他们选择的绑定,以便他们的应用程序将使用 Apache Log4jjava.util loggingLogback 进行日志记录。因为每个开发人员都想自己决定,对吗?

不幸的是,SLF4J 有几个缺点:

尽管如此,SLF4J 仍然是一件好事,因此 SciJava 项目确实提供了LogService implementation backed by SLF4J,热心的开发人员可以使用它将所有 SciJava 日志记录重定向到 SLF4J 框架,然后他们可以使用他们选择的 SLF4J 绑定further redirect

ImageJ2 中的日志记录如何工作?

ImageJ2 对所有核心日志记录使用 SciJava 日志记录框架。普通 ImageJ2 发行版使用 StderrLogService 将这些消息发送到标准错误流。默认日志级别为 INFO

也就是说,在 GUI 驱动的应用程序中使用标准输出和/或错误流存在一个问题:默认情况下此类消息不可见。为了解决这个问题,许多 GUI 驱动的应用程序为日志消息实现了自己的 UI 组件,通常是某种“日志窗口”。此解决方案是原始 ImageJ 解决 GUI 端日志记录问题的方法:插件应调用静态 IJ.logIJ.handleException 方法分别发出日志消息并向用户报告异常。

ImageJ2 默认使用 ImageJ 旧版用户界面运行,这意味着它继承了此日志窗口。但除此之外,它还提供了一个单独的控制台窗口,将所有消息记录到 stdout 和 stderr,这样就不会向用户隐藏任何可能有价值的控制台输出。每当发生任何 stderr 输出时,控制台窗口都会自动变为可见。 stderr 的输出显示为红色,以区别于 stdout 的输出。

因此,只要日志消息以某种方式最终出现在 stdout 或 stderr 上(默认情况下),一切都很好,用户将看到它们。但是,如果您配置自己的日志记录实现来抑制 stderr 行为,以支持例如记录到某处的文件,那么您就得靠自己了!

斐济的伐木工作如何?

ImageJ 的Fiji发行版是一个更复杂的野兽,因为它附带了许多插件,每个插件都可以在日志记录方面做自己的事情。 Fiji 不是 herd cats,而是简单地提供每个插件所需的日志框架,以便它可以畅通无阻地运行。

然而,最终,斐济发行版需要运送一个,而且“仅”一个,SLF4J 绑定;否则,基于 SLF4J 的日志记录将无法正常工作。截至撰写本文时,斐济发布了 logback-classic 绑定,这意味着基于 SLF4J 的日志记录可以是 configured in all the usual Logback ways。 Fiji 在 scijava-config 库中提供了默认的 Logback 配置,它将 INFO 级别事件发送到 stdout,并将更严重的级别(WARNERRORFATAL)发送到 stderr。如果您想覆盖配置,则需要删除或修改该 JAR 文件,将 logback.xml 替换为您自己的设计之一。选择logback-classic的原因是因为Bio-Formats项目明确依赖于它;斐济并没有解决这个问题,而是随波逐流,并集中在相同的依赖关系上。

控制日志记录级别

如果您使用标准 SciJava LogService 实现,则可以通过 scijava.log.level 系统属性控制日志记录级别。

例如,在 Java 代码中:

System.setProperty("scijava.log.level", "debug");

或者在运行特定类时通过命令行:

java -Dscijava.log.level=debug ... myorg.MyMainClass

或者在启动 ImageJ2 时通过命令行:

ImageJ-[linux64|macosx|win32.exe|win64.exe] -Dscijava.log.level=debug

您甚至可以自定义每个包/类层次结构的日志记录行为。例如,仅打开 org.scijava.plugin 包和子包中的类的调试级别日志记录:

System.setProperty("scijava.log.level:org.scijava.plugin", "debug");

如果您更喜欢环境变量,设置 DEBUG 环境变量将导致 SciJava 日志记录默认为 DEBUG 级别,而不是通常的 WARN 级别。

在代码中使用 LogService

LogService 可以通过 SciJava 插件访问,其方式与任何其他 service 相同:作为用 @Parameter 注释的字段。有关详细信息,请参阅Writing plugins指南。