Log API enhancements and mojo MDC - #12690
Conversation
Backport four Log-related improvements from master to the 4.0.x branch
for inclusion in rc-7:
1. Log.trace() — new trace level (maps to SLF4J TRACE / JUL FINEST)
to separate Maven core internals from user-facing debug messages.
Currently -X floods debug output with resolver/interpolation details
that drown user-relevant diagnostics.
2. Log.child(name) — creates a sub-logger with an independently
filterable name (e.g. "CompilerMojo.diagnostics"), letting plugin
sub-components log under their own namespace.
3. Logger name alignment — Maven 4 Log now uses the mojo implementation
class name (e.g. "org.apache.maven.plugins.compiler.CompilerMojo")
instead of the goal name ("compiler:compile"). This matches what
Maven 3 mojos already use and enables standard SLF4J hierarchical
level configuration.
4. Mojo MDC propagation — sets "maven.mojo.id" (prefix:goal@executionId)
in the SLF4J MDC during mojo execution. All log messages — including
those arriving through the JUL-to-SLF4J bridge — now carry mojo
context, available to any SLF4J appender via %X{maven.mojo.id}.
Also fixes a pre-existing bug in DefaultLog where warn(Supplier, Throwable)
incorrectly delegated to logger.info() instead of logger.warn().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Align with master by wrapping the five xxx(Throwable) overloads in level-enabled checks, avoiding unnecessary method calls and empty string construction when the level is disabled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
Clean, well-scoped backport of Log API enhancements from #12572 to 4.0.x. All functional changes are correct, the bug fix (warn(Supplier, Throwable) delegating to logger.info() instead of logger.warn()) is verified, and the backport includes additional consistency improvements.
Notable observations:
- The backport correctly omits the
@sincetags that the original PR uses (4.1.0for trace methods). Since theLoginterface is@since 4.0.0and the 4.0.x branch has no per-method@sincetags, this is the right call. - The backport improves on the original by adding
isXxxEnabled()guards to the existingdebug(Throwable),info(Throwable),warn(Throwable), anderror(Throwable)methods, which previously called the logger unconditionally. This is a welcome consistency fix not in the original PR. - The
Loginterface is@Providerand@Experimental, so adding new abstract methods (trace methods) is safe — external implementations are not expected.
Minor items:
- The original PR #12572 adds
DefaultLogTest.javawith a test forchild(). This test was not included in the backport — consider adding it for parity. mojoSkipped()does not clear the mojo MDC. If a previous mojo set the MDC and a subsequent mojo is skipped, log messages duringmojoSkippedhandling would carry the stale mojo ID. This matches the original PR behavior and is a very minor edge case.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
Apply review fixes from #12694 to align the backport: - Log.java: make all 6 trace methods default (no-ops) to prevent AbstractMethodError for existing third-party Log implementors. isTraceEnabled() returns false by default. - ProjectBuildLogAppender: add FORKING_MOJO_ID ThreadLocal mirroring the existing FORKING_PROJECT_ID pattern. When setMojoId(null) is called, the forking mojo's ID is restored instead of clearing. - LoggingExecutionListener: save current mojoId in forkStarted(), clear forking mojoId in forkSucceeded/forkFailed. Fix cleanup ordering in mojoSucceeded/mojoFailed — delegate runs first, then MDC is cleared. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Applied review fixes from #12694 to align the backport: 1. 2. 3.
Build: compiles cleanly and passes all maven-core tests (562 tests, 2 pre-existing failures unrelated to logging). |
gnodet
left a comment
There was a problem hiding this comment.
Delta review — checking the latest commit e3c872f5 ("Address review: default trace methods and fork-aware mojoId").
The latest commit correctly addresses two important concerns:
-
Default trace methods in
Log.java— Essential for this backport. On 4.0.x, existing third-partyLogimplementations would getAbstractMethodErrorif these were abstract. The no-op defaults (isTraceEnabledreturns false, all trace overloads are no-ops) are the correct backward-compatible choice. -
Fork-aware mojoId (
FORKING_MOJO_IDThreadLocal +setForkingMojoId) — An improvement over the original PR #12572 on master, which does not have this pattern. It correctly mirrors the existingFORKING_PROJECT_IDsave/restore pattern, ensuring the forking mojo's MDC is restored after forked mojos complete.
Previous findings status:
| Finding | Status | Notes |
|---|---|---|
Missing DefaultLogTest.java |
Still open (minor) | Test-parity gap only — functionality works correctly |
mojoSkipped() doesn't clear MDC |
Still open (non-issue) | mojoSkipped is called for mojos that were never started, so MDC is already cleared by the preceding mojo's mojoSucceeded/mojoFailed |
Both remaining items are very minor and don't block the PR.
Additional observation: The ordering change in mojoSucceeded/mojoFailed (delegate runs before MDC clear) is a deliberate improvement — the delegate can still access the mojoId during its callback.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
- Add DefaultLogTest with 5 tests: warn/supplier regression, trace delegation, trace no-op guard, child() sub-logger, and default trace methods (AbstractMethodError prevention). - Clear mojo MDC in mojoSkipped() to prevent stale mojo context from leaking into subsequent log messages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
Delta review — checking commit 56f4be34 ("Address review: add DefaultLogTest and clear MDC on mojoSkipped").
Both remaining items from the previous review are now resolved:
| Finding | Status |
|---|---|
Missing DefaultLogTest.java |
✅ Resolved — added with 5 tests: childCreatesSubLogger, warnWithSupplierAndThrowableDelegatesToWarn, traceMethodsDelegateToSlf4jTrace, traceIsNoOpWhenDisabled, defaultTraceIsDisabled |
mojoSkipped() doesn't clear MDC |
✅ Resolved — now calls ProjectBuildLogAppender.setMojoId(null) after delegate, consistent with mojoSucceeded/mojoFailed |
The clearing pattern (clear after delegate call) is consistent across all three mojo lifecycle callbacks. The test suite also covers the warn(Supplier, Throwable) bug fix and trace backward compatibility.
All review findings across 4 rounds are now addressed. 👍
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
Summary
Four Log-related improvements for 4.0.x:
Log.trace()— new trace level (SLF4J TRACE / JUL FINEST) to separate Maven core internals from user-facing debug messages. Currently-Xfloods debug output with resolver/interpolation details that drown user-relevant diagnostics. All 6 trace methods havedefaultimplementations (no-ops) to preventAbstractMethodErrorfor existing third-partyLogimplementors.Log.child(name)— creates a sub-logger with an independently filterable name (e.g.CompilerMojo.diagnostics), letting plugin sub-components log under their own namespace.Lognow uses the mojo implementation class name (e.g.org.apache.maven.plugins.compiler.CompilerMojo) instead of the goal name (compiler:compile). This matches what Maven 3 mojos already use and enables standard SLF4J hierarchical level configuration.maven.mojo.id(prefix:goal@executionId) in the SLF4J MDC during mojo execution. All log messages — including those arriving through the JUL-to-SLF4J bridge — now carry mojo context, available to any SLF4J appender via%X{maven.mojo.id}. Fork-aware: saves and restores the forking mojo's ID across forked lifecycles.Also fixes a pre-existing bug where
DefaultLog.warn(Supplier, Throwable)delegated tologger.info()instead oflogger.warn(), and addsisXxxEnabled()guards to the existingdebug(Throwable),info(Throwable),warn(Throwable), anderror(Throwable)methods.Files changed
Log.javatrace()default methods +child()default methodDefaultLog.javaDefaultMavenPluginManager.javagetFullGoalName()→getImplementation()DefaultBuildPluginManager.javagetFullGoalName()→getImplementation()ProjectBuildLogAppender.javamaven.mojo.idMDC key + fork-awaresetMojoId()/setForkingMojoId()LoggingExecutionListener.javaRelated
Test plan
mvn test -pl impl/maven-core— 562 tests pass🤖 Generated with Claude Code