skip to content

How would you choose Gradle log verbosity and stacktrace settings for a CI pipeline versus local development, and how do you set them without changing every command?

level: seniorimportance: should knowfreq 30%

answer

  1. local: LIFECYCLE default, escalate -i/-s on demand
  2. CI: LIFECYCLE + --stacktrace, avoid default --debug
  3. --console=plain for clean CI logs
  4. set in gradle.properties / GRADLE_OPTS, not per-command
  5. debug = 10-100x log volume

basics

~20 s

Locally keep the LIFECYCLE default and add -i/-s only when debugging. On CI, default to LIFECYCLE plus --stacktrace so failures are diagnosable, avoid --debug (huge logs), and set it via org.gradle.* or GRADLE_OPTS/args rather than per-command flags.

solid answer

~40 s

**Local:** keep the **LIFECYCLE** default for clean, readable output; reach for `-i` to diagnose cache/incremental issues and `-s` for a stacktrace on a failure — ad hoc, not always-on. **CI:** the goal is *diagnosable failures without log bloat*. A common baseline is LIFECYCLE verbosity **plus `--stacktrace`**, so any failure carries a truncated trace; reserve `--full-stacktrace`/`--debug` for a targeted re-run because DEBUG output is enormous and inflates log storage and parse time. Pair this with `--console=plain` on CI so progress bars don't corrupt log files. To avoid sprinkling flags on every invocation, set defaults centrally: `org.gradle.console=plain` in `gradle.properties`, common args via a CI variable or `GRADLE_OPTS`, and let the verbosity flag be the one thing the job passes. Treat verbosity as a policy: clean by default, escalate on demand.

code

bash · 4 lines
bash
# CI: diagnosable failures, bounded log volume
./gradlew build --stacktrace --console=plain
# Escalate only when investigating:
./gradlew build --info --full-stacktrace

go deeper

for a junior

Know that you escalate verbosity on demand and that DEBUG is very noisy.

for a middle

Distinguish local (clean default) from CI (LIFECYCLE + --stacktrace) and name --console=plain.

for a senior

Justify avoiding default DEBUG by log-volume/cost and design an escalation path plus centralized config.

for a principal

Set an org-wide logging policy balancing diagnosability, storage cost, and reproducibility, codified in gradle.properties/CI.

## Two different goals **Local dev** optimizes for a *readable, interactive* console; **CI** optimizes for *diagnosable, machine-parseable, cost-bounded* logs. The same flags serve both, but the defaults differ. ## Local recommendation - Default **LIFECYCLE** — uncluttered. - Escalate **on demand**: `-i` when a task rebuilds unexpectedly (cache/incremental debugging), `-s` when a failure's message isn't enough. - Avoid making `-d` a habit; it's a targeted tool. ## CI recommendation - **Verbosity:** LIFECYCLE (or INFO if you actively triage cache behavior). **Avoid DEBUG by default** — it can multiply log size by 10-100x, slowing log upload, raising storage cost, and burying signal. - **Stacktrace:** add **`--stacktrace`** so every failure is actionable without a re-run. Keep `--full-stacktrace` for a manual escalation job. - **Console:** `--console=plain` (or `org.gradle.console=plain`) so rich/progress output doesn't write control characters into the captured log. - **Escalation path:** a separate 'debug' workflow or a manual re-run that adds `-i`/`-d`/`-S` only when investigating. ## Setting it once, not per-command You rarely want flags on every `gradle` line: ```properties # gradle.properties (checked in or CI-only) org.gradle.console=plain org.gradle.warning.mode=all ``` ```bash # CI environment — one place to control args export GRADLE_OPTS="-Dorg.gradle.console=plain" ./gradlew build --stacktrace ``` Keep the per-job command minimal (`build --stacktrace`) and push stable choices (console, warning mode) into `gradle.properties` so they apply uniformly. ## Trade-offs to articulate - **Signal vs. volume:** DEBUG maximizes signal but destroys readability and costs storage/time. Default low, escalate deliberately. - **Reproducibility:** centralizing settings in `gradle.properties`/env avoids per-developer drift and 'works for me' flag differences. - **Failure ergonomics:** always-on `--stacktrace` on CI removes the 'please re-run with --stacktrace' round-trip that wastes a whole CI cycle.

  • Why avoid --debug as a CI default?
    DEBUG can balloon log size by 10-100x, slowing log upload, increasing storage cost, and burying the actual failure signal. Use it only for a targeted re-run.
  • Why add --stacktrace on CI by default?
    It makes every failure carry a trace, removing the wasted CI cycle spent re-running just to get 'Run with --stacktrace'.
  • How do you keep verbosity settings consistent across developers and CI?
    Push stable choices (console mode, warning mode) into gradle.properties or GRADLE_OPTS instead of per-command flags, so they apply uniformly.

saying these in an interview costs you the question

  • Defaulting CI to --debug 'to be safe' — it bloats logs and obscures failures.
  • Putting verbosity flags on every command instead of centralizing stable settings.
  • Forgetting --console=plain on CI, letting progress/control characters corrupt captured logs.

context