构建日志是 Gradle 在构建过程中传达发生情况的主要方式。清晰的日志记录可帮助您快速了解构建状态、识别问题并有效进行故障排除。日志中过多的噪音可能会掩盖重要的警告或错误。

Gradle 提供了灵活的日志控制,使您能够根据需要调整详细程度和细节。

Gradle 日志级别

Gradle 定义了六个主要日志级别

级别 描述

ERROR

错误消息

QUIET

重要信息消息

WARNING

警告消息

LIFECYCLE

进度信息消息

INFO

信息消息

DEBUG

调试消息

默认日志级别为 LIFECYCLE,提供进度更新,但不会有过多的细节。

选择和设置日志级别

您可以通过命令行选项或配置 gradle.properties 文件来设置日志级别。

CLI 选项 属性 输出日志级别

-q--quiet

org.gradle.logging.level=quiet

QUIET 及更高

-w--warn

org.gradle.logging.level=warn

WARN 及更高

无日志选项

LIFECYCLE 及更高

-i--info

org.gradle.logging.level=info

INFO 及更高

-d--debug

org.gradle.logging.level=debug

DEBUG 及更高(所有日志消息)

例如,要在项目的 gradle.properties 文件中设置一致的日志级别

org.gradle.logging.level=info

同样在命令行中

$ ./gradlew run --info

您可以使用 Gradle 的内置日志记录器直接从构建脚本和任务发出日志消息

build.gradle.kts
tasks.register("logtask") {
    doLast {
        logger.lifecycle("Lifecycle: Build progress info.")
        logger.info("Info: Additional insights.")
        logger.debug("Debug: Detailed troubleshooting info.")
    }
}
build.gradle
tasks.register('logtask') {
    doLast {
        logger.lifecycle('Lifecycle: Build progress info.')
        logger.info('Info: Additional insights.')
        logger.debug('Debug: Detailed troubleshooting info.')
    }
}

使用适当的日志级别(lifecycleinfodebug)以确保您的构建输出清晰且信息丰富。

DEBUG 日志级别可能会将敏感安全信息暴露到控制台

堆栈跟踪选项

堆栈跟踪对于诊断构建失败期间的问题非常有用。您可以通过命令行选项或属性控制堆栈跟踪输出

CLI 选项 Gradle 属性 显示堆栈跟踪

--stacktrace-s

org.gradle.logging.stacktrace=always

打印截断的堆栈跟踪。我们建议使用此选项而非完整堆栈跟踪。由于底层动态调用机制,Groovy 完整堆栈跟踪非常冗长。但它们通常不包含有关您的代码中出现何种问题的相关信息。此选项为弃用警告呈现堆栈跟踪。

--full-stacktrace-S

org.gradle.logging.stacktrace=full

打印完整的堆栈跟踪。此选项为弃用警告呈现堆栈跟踪。

(无)

(无)

在构建错误(例如,编译错误)的情况下,不会将堆栈跟踪打印到控制台。只有在内部异常的情况下才会打印堆栈跟踪。如果选择 DEBUG 日志级别,则始终打印截断的堆栈跟踪。

例如,要始终在构建错误时显示完整堆栈跟踪,请在 gradle.properties 中设置

org.gradle.logging.stacktrace=full

记录敏感信息

DEBUG 日志级别运行 Gradle 可能会将敏感信息暴露到控制台和构建日志。

此信息可能包括

  • 环境变量

  • 私有存储库凭据

  • 构建缓存和 Develocity 凭据

  • 插件门户发布凭据

在公共持续集成 (CI) 服务上运行时,避免使用 DEBUG 日志级别非常重要。这些服务上的构建日志可供公众访问,并可能暴露敏感信息。即使在私有 CI 服务上,记录敏感凭据也可能根据您组织的安全威胁模型带来风险。建议与您组织的安全团队讨论此事。

一些 CI 提供商试图从日志中编辑敏感凭据,但此过程并非万无一失,通常只编辑预配置秘密的精确匹配。

如果您怀疑 Gradle 插件可能无意中暴露敏感信息,请联系我们的安全团队以获取披露方面的帮助。

自定义日志消息

在构建文件中进行日志记录的一个简单选项是向标准输出写入消息。Gradle 将写入标准输出的任何内容重定向到其日志系统,级别为 QUIET

build.gradle.kts
println("A message which is logged at QUIET level")
build.gradle
println 'A message which is logged at QUIET level'

Gradle 还为构建脚本提供了一个 logger 属性,它是 Logger 的实例。此接口扩展了 SLF4J Logger 接口并添加了一些 Gradle 特定方法。下面是其在构建脚本中使用的示例

build.gradle.kts
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.") // Gradle never logs TRACE level logs
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.') // Gradle never logs TRACE level logs

