Fix logging to use an inheritable thread local, fixes #295

This commit is contained in:
Guillaume Nodet
2021-01-05 11:36:59 +01:00
parent 4ae20969b5
commit e639be9a9f
10 changed files with 209 additions and 12 deletions

View File

@@ -64,7 +64,6 @@ import org.mvndaemon.mvnd.logging.smart.AbstractLoggingSpy;
import org.mvndaemon.mvnd.logging.smart.ProjectBuildLogAppender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import sun.misc.Signal;
import sun.misc.SignalHandler;
@@ -547,7 +546,7 @@ public class Server implements AutoCloseable, Runnable {
loggingSpy.fail(t);
} finally {
sender.join();
MDC.remove(ProjectBuildLogAppender.KEY_PROJECT_ID);
ProjectBuildLogAppender.setProjectId(null);
}
} catch (Throwable t) {
LOGGER.error("Error while building project", t);

View File

@@ -34,7 +34,6 @@ import org.mvndaemon.mvnd.daemon.Connection;
import org.mvndaemon.mvnd.logging.smart.ProjectBuildLogAppender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
@Named
@Priority(10)
@@ -147,7 +146,7 @@ public class DaemonPrompter extends AbstractInputHandler implements Prompter, In
private void doDisplay(String message) throws IOException {
try {
Connection con = Objects.requireNonNull(Connection.getCurrent());
String projectId = MDC.get(ProjectBuildLogAppender.KEY_PROJECT_ID);
String projectId = ProjectBuildLogAppender.getProjectId();
Message.ProjectEvent msg = Message.display(projectId, message);
LOGGER.info("Sending display request: " + msg);
con.dispatch(msg);
@@ -159,7 +158,7 @@ public class DaemonPrompter extends AbstractInputHandler implements Prompter, In
private String doPrompt(String message, boolean password) throws IOException {
try {
Connection con = Objects.requireNonNull(Connection.getCurrent());
String projectId = MDC.get(ProjectBuildLogAppender.KEY_PROJECT_ID);
String projectId = ProjectBuildLogAppender.getProjectId();
String uid = UUID.randomUUID().toString();
Message.Prompt msg = new Message.Prompt(projectId, uid, message, password);
LOGGER.info("Requesting prompt: " + msg);

View File

@@ -20,7 +20,6 @@ package org.mvndaemon.mvnd.logging.internal;
import org.codehaus.plexus.logging.Logger;
import org.mvndaemon.mvnd.logging.smart.ProjectBuildLogAppender;
import org.slf4j.MDC;
/**
* Adapt an SLF4J logger to a Plexus logger, ignoring Plexus logger API parts that are not classical and
@@ -42,7 +41,7 @@ public class Slf4jLogger
public Slf4jLogger(org.slf4j.Logger logger) {
this.logger = logger;
this.projectId = MDC.get(ProjectBuildLogAppender.KEY_PROJECT_ID);
this.projectId = ProjectBuildLogAppender.getProjectId();
}
public void debug(String message) {
@@ -140,8 +139,8 @@ public class Slf4jLogger
}
private void setMdc() {
if (projectId != null && MDC.get(ProjectBuildLogAppender.KEY_PROJECT_ID) == null) {
MDC.put(ProjectBuildLogAppender.KEY_PROJECT_ID, projectId);
if (projectId != null && ProjectBuildLogAppender.getProjectId() == null) {
ProjectBuildLogAppender.setProjectId(projectId);
}
}

View File

@@ -17,7 +17,6 @@ package org.mvndaemon.mvnd.logging.smart;
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.execution.ExecutionListener;
import org.slf4j.MDC;
public class LoggingExecutionListener implements ExecutionListener {
@@ -141,7 +140,7 @@ public class LoggingExecutionListener implements ExecutionListener {
private void setMdc(ExecutionEvent event) {
if (event.getProject() != null) {
MDC.put(ProjectBuildLogAppender.KEY_PROJECT_ID, event.getProject().getArtifactId());
ProjectBuildLogAppender.setProjectId(event.getProject().getArtifactId());
}
}
}

View File

@@ -47,6 +47,7 @@ public class LoggingOutputStream extends FilterOutputStream {
super.write(b);
if (buf.isEol()) {
String line = new String(buf.toByteArray(), 0, buf.size() - LINE_SEP.length);
ProjectBuildLogAppender.updateMdc();
consumer.accept(line);
buf.reset();
}

View File

@@ -23,13 +23,39 @@ import ch.qos.logback.core.AppenderBase;
import java.util.Map;
import org.apache.maven.shared.utils.logging.LoggerLevelRenderer;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.slf4j.MDC;
/**
* This Maven-specific appender outputs project build log messages
* to the smart logging system.
*/
public class ProjectBuildLogAppender extends AppenderBase<ILoggingEvent> {
public static final String KEY_PROJECT_ID = "maven.project.id";
private static final String KEY_PROJECT_ID = "maven.project.id";
private static final ThreadLocal<String> PROJECT_ID = new InheritableThreadLocal<>();
public static String getProjectId() {
return PROJECT_ID.get();
}
public static void setProjectId(String projectId) {
if (projectId != null) {
PROJECT_ID.set(projectId);
MDC.put(KEY_PROJECT_ID, projectId);
} else {
PROJECT_ID.remove();
MDC.remove(KEY_PROJECT_ID);
}
}
public static void updateMdc() {
String id = getProjectId();
if (id != null) {
MDC.put(KEY_PROJECT_ID, id);
} else {
MDC.remove(KEY_PROJECT_ID);
}
}
private String pattern;
private PatternLayout layout;

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvndaemon.mvnd.it;
import java.io.IOException;
import javax.inject.Inject;
import org.junit.jupiter.api.Test;
import org.mvndaemon.mvnd.assertj.TestClientOutput;
import org.mvndaemon.mvnd.client.Client;
import org.mvndaemon.mvnd.client.DaemonParameters;
import org.mvndaemon.mvnd.junit.MvndTest;
@MvndTest(projectDir = "src/test/projects/exec-output")
public class ExecOutputTest {
@Inject
Client client;
@Inject
DaemonParameters parameters;
@Test
void cleanInstall() throws IOException, InterruptedException {
final TestClientOutput output = new TestClientOutput();
client.execute(output, "clean", "verify", "-e", "-Dmvnd.log.level=DEBUG").assertSuccess();
output.messagesToString()
.contains("ProjectLogMessage{projectId='exec-output', message='[INFO] [stdout] Hello world!'}");
}
}

View File

@@ -0,0 +1,3 @@
-Dmaven.wagon.httpconnectionManager.ttlSeconds=120
-Dmaven.wagon.http.retryHandler.requestSentEnabled=true
-Dmaven.wagon.http.retryHandler.count=10

View File

@@ -0,0 +1,103 @@
<!--
Copyright 2019 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.mvndaemon.mvnd.test.exec-output</groupId>
<artifactId>exec-output</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven-clean-plugin.version>2.5</maven-clean-plugin.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<maven-install-plugin.version>2.4</maven-install-plugin.version>
<maven-resources-plugin.version>2.6</maven-resources-plugin.version>
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
<exec-maven-plugin.version>3.0.0</exec-maven-plugin.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven-clean-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>${maven-install-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven-resources-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${exec-maven-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>run</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<useMavenLogger>false</useMavenLogger>
<executable>java</executable>
<longClasspath>true</longClasspath>
<arguments>
<argument>-classpath</argument>
<classpath/>
<argument>org.mvndaemon.mvnd.test.Greeting</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvndaemon.mvnd.test;
public class Greeting {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}