When and why would you guard a logging call with logger.isInfoEnabled() or isDebugEnabled()?
answer
- {} defers concat, guard defers arg-building
- isDebugEnabled / isInfoEnabled
- generic isEnabled(LogLevel)
- guard only when args are expensive
- no side effects in log blocks
basics
~10 sWrap a log call in an is...Enabled() check when building the message is expensive. The guard skips that work entirely when the level is off, instead of computing a string that gets thrown away.
solid answer
~30 sGradle's `Logger` inherits SLF4J's level-check methods: `isDebugEnabled()`, `isInfoEnabled()`, `isWarnEnabled()`, `isErrorEnabled()`, plus Gradle's `isLifecycleEnabled()`/`isQuietEnabled()` and the generic `isEnabled(LogLevel)`. For ordinary messages you do not need them — `{}` placeholders already defer argument-to-string conversion. The guard pays off when *constructing the arguments themselves* is costly: iterating a big collection, serializing an object, or calling an expensive method just to log it. Without the guard you do that work even when DEBUG is off; with it you skip the whole block. So the rule is: use `{}` placeholders by default, and add an `if (logger.isDebugEnabled())` guard only around genuinely expensive message preparation.
code
kotlin · 7 lines// Expensive argument -> guard it
if (logger.isDebugEnabled()) {
logger.debug("Resolved graph: {}", configurations.compileClasspath.get().files.joinToString())
}
// Cheap args -> placeholders are enough, no guard
logger.info("Compiled {} sources", sourceCount)go deeper
Know placeholders exist; the guard nuance is usually middle+.
Explain the difference between concatenation deferral (placeholders) and argument-construction deferral (the guard).
Discuss build-scale impact (per-task overhead) and the no-side-effects rule for log blocks.
Codify a logging-cost convention so debug instrumentation never penalizes normal CI runs.
## The two layers of deferral ### 1. Placeholder deferral (cheap, always do this) SLF4J's `{}` form avoids string concatenation when the level is disabled: ```kotlin logger.debug("User {} has {} roles", user.id, roles.size) ``` If DEBUG is off, no string is built. This covers most cases and needs no guard. ### 2. Argument-construction deferral (the guard) Placeholders still **evaluate the arguments** before the call. If an argument is itself expensive to compute, you have already paid that cost: ```kotlin // roles.joinToString runs even if DEBUG is disabled logger.debug("Roles: {}", roles.joinToString()) ``` Guarding skips the computation entirely: ```kotlin if (logger.isDebugEnabled()) { logger.debug("Roles: {}", roles.joinToString()) } ``` ## Available checks on Gradle's Logger - SLF4J: `isTraceEnabled()`, `isDebugEnabled()`, `isInfoEnabled()`, `isWarnEnabled()`, `isErrorEnabled()`. - Gradle additions: `isLifecycleEnabled()`, `isQuietEnabled()`, and the generic `isEnabled(LogLevel.INFO)`. ## When it matters in a build Gradle builds can configure thousands of tasks; a debug log that serializes a dependency graph or walks a file tree on every task would slow even non-debug runs if unguarded. That is exactly where the guard earns its keep. ## Rule of thumb - Default: `{}` placeholders, no guard. - Add a guard only when preparing the *arguments* is itself expensive. - Never put side effects inside the guarded block that the build relies on — logging must stay side-effect free.
- If you already use {} placeholders, is a guard still ever needed?Yes — placeholders skip string concatenation but still evaluate the argument expressions. If building an argument is expensive, guard the call to skip that computation when the level is off.
- Is there a generic level-check method?Yes, logger.isEnabled(LogLevel) takes any LogLevel, including the Gradle-specific LIFECYCLE and QUIET.
saying these in an interview costs you the question
- Guarding every single log statement, adding noise for no benefit on cheap messages.
- Putting build-critical side effects inside an isDebugEnabled() block.
- Believing {} placeholders avoid evaluating the argument expressions themselves.