使用链接典型的 SLF4J 模式来用日志消息中的实际值替换占位符。

build.gradle.kts
logger.info("A {} log message", "info")
build.gradle
logger.info('A {} log message', 'info')

您还可以使用 SLF4J 日志记录器从构建中使用的其他类(例如,来自 buildSrc 目录的类)中连接到 Gradle 的日志系统。您可以像在构建脚本中使用提供的日志记录器一样使用此日志记录器。

build.gradle.kts
import org.slf4j.LoggerFactory

val slf4jLogger = LoggerFactory.getLogger("some-logger")
slf4jLogger.info("An info log message logged using SLF4j")
build.gradle
import org.slf4j.LoggerFactory

def slf4jLogger = LoggerFactory.getLogger('some-logger')
slf4jLogger.info('An info log message logged using SLF4j')

来自外部工具和库的日志记录

在内部,Gradle 使用 Ant 和 Ivy。两者都有自己的日志系统。Gradle 将它们的日志输出重定向到 Gradle 日志系统。

Ant/Ivy 日志级别与 Gradle 日志级别之间存在 1:1 映射,除了 Ant/Ivy TRACE 日志级别,它映射到 Gradle DEBUG 日志级别。这意味着默认的 Gradle 日志级别不会显示任何 Ant/Ivy 输出,除非它是错误或警告。

许多工具仍然使用标准输出进行日志记录。默认情况下,Gradle 将标准输出重定向到 QUIET 日志级别,将标准错误重定向到 ERROR 级别。此行为是可配置的。

project 对象提供了一个 LoggingManager,它允许您在评估构建脚本时更改标准输出或错误重定向到的日志级别。

build.gradle.kts
logging.captureStandardOutput(LogLevel.INFO)
println("A message which is logged at INFO level")
build.gradle
logging.captureStandardOutput LogLevel.INFO
println 'A message which is logged at INFO level'

要在任务执行期间更改标准输出或错误的日志级别,请使用 LoggingManager

build.gradle.kts
tasks.register("logInfo") {
    logging.captureStandardOutput(LogLevel.INFO)
    doFirst {
        println("A task message which is logged at INFO level")
    }
}
build.gradle
tasks.register('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 的日志内容

此功能已弃用,并将在下一个主要版本中删除,不提供替代方案。

配置缓存限制了自定义 Gradle 日志 UI 的能力。自定义日志记录器只能实现受支持的监听器接口。当配置缓存条目被重用时,这些接口不会收到事件,因为配置阶段被跳过。

您可以用自己的 UI 替换 Gradle 的大部分日志 UI。如果您想以某种方式自定义 UI(例如,记录更多或更少的信息或更改格式),可以这样做。只需使用 Gradle.useLogger(java.lang.Object) 方法替换日志记录即可。这可以从构建脚本、初始化脚本或通过嵌入式 API 访问。请注意,这将完全禁用 Gradle 的默认输出。下面是一个初始化脚本示例,它更改了任务执行和构建完成的日志记录方式

customLogger.init.gradle.kts
useLogger(CustomEventLogger())

@Suppress("deprecation")
class CustomEventLogger() : BuildAdapter(), TaskExecutionListener {

    override fun beforeExecute(task: Task) {
        println("[${task.name}]")
    }

    override fun afterExecute(task: Task, state: TaskState) {
        println()
    }

    override fun buildFinished(result: BuildResult) {
        println("build completed")
        if (result.failure != null) {
            (result.failure as Throwable).printStackTrace()
        }
    }
}
customLogger.init.gradle
useLogger(new CustomEventLogger())

@SuppressWarnings("deprecation")
class CustomEventLogger extends BuildAdapter implements TaskExecutionListener {

    void beforeExecute(Task task) {
        println "[$task.name]"
    }

    void afterExecute(Task task, TaskState state) {
        println()
    }
    
    void buildFinished(BuildResult result) {
        println 'build completed'
        if (result.failure != null) {
            result.failure.printStackTrace()
        }
    }
}
$ ./gradlew -I customLogger.init.gradle.kts build

> Task :compile
[compile]
compiling source

> Task :testCompile
[testCompile]
compiling test source

> Task :test
[test]
running unit tests

> Task :build
[build]

build completed
3 actionable tasks: 3 executed
$ ./gradlew -I customLogger.init.gradle build

> Task :compile
[compile]
compiling source

> Task :testCompile
[testCompile]
compiling test source

> Task :test
[test]
running unit tests

> Task :build
[build]

build completed
3 actionable tasks: 3 executed

您的日志记录器可以实现下面列出的任何监听器接口。当您注册日志记录器时,只替换其实现的接口的日志记录。其他接口的日志记录保持不变。您可以在构建生命周期事件中找到有关监听器接口的更多信息。


1. 不兼容配置缓存。