Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,70 @@
@Experimental
@Provider
public interface Log {
/**
* {@return true if the <b>trace</b> error level is enabled}
*/
boolean isTraceEnabled();

/**
* Sends a message to the user in the <b>trace</b> error level.
* <p>
* Trace is the most verbose level, intended for Maven core internals
* such as resolver negotiation, model interpolation, and lifecycle
* ordering details. Use {@link #debug(CharSequence)} instead for
* messages that help <em>users</em> investigate their build
* (e.g. why a module was recompiled).
*
* @param content the message to log
*/
void trace(CharSequence content);

/**
* Sends a message (and accompanying exception) to the user at the <b>trace</b> error level.
* The error's stacktrace will be output when this error level is enabled.
*
* @param content the message to log
* @param error the error that caused this log
*/
void trace(CharSequence content, Throwable error);

/**
* Sends an exception to the user in the <b>trace</b> error level.
* The stack trace for this exception will be output when this error level is enabled.
*
* @param error the error that caused this log
*/
void trace(Throwable error);

/**
* Sends a lazily-computed message in the <b>trace</b> error level.
* The supplier is only evaluated if trace is enabled.
*
* @param content the message supplier
*/
void trace(Supplier<String> content);

/**
* Sends a lazily-computed message (and accompanying exception) in the <b>trace</b> error level.
* The supplier is only evaluated if trace is enabled.
*
* @param content the message supplier
* @param error the error that caused this log
*/
void trace(Supplier<String> content, Throwable error);

/**
* {@return true if the <b>debug</b> error level is enabled}
*/
boolean isDebugEnabled();

/**
* Sends a message to the user in the <b>debug</b> error level.
* <p>
* Debug is intended for messages that help <em>users</em> investigate
* their build — for example, why a module was recompiled or what
* classpath was resolved. For Maven core internals, use
* {@link #trace(CharSequence)} instead.
*
* @param content the message to log
*/
Expand Down Expand Up @@ -167,4 +224,27 @@ public interface Log {
void error(Supplier<String> content);

void error(Supplier<String> content, Throwable error);

/**
* Returns a child logger whose name is derived from this logger's name
* by appending a dot and the given suffix.
*
* <p>For example, if a plugin's logger is named
* {@code "org.apache.maven.plugins.compiler.CompilerMojo"},
* then {@code child("diagnostics")} returns a logger named
* {@code "org.apache.maven.plugins.compiler.CompilerMojo.diagnostics"}.
* This lets sub-components log under an independently filterable name
* without requiring a separate injection point.</p>
*
* <p>The default implementation returns {@code this}, so existing
* {@code Log} implementations continue to work without changes.
* Implementations that wrap a hierarchical logging backend (such as
* SLF4J) should override this to create a real child logger.</p>
*
* @param name the suffix to append (must not be {@code null} or blank)
* @return a child logger — never {@code null}
*/
default Log child(String name) {
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import org.apache.maven.api.plugin.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.util.Objects.requireNonNull;

Expand All @@ -32,6 +33,46 @@ public DefaultLog(Logger logger) {
this.logger = requireNonNull(logger);
}

@Override
public boolean isTraceEnabled() {
return logger.isTraceEnabled();
}

@Override
public void trace(CharSequence content) {
if (isTraceEnabled()) {
logger.trace(toString(content));
}
}

@Override
public void trace(CharSequence content, Throwable error) {
if (isTraceEnabled()) {
logger.trace(toString(content), error);
}
}

@Override
public void trace(Throwable error) {
if (isTraceEnabled()) {
logger.trace("", error);
}
}

@Override
public void trace(Supplier<String> content) {
if (isTraceEnabled()) {
logger.trace(content.get());
}
}

@Override
public void trace(Supplier<String> content, Throwable error) {
if (isTraceEnabled()) {
logger.trace(content.get(), error);
}
}

@Override
public void debug(CharSequence content) {
if (isDebugEnabled()) {
Expand All @@ -48,7 +89,9 @@ public void debug(CharSequence content, Throwable error) {

@Override
public void debug(Throwable error) {
logger.debug("", error);
if (isDebugEnabled()) {
logger.debug("", error);
}
}

@Override
Expand Down Expand Up @@ -81,7 +124,9 @@ public void info(CharSequence content, Throwable error) {

@Override
public void info(Throwable error) {
logger.info("", error);
if (isInfoEnabled()) {
logger.info("", error);
}
}

@Override
Expand Down Expand Up @@ -114,7 +159,9 @@ public void warn(CharSequence content, Throwable error) {

@Override
public void warn(Throwable error) {
logger.warn("", error);
if (isWarnEnabled()) {
logger.warn("", error);
}
}

@Override
Expand All @@ -127,7 +174,7 @@ public void warn(Supplier<String> content) {
@Override
public void warn(Supplier<String> content, Throwable error) {
if (isWarnEnabled()) {
logger.info(content.get(), error);
logger.warn(content.get(), error);
}
}

Expand All @@ -147,7 +194,9 @@ public void error(CharSequence content, Throwable error) {

@Override
public void error(Throwable error) {
logger.error("", error);
if (isErrorEnabled()) {
logger.error("", error);
}
}

@Override
Expand Down Expand Up @@ -184,6 +233,12 @@ public boolean isErrorEnabled() {
return logger.isErrorEnabled();
}

@Override
public Log child(String name) {
requireNonNull(name, "name");
return new DefaultLog(LoggerFactory.getLogger(logger.getName() + "." + name));
}

private String toString(CharSequence content) {
return content != null ? content.toString() : "";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,22 @@ public void projectSkipped(ExecutionEvent event) {
@Override
public void mojoStarted(ExecutionEvent event) {
setMdc(event);
setMojoMdc(event);
buildEventListener.mojoStarted(event);
delegate.mojoStarted(event);
}

@Override
public void mojoSucceeded(ExecutionEvent event) {
setMdc(event);
ProjectBuildLogAppender.setMojoId(null);
delegate.mojoSucceeded(event);
}

@Override
public void mojoFailed(ExecutionEvent event) {
setMdc(event);
ProjectBuildLogAppender.setMojoId(null);
delegate.mojoFailed(event);
}

Expand Down Expand Up @@ -187,4 +190,12 @@ private void setMdc(ExecutionEvent event) {
ProjectBuildLogAppender.setProjectId(event.getProject().getArtifactId());
}
}

private void setMojoMdc(ExecutionEvent event) {
if (event.getMojoExecution() != null) {
String mojoId = event.getMojoExecution().getMojoDescriptor().getFullGoalName() + "@"
+ event.getMojoExecution().getExecutionId();
ProjectBuildLogAppender.setMojoId(mojoId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
public class ProjectBuildLogAppender implements AutoCloseable {

private static final String KEY_PROJECT_ID = "maven.project.id";
private static final String KEY_MOJO_ID = "maven.mojo.id";
private static final ThreadLocal<String> PROJECT_ID = new InheritableThreadLocal<>();
private static final ThreadLocal<String> MOJO_ID = new InheritableThreadLocal<>();
private static final ThreadLocal<String> FORKING_PROJECT_ID = new InheritableThreadLocal<>();

public static String getProjectId() {
Expand All @@ -52,6 +54,31 @@ public static void setProjectId(String projectId) {
}
}

public static String getMojoId() {
return MOJO_ID.get();
}

/**
* Sets or clears the mojo execution identifier in both the thread-local
* and the SLF4J MDC. The value is available to any SLF4J appender via
* the MDC key {@code maven.mojo.id} and to JUL-bridged messages through
* the same MDC path.
* <p>
* Format: {@code "prefix:goal@executionId"}
* (e.g. {@code "compiler:compile@default-compile"}).
*
* @param mojoId the mojo identifier, or {@code null} to clear
*/
public static void setMojoId(String mojoId) {
if (mojoId != null) {
MOJO_ID.set(mojoId);
MDC.put(KEY_MOJO_ID, mojoId);
} else {
MOJO_ID.remove();
MDC.remove(KEY_MOJO_ID);
}
}

public static void setForkingProjectId(String forkingProjectId) {
if (forkingProjectId != null) {
FORKING_PROJECT_ID.set(forkingProjectId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public void executeMojo(MavenSession session, MojoExecution mojoExecution)
scope.seed(
org.apache.maven.api.plugin.Log.class,
new DefaultLog(LoggerFactory.getLogger(
mojoExecution.getMojoDescriptor().getFullGoalName())));
mojoExecution.getMojoDescriptor().getImplementation())));
InternalMavenSession sessionV4 = InternalMavenSession.from(session.getSession());
scope.seed(Project.class, sessionV4.getProject(project));
scope.seed(org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(sessionV4, mojoExecution));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ private <T> T loadV4Mojo(

org.apache.maven.api.MojoExecution execution = new DefaultMojoExecution(sessionV4, mojoExecution);
org.apache.maven.api.plugin.Log log = new DefaultLog(
LoggerFactory.getLogger(mojoExecution.getMojoDescriptor().getFullGoalName()));
LoggerFactory.getLogger(mojoExecution.getMojoDescriptor().getImplementation()));
try {
Injector injector = Injector.create();
injector.discover(pluginRealm);
Expand Down
Loading