Skip to content

Console modes: --console=plain/rich/verbose/machine - #13180

Open
gnodet wants to merge 3 commits into
feature/build-reportfrom
feature/console-modes
Open

gnodet wants to merge 3 commits into
feature/build-reportfrom
feature/console-modes

Conversation

@gnodet

@gnodet gnodet commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Part 3 of the logging feature chain. Depends on #12695 (build report).

Adds the --console CLI flag with four output modes:

  • plain — compact one-line-per-module output, ideal for CI (auto-selected in CI environments)
  • rich — JLine status bar with live reactor progress (auto-selected on interactive TTYs)
  • verbose — full mojo-level output, current Maven 4.0 default behavior
  • machine — JSON lines: one typed JSON object per lifecycle event, designed for piping to external tools

Auto-detection (--console=auto, the default): CI → plain, interactive TTY → rich, otherwise → verbose.

Files changed (16 files, ~4000 insertions)

Area Files
API Options.java (+console())
Event loggers PlainExecutionEventLogger, RichBuildEventListener, RichExecutionEventLogger, MachineBuildEventListener, MachineExecutionEventLogger
CLI wiring CommonsCliOptions, LayeredOptions, LookupInvoker (preliminary interactive detection), MavenInvoker (console mode switch + transfer listener)
Existing logger ExecutionEventLogger (version info on failure)
Tests 5 test classes with full coverage

PR chain

# PR Feature
1 #12694 Logging foundation
2 #12695 Build report
3 This PR Console modes
4 #12698 Warning mode + diagnostics
5 #12699 mvnlog viewer
6 #12702 Structured problems pipeline
7 #12714 TRACE level migration

Test plan

  • mvn test -pl impl/maven-cli — all 692 tests pass
  • mvn test -pl impl/maven-core — all tests pass
  • CI validation

🤖 Generated with Claude Code

@gnodet

gnodet commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

One format worth considering for the machine-readable console mode: logfmt.

level=INFO  build=a1b2c3 module=my-app execution=maven-compiler-plugin:compile:default phase=compile ts=1234567890123 msg="Compiling 42 source files"
level=ERROR build=a1b2c3 module=my-app execution=maven-compiler-plugin:compile:default phase=compile ts=1234567890456 msg="Compilation failure"
level=INFO  build=a1b2c3 module=my-app execution=maven-compiler-plugin:compile:default result=FAILURE duration_ms=1823 msg="Mojo finished"

It sits nicely between plain text (human-readable) and JSON lines (fully structured): parseable by Loki, Vector, Grafana out of the box, but still legible with a plain cat.

The interesting property: with build + module + execution as grouping keys, the full hierarchy (modules → executions → log events + timing + results) can be reconstructed from the flat stream by any consumer.

Could be offered as a --console=logfmt option, or considered as the canonical machine format if we want to converge on a single representation.

@gnodet
gnodet force-pushed the feature/build-report branch 8 times, most recently from 7eaa538 to 869e497 Compare September 19, 2026 04:55

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Console modes review — overall this is solid. Three specific issues worth addressing before merge.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

MavenProject project = event.getProject();
MojoExecution mojo = event.getMojoExecution();

String mojoKey = project.getArtifactId() + ":" + mojo.getExecutionId() + ":" + mojo.getGoal();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✖️ Bug: missing — silently collides in multi-module builds

The key is not unique when two modules in the same reactor share the same (different s). in overwrites the prior entry; the subsequent in / returns or the wrong start time — producing zero or negative durations in the JSON output with no error.

correctly includes :

Same fix needed at lines 211 and 293.

} else {
logger.info(buffer.toString());
}
logger.info(buffer.toString());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✖️ Behavioral regression: downgraded from ERROR to INFO level

The original used for the status line, producing . This PR changes it to , producing .

The ANSI coloring () still makes the text visually red in terminals, but any tool that scans the log stream by level — CI scripts using , Maven wrappers, IDE build output parsers, test frameworks — will silently miss the failure signal. The level and the color serve different consumers.


// Reactor state
private volatile int totalProjects;
private volatile int currentVisitedProjectCount;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: with increment — use

is declared but incremented inside at line 155. provides visibility but not atomicity for compound read-modify-write; the block is what makes the increment correct. The modifier is redundant and misleading — it implies the field can be safely read-and-acted-upon outside the lock.

already uses for the same pattern. has the same issue (line 83):

Then in : , and in : — no block needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants