What is project.logger in a Gradle build, and how do you use it to print messages?
answer
- Logger extends SLF4J Logger
- lifecycle = default visible level
- use {} placeholders not concat
- available on Project, Task, Settings
- prefer over println
basics
~10 sproject.logger is Gradle's built-in logger. You call methods like logger.lifecycle("msg"), logger.info(...), logger.quiet(...), logger.error(...) instead of println to emit messages at the right log level.
solid answer
~30 sEvery Gradle `Project` (and `Task`) exposes a `logger` property of type `org.gradle.api.logging.Logger`. It is the idiomatic way to emit build output instead of `println`, because each message is tagged with a level and Gradle decides whether to show it based on the current verbosity. The everyday method is `logger.lifecycle("...")` — the default visible level, used for high-signal progress messages. Other methods map to levels: `quiet`, `info`, `debug`, `warn`, `error`. Because `Logger` extends SLF4J's `Logger`, you also get the standard SLF4J methods and `{}` placeholder formatting (`logger.info("Built {} in {} ms", name, ms)`), which avoids string concatenation when the level is disabled.
code
kotlin · 7 linestasks.register("report") {
doLast {
logger.lifecycle("Generating report...") // shown by default
logger.info("Scanned {} files", 42) // only with --info
logger.error("Missing config file") // always shown
}
}go deeper
Know that logger.lifecycle/info/error exist and are preferred over println for build output.
Explain that Logger extends SLF4J, the level-to-method mapping, and {} placeholder deferral.
Discuss obtaining a logger in a plugin via Logging.getLogger, and per-task vs per-project loggers.
Frame logging discipline as part of build observability and standardize level conventions across a multi-team build.
## What `project.logger` is Every Gradle `Project` object exposes a read-only `logger` property. Its type is `org.gradle.api.logging.Logger`, which **extends `org.slf4j.Logger`** — so it is both a Gradle logger (with Gradle-specific levels) and a fully standard SLF4J logger. The same `logger` is also available on `Task`, `Settings`, `Gradle`, and `Script`, so build scripts and plugins share one logging API. ## Why not `println`? `println` writes straight to `System.out`. Gradle *captures* standard out (see `captureStandardOutput`) and re-routes it, but you lose level information: a `println` cannot be suppressed when the user runs at a quieter level, and it bypasses Gradle's rich console rendering. Using `logger.<level>(...)` lets Gradle decide visibility based on the run's verbosity. ## The methods Gradle adds level-specific convenience methods on top of SLF4J: - `logger.error(...)` — failures. - `logger.warn(...)` — warnings. - `logger.lifecycle(...)` — **the default visible level**; progress/high-signal messages. - `logger.quiet(...)` — always shown unless `--quiet` hides everything below WARN? (no — QUIET is *above* lifecycle: shown even with `-q`). - `logger.info(...)` — shown with `-i`/`--info`. - `logger.debug(...)` — shown with `-d`/`--debug`. There are also generic overloads taking a `LogLevel`: `logger.log(LogLevel.INFO, "...")`. ## SLF4J placeholders Because it is an SLF4J `Logger`, use `{}` placeholders rather than concatenation: ```kotlin logger.info("Processed {} files in {} ms", count, elapsed) ``` If INFO is disabled, the arguments are never converted to strings — this is the standard SLF4J performance benefit. ## Where to get a logger - In a build script: just `logger`. - In a custom task: `logger` is inherited (a per-task logger). - In a plugin class with no project handy: `org.gradle.api.logging.Logging.getLogger(MyClass::class.java)`.
- Why is `logger.info("x={}", value)` better than `logger.info("x=" + value)`?The `{}` form defers string building: if INFO is disabled the arguments are never concatenated, saving the cost. The `+` form always builds the string regardless of level.
- What type does project.logger have, and why does that matter?`org.gradle.api.logging.Logger`, which extends `org.slf4j.Logger`. That means standard SLF4J methods work, plus Gradle adds `lifecycle` and `quiet`.
saying these in an interview costs you the question
- Saying you should use System.out.println for normal build messages.
- Claiming logger is only on Project (it is also on Task, Settings, Gradle).
- Thinking Gradle's Logger is unrelated to SLF4J.