日志是构建工具的主要界面。如果日志太多,真正的警告和问题容易被隐藏。另一方面,如果出了错,你需要找出相关的信息。Gradle 定义了6个日志级别,如表 18.1,“日志级别”所示。除了那些您可能通常都会看到的日志级别之外,还有两个 Gradle 特定日志级别。这两个级别分别是 QUIET 和 LIFECYCLE. 默认使用后面的这个日志级别,用于报告构建进度。
The log is the main 'UI' of a build tool. If it is too verbose, real warnings and problems are easily hidden
by this. On the other hand you need the relevant information for figuring out if things have gone wrong. Gradle
defines 6 log levels, as shown in
Table 18.1, “Log levels”
. There are two Gradle-specific log levels, in
addition to the ones you might normally see. Those levels are
QUIET
and
LIFECYCLE
. The latter is the default, and is used to report build progress.
表 18.1. 日志级别
Level | 用于 |
ERROR | 错误消息 |
QUIET | 重要的信息消息 |
WARNING | 警告消息 |
LIFECYCLE | 进度信息消息 |
INFO | 信息性消息 |
DEBUG | 调试消息 |
Table 18.1. Log levels
Level | Used for |
ERROR | Error messages |
QUIET | Important information messages |
WARNING | Warning messages |
LIFECYCLE | Progress information messages |
INFO | Information messages |
DEBUG | Debug messages |
您可以使用表 18.2,“日志级别的命令行选项”中所示的命令行开关来选择不同的日志级别。在表 18.3,“栈跟踪的命令行选项”中,你可以看到影响栈跟踪日志的命令行开关。
You can use the command line switches shown in
Table 18.2, “Log level command-line options”
to choose
different log levels. In
Table 18.3, “Stacktrace command-line options”
you find the command line switches which affect
stacktrace logging.
表 18.2. 日志级别的命令行选项
选项 | 输出日志级别 |
没有日志选项 | LIFECYCLE 及更高 |
-q or --quiet
|
QUIET 及更高 |
-i or --info
|
INFO 及更高 |
-d or --debug
|
DEBUG 及更高 |
Table 18.2. Log level command-line options
Option | Outputs Log Levels |
no logging options | LIFECYCLE and higher |
-q
or
--quiet
|
QUIET and higher |
-i
or
--info
|
INFO and higher |
-d
or
--debug
|
DEBUG and higher (that is, all log messages) |
表 18.3. 栈跟踪的命令行选项
选项 | 意义 |
没有栈跟踪选项 | 构建错误(如编译错误)时没有栈跟踪打印到控制台。只有在内部异常的情况下才打印栈跟踪。如果选择 DEBUG 日志级别,则总是输出截断后的栈跟踪信息。
|
-s or --stacktrace
|
输出截断的栈跟踪。我们推荐使用这一个选项而不是打印全栈的跟踪信息。Groovy 的全栈跟踪非常冗长 (由于其潜在的动态调用机制,然而他们通常不包含你的的代码中哪里错了的相关信息。) |
-S or --full-stacktrace
|
打印全部的栈跟踪信息。 |
Table 18.3. Stacktrace command-line options
Option | Meaning |
No stacktrace options |
No stacktraces are printed to the console in case of a build error (e.g. a compile error). Only in
case of internal exceptions will stacktraces be printed. If the
DEBUG
log level
is chosen, truncated stacktraces are always printed.
|
-s
or
--stacktrace
|
Truncated stacktraces are printed. We recommend this over full stacktraces. Groovy full stacktraces are extremely verbose (Due to the underlying dynamic invocation mechanisms. Yet they usually do not contain relevant information for what has gone wrong in your code.) |
-S
or
--full-stacktrace
|
The full stacktraces are printed out. |
在构建文件中打印日志的一个简单方法是把消息写到标准输出中。Gradle 会把写到标准输出的所有内容重定向到它的日志系统的 QUIET
级别中。
A simple option for logging in your build file is to write messages to standard output. Gradle redirects
anything written to standard output to it's logging system at the
QUIET
log level.
示例18.1. 使用标准输出写日志
Example 18.1. Using stdout to write log messages
build.gradle
println 'A message which is logged at QUIET level'
Gradle 还提供了一个 logger
属性给构建脚本,它是一个 Logger
实例。该接口扩展自 SLF4J的 Logger
接口,并添加了几个 Gradle 的特有方法。下面是关于如何在构建脚本中使用它的示例:
Gradle also provides a
logger
property to a build script, which is an instance of
Logger
. This interface extends the SLF4J
Logger
interface and adds a few Gradle specific methods to it. Below is an example
of how this is used in the build script:
示例 18.2. 编写自己的日志消息
Example 18.2. Writing your own log messages
build.gradle
logger.quiet('An info log message which is always logged.') logger.error('An error log message.') logger.warn('A warning log message.') logger.lifecycle('A lifecycle info log message.') logger.info('An info log message.') logger.debug('A debug log message.') logger.trace('A trace log message.')
您也可以在构建脚本中通过其他使用的类 hook 到 Gradle 的日志系统中(例如 buildSrc
目录中的类)。只需使用一个 SLF4J 的logger对象。你可以在构建脚本中,以与内置的logger相同的方式使用这个logger。
You can also hook into Gradle's logging system from within other classes used in the build (classes from
the
buildSrc
directory for example). Simply use an SLF4J logger. You can use this
logger the same way as you use the provided logger in the build script.
示例 18.3. 使用 SLF4J 编写日志消息
Example 18.3. Using SLF4J to write log messages
build.gradle
import org.slf4j.Logger import org.slf4j.LoggerFactory Logger slf4jLogger = LoggerFactory.getLogger('some-logger') slf4jLogger.info('An info log message logged using SLF4j')
Gradle 内部使用 Ant 和 Ivy。它们都有自己的日志系统。Gradle 将其日志输出重定向到 Gradle 的日志系统。从 Ant/Ivy 的日志级别到 Gradle 的日志级别是一对一的映射,除了 Ant/Ivy 的 TRACE
级别之外,它是映射到Gradle 的 DEBUG
级别的。这意味着默认情况下, Gradle 日志级别将不会显示任何 Ant/Ivy 的输出,除非是错误或警告信息。
Internally, Gradle uses Ant and Ivy. Both have their own logging system. Gradle redirects their logging
output into the Gradle logging system. There is a 1:1 mapping from the Ant/Ivy log levels to the Gradle log
levels, except the Ant/Ivy
TRACE
log level, which is mapped to Gradle
DEBUG
log level. This means the default Gradle log level will not show any Ant/Ivy output
unless it is an error or a warning.
有很多的工具仍然在使用标准输出进行日志记录。默认情况下,Gradle 将标准输出重定向到QUIET
日志级别,把标准错误输出重写向到 ERROR
级别。这种行为是可配置的。Project对象提供了一个LoggingManager
,它可以在评估构建脚本时,修改标准输出和错误重定向的日志级别。
There are many tools out there which still use standard output for logging. By default, Gradle redirects
standard output to the
QUIET
log level and standard error to the
ERROR
level. This behavior is configurable. The project object provides a
LoggingManager
, which allows you to change the log levels that
standard out or error are redirected to when your build script is evaluated.
示例 18.4. 配置标准输出捕获
Example 18.4. Configuring standard output capture
build.gradle
logging.captureStandardOutput LogLevel.INFO
println 'A message which is logged at INFO level'
为能在任务执行过程中更改标准输出或错误的日志级别,task也提供了一个 LoggingManager
。
To change the log level for standard out or error during task execution, tasks also provide a
LoggingManager
.
示例 18.5. 对任务配置标准输出捕获
Example 18.5. Configuring standard output capture for a task
build.gradle
task logInfo {
logging.captureStandardOutput LogLevel.INFO
doFirst {
println 'A task message which is logged at INFO level'
}
}
Gradle 还提供了对 Java Util Logging,Jakarta Commons Logging 和 Log4j 的日志工具的集成。你所构建的类使用这些日志记录工具输出的任何日志消息,都将被重定向到 Gradle 的日志系统。
Gradle also provides integration with the Java Util Logging, Jakarta Commons Logging and Log4j logging
toolkits. Any log messages which your build classes write using these logging toolkits will be redirected to
Gradle's logging system.
您可以用您自己的 logging UI大量地替换 Gradle 的。你可以这样,比如,如果您想要以某种方式自定义 UI ——以输出更多或更少的信息,或修改日志格式,您可以使用 Gradle.useLogger()
方法替换这个logging。它可以在构建脚本,init 脚本,或者是通过内嵌的 API 访问。请注意它完全禁用 Gradle 的默认输出。下面是一个示例,在 init 脚本中修改任务执行和构建完成的日志打印。
You can replace much of Gradle's logging UI with your own. You might do this, for example, if you want to
customize the UI in some way - to log more or less information, or to change the formatting. You replace
the logging using the
Gradle.useLogger()
method. This
is accessible from a build script, or an init script, or via the embedding API.
Note that this completely disables Gradle's default output.
Below is an example init script which changes how task execution and build completion is logged.
示例 18.6 的例子. 自定义 Gradle 日志
Example 18.6. Customizing what Gradle logs
init.gradle
useLogger(new CustomEventLogger()) class CustomEventLogger extends BuildAdapter implements TaskExecutionListener { public void beforeExecute(Task task) { println "[$task.name]" } public void afterExecute(Task task, TaskState state) { println() } public void buildFinished(BuildResult result) { println 'build completed' if (result.failure != null) { result.failure.printStackTrace() } } }
gradle -I init.gradle build
的输出结果
Output of gradle -I init.gradle build
> gradle -I init.gradle build [compile] compiling source [testCompile] compiling test source [test] running unit tests [build] build completed
你的logger可以实现下面列出的任何监听器接口。当你注册一个logger时,只能替换它实现的接口的日志记录。其他接口的日志记录是不变的。你可以在 55.6章节,“在构建脚本中响应生命周期”参阅更多有关监听器接口的信息。
Your logger can implement any of the listener interfaces listed below.
When you register a logger, only the logging for the interfaces that it implements is replaced. Logging
for the other interfaces is left untouched.
You can find out more about the listener interfaces in
Section 55.6, “Responding to the lifecycle in the build script”
.