mirror of
https://github.com/jlengrand/helidon.git
synced 2026-03-10 08:21:17 +00:00
MDC logging support (#2479)
MDC logging support Signed-off-by: David Kral <david.k.kral@oracle.com>
This commit is contained in:
21
bom/pom.xml
21
bom/pom.xml
@@ -841,6 +841,27 @@
|
|||||||
<artifactId>helidon-microprofile-tests-junit5</artifactId>
|
<artifactId>helidon-microprofile-tests-junit5</artifactId>
|
||||||
<version>${helidon.version}</version>
|
<version>${helidon.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Logging -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<artifactId>helidon-logging-common</artifactId>
|
||||||
|
<version>${helidon.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<artifactId>helidon-logging-jul</artifactId>
|
||||||
|
<version>${helidon.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<artifactId>helidon-logging-slf4j</artifactId>
|
||||||
|
<version>${helidon.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<artifactId>helidon-logging-log4j</artifactId>
|
||||||
|
<version>${helidon.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -25,7 +25,10 @@ import java.util.regex.Pattern;
|
|||||||
/**
|
/**
|
||||||
* A {@link StreamHandler} that writes to {@link System#out standard out} and uses a {@link ThreadFormatter} for formatting.
|
* A {@link StreamHandler} that writes to {@link System#out standard out} and uses a {@link ThreadFormatter} for formatting.
|
||||||
* Sets the level to {@link Level#ALL} so that level filtering is performed solely by the loggers.
|
* Sets the level to {@link Level#ALL} so that level filtering is performed solely by the loggers.
|
||||||
|
*
|
||||||
|
* @deprecated use io.helidon.logging.jul.HelidonConsoleHandler from helidon-logging-jul module instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "2.1.1")
|
||||||
public class HelidonConsoleHandler extends StreamHandler {
|
public class HelidonConsoleHandler extends StreamHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,6 +43,9 @@ public class HelidonConsoleHandler extends StreamHandler {
|
|||||||
setOutputStream(System.out);
|
setOutputStream(System.out);
|
||||||
setLevel(Level.ALL); // Handlers should not filter, loggers should
|
setLevel(Level.ALL); // Handlers should not filter, loggers should
|
||||||
setFormatter(new ThreadFormatter());
|
setFormatter(new ThreadFormatter());
|
||||||
|
System.out.println("You are using deprecated logging handler -> io.helidon.common.HelidonConsoleHandler "
|
||||||
|
+ "Please use helidon-logging-jul module and change your handler to "
|
||||||
|
+ "io.helidon.logging.jul.HelidonConsoleHandler");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -42,5 +42,9 @@
|
|||||||
<artifactId>hamcrest-all</artifactId>
|
<artifactId>hamcrest-all</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.common</groupId>
|
||||||
|
<artifactId>helidon-common-service-loader</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,8 +16,11 @@
|
|||||||
package io.helidon.common.context;
|
package io.helidon.common.context;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@@ -26,7 +29,15 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import io.helidon.common.context.spi.DataPropagationProvider;
|
||||||
|
import io.helidon.common.serviceloader.HelidonServiceLoader;
|
||||||
|
|
||||||
class ContextAwareExecutorImpl implements ContextAwareExecutorService {
|
class ContextAwareExecutorImpl implements ContextAwareExecutorService {
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private static final List<DataPropagationProvider> PROVIDERS = HelidonServiceLoader
|
||||||
|
.builder(ServiceLoader.load(DataPropagationProvider.class)).build().asList();
|
||||||
|
|
||||||
private final ExecutorService delegate;
|
private final ExecutorService delegate;
|
||||||
|
|
||||||
ContextAwareExecutorImpl(ExecutorService toWrap) {
|
ContextAwareExecutorImpl(ExecutorService toWrap) {
|
||||||
@@ -112,21 +123,39 @@ class ContextAwareExecutorImpl implements ContextAwareExecutorService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings(value = "unchecked")
|
||||||
protected <T> Callable<T> wrap(Callable<T> task) {
|
protected <T> Callable<T> wrap(Callable<T> task) {
|
||||||
Optional<Context> context = Contexts.context();
|
Optional<Context> context = Contexts.context();
|
||||||
|
|
||||||
if (context.isPresent()) {
|
if (context.isPresent()) {
|
||||||
return () -> Contexts.runInContext(context.get(), task);
|
Map<Class<?>, Object> properties = new HashMap<>();
|
||||||
|
PROVIDERS.forEach(provider -> properties.put(provider.getClass(), provider.data()));
|
||||||
|
return () -> {
|
||||||
|
try {
|
||||||
|
PROVIDERS.forEach(provider -> provider.propagateData(properties.get(provider.getClass())));
|
||||||
|
return Contexts.runInContext(context.get(), task);
|
||||||
|
} finally {
|
||||||
|
PROVIDERS.forEach(DataPropagationProvider::clearData);
|
||||||
|
}
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings(value = "unchecked")
|
||||||
protected Runnable wrap(Runnable command) {
|
protected Runnable wrap(Runnable command) {
|
||||||
Optional<Context> context = Contexts.context();
|
Optional<Context> context = Contexts.context();
|
||||||
|
|
||||||
if (context.isPresent()) {
|
if (context.isPresent()) {
|
||||||
return () -> Contexts.runInContext(context.get(), command);
|
Map<Class<?>, Object> properties = new HashMap<>();
|
||||||
|
PROVIDERS.forEach(provider -> properties.put(provider.getClass(), provider.data()));
|
||||||
|
return () -> {
|
||||||
|
try {
|
||||||
|
PROVIDERS.forEach(provider -> provider.propagateData(properties.get(provider.getClass())));
|
||||||
|
Contexts.runInContext(context.get(), command);
|
||||||
|
} finally {
|
||||||
|
PROVIDERS.forEach(DataPropagationProvider::clearData);
|
||||||
|
}
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.common.context.spi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is SPI provider which helps user to propagate values from one thread to another.
|
||||||
|
*
|
||||||
|
* Every provider has its method {@link #data()} invoked before thread switch, to obtain
|
||||||
|
* value for propagation. After the thread is switched, the new thread executes
|
||||||
|
* {@link #propagateData(Object)} to propagate data.
|
||||||
|
*
|
||||||
|
* @param <T> an actual type of the data which will be propagated
|
||||||
|
*/
|
||||||
|
public interface DataPropagationProvider<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return data that should be propagated.
|
||||||
|
*
|
||||||
|
* @return data for propagation
|
||||||
|
*/
|
||||||
|
T data();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Propagates the data to be used by the new thread.
|
||||||
|
*
|
||||||
|
* @param data data for propagation
|
||||||
|
*/
|
||||||
|
void propagateData(T data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the propagated date from the new thread when it finishes.
|
||||||
|
*/
|
||||||
|
void clearData();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider for data propagation between threads in executor service.
|
||||||
|
*/
|
||||||
|
package io.helidon.common.context.spi;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,6 +20,10 @@
|
|||||||
module io.helidon.common.context {
|
module io.helidon.common.context {
|
||||||
requires java.logging;
|
requires java.logging;
|
||||||
requires io.helidon.common;
|
requires io.helidon.common;
|
||||||
|
requires io.helidon.common.serviceloader;
|
||||||
|
|
||||||
exports io.helidon.common.context;
|
exports io.helidon.common.context;
|
||||||
|
exports io.helidon.common.context.spi;
|
||||||
|
|
||||||
|
uses io.helidon.common.context.spi.DataPropagationProvider;
|
||||||
}
|
}
|
||||||
|
|||||||
6
dependencies/pom.xml
vendored
6
dependencies/pom.xml
vendored
@@ -79,6 +79,7 @@
|
|||||||
<version.lib.jsonp-impl>1.1.6</version.lib.jsonp-impl>
|
<version.lib.jsonp-impl>1.1.6</version.lib.jsonp-impl>
|
||||||
<version.lib.junit>5.6.2</version.lib.junit>
|
<version.lib.junit>5.6.2</version.lib.junit>
|
||||||
<version.lib.junit4>4.13.1</version.lib.junit4>
|
<version.lib.junit4>4.13.1</version.lib.junit4>
|
||||||
|
<version.lib.log4j>2.13.3</version.lib.log4j>
|
||||||
<version.lib.mariadb-java-client>2.6.2</version.lib.mariadb-java-client>
|
<version.lib.mariadb-java-client>2.6.2</version.lib.mariadb-java-client>
|
||||||
<version.lib.maven-wagon>2.10</version.lib.maven-wagon>
|
<version.lib.maven-wagon>2.10</version.lib.maven-wagon>
|
||||||
<version.lib.microprofile-config>1.4</version.lib.microprofile-config>
|
<version.lib.microprofile-config>1.4</version.lib.microprofile-config>
|
||||||
@@ -742,6 +743,11 @@
|
|||||||
<artifactId>slf4j-simple</artifactId>
|
<artifactId>slf4j-simple</artifactId>
|
||||||
<version>${version.lib.slf4j}</version>
|
<version>${version.lib.slf4j}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
<version>${version.lib.log4j}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.smallrye</groupId>
|
<groupId>io.smallrye</groupId>
|
||||||
|
|||||||
37
logging/common/pom.xml
Normal file
37
logging/common/pom.xml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
~
|
||||||
|
~ 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="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>helidon-logging-project</artifactId>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<version>2.1.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>helidon-logging-common</artifactId>
|
||||||
|
<name>Helidon Logging Common</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.common</groupId>
|
||||||
|
<artifactId>helidon-common-service-loader</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.common;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
import io.helidon.common.serviceloader.HelidonServiceLoader;
|
||||||
|
import io.helidon.logging.common.spi.MdcProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon MDC delegates values across all of the supported logging frameworks on the classpath.
|
||||||
|
*/
|
||||||
|
public class HelidonMdc {
|
||||||
|
|
||||||
|
private static final List<MdcProvider> MDC_PROVIDERS = HelidonServiceLoader
|
||||||
|
.builder(ServiceLoader.load(MdcProvider.class)).build().asList();
|
||||||
|
|
||||||
|
private HelidonMdc() {
|
||||||
|
throw new UnsupportedOperationException("This class cannot be instantiated");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Propagate value to all of the {@link MdcProvider} registered via SPI.
|
||||||
|
*
|
||||||
|
* @param key entry key
|
||||||
|
* @param value entry value
|
||||||
|
*/
|
||||||
|
public static void set(String key, String value) {
|
||||||
|
MDC_PROVIDERS.forEach(provider -> provider.put(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove value with the specific key from all of the instances of {@link MdcProvider}.
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
*/
|
||||||
|
public static void remove(String key) {
|
||||||
|
MDC_PROVIDERS.forEach(provider -> provider.remove(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all of the entries bound to the current thread from the instances of {@link MdcProvider}.
|
||||||
|
*/
|
||||||
|
public static void clear() {
|
||||||
|
MDC_PROVIDERS.forEach(MdcProvider::clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the first value found to the specific key.
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @return found value bound to key
|
||||||
|
*/
|
||||||
|
public static Optional<String> get(String key) {
|
||||||
|
return MDC_PROVIDERS.stream()
|
||||||
|
.map(provider -> provider.get(key))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon MDC support for delegation of the MDC values to all of the logging frameworks.
|
||||||
|
*/
|
||||||
|
package io.helidon.logging.common;
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.common.spi;
|
||||||
|
|
||||||
|
import io.helidon.logging.common.HelidonMdc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider which is used to propagate values passed from {@link HelidonMdc} to the
|
||||||
|
* corresponding logging framework MDC storage.
|
||||||
|
*/
|
||||||
|
public interface MdcProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set value to the specific logging framework MDC storage.
|
||||||
|
* @param key entry key
|
||||||
|
* @param value entry value
|
||||||
|
*/
|
||||||
|
void put(String key, String value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove value bound to the key from the specific logging framework MDC storage.
|
||||||
|
*
|
||||||
|
* @param key entry to remove
|
||||||
|
*/
|
||||||
|
void remove(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all of the MDC values from the specific logging framework MDC storage.
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value bound to the specific key.
|
||||||
|
*
|
||||||
|
* @param key entry key
|
||||||
|
* @return value bound to the key
|
||||||
|
*/
|
||||||
|
String get(String key);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This package provides interface for an actual MDC support implementation.
|
||||||
|
*/
|
||||||
|
package io.helidon.logging.common.spi;
|
||||||
28
logging/common/src/main/java/module-info.java
Normal file
28
logging/common/src/main/java/module-info.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon logging.
|
||||||
|
*/
|
||||||
|
module io.helidon.logging.common {
|
||||||
|
requires io.helidon.common.serviceloader;
|
||||||
|
|
||||||
|
exports io.helidon.logging.common;
|
||||||
|
exports io.helidon.logging.common.spi;
|
||||||
|
|
||||||
|
uses io.helidon.logging.common.spi.MdcProvider;
|
||||||
|
|
||||||
|
}
|
||||||
56
logging/jul/pom.xml
Normal file
56
logging/jul/pom.xml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
~
|
||||||
|
~ 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="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>helidon-logging-project</artifactId>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<version>2.1.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>helidon-logging-jul</artifactId>
|
||||||
|
<name>Helidon Java Util Logging Integration</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.common</groupId>
|
||||||
|
<artifactId>helidon-common-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<artifactId>helidon-logging-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.common</groupId>
|
||||||
|
<artifactId>helidon-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-all</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.jul;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.LogRecord;
|
||||||
|
import java.util.logging.StreamHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link StreamHandler} that writes to {@link System#out standard out} and uses a {@link HelidonFormatter} for formatting.
|
||||||
|
* Sets the level to {@link Level#ALL} so that level filtering is performed solely by the loggers.
|
||||||
|
*/
|
||||||
|
public class HelidonConsoleHandler extends StreamHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link HelidonConsoleHandler} configured with:
|
||||||
|
* <ul>
|
||||||
|
* <li>the output stream set to {@link System#out}</li>
|
||||||
|
* <li>the formatter set to a {@link HelidonFormatter}</li>
|
||||||
|
* <li>the level set to {@link Level#ALL}</li>
|
||||||
|
* </ul>.
|
||||||
|
*/
|
||||||
|
public HelidonConsoleHandler() {
|
||||||
|
setOutputStream(System.out);
|
||||||
|
setLevel(Level.ALL); // Handlers should not filter, loggers should
|
||||||
|
setFormatter(new HelidonFormatter());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publish(LogRecord record) {
|
||||||
|
super.publish(record);
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.jul;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.LogManager;
|
||||||
|
import java.util.logging.LogRecord;
|
||||||
|
import java.util.logging.SimpleFormatter;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import io.helidon.logging.common.HelidonMdc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link SimpleFormatter} that replaces all occurrences of MDC tags like {@code %X{value}} with specific values.
|
||||||
|
* It also supports replacement of {@code "!thread!"} with the current thread.
|
||||||
|
*/
|
||||||
|
public class HelidonFormatter extends SimpleFormatter {
|
||||||
|
private static final String THREAD = "thread";
|
||||||
|
private static final String THREAD_TOKEN = "!" + THREAD + "!";
|
||||||
|
private static final Pattern THREAD_PATTERN = Pattern.compile(THREAD_TOKEN);
|
||||||
|
private static final Pattern X_VALUE = Pattern.compile("(\\s?%X\\{)(\\S*?)(})");
|
||||||
|
private static final Map<String, Pattern> PATTERN_CACHE = new HashMap<>();
|
||||||
|
private static final String JUL_FORMAT_PROP_KEY = "java.util.logging.SimpleFormatter.format";
|
||||||
|
private final String format = LogManager.getLogManager().getProperty(JUL_FORMAT_PROP_KEY);
|
||||||
|
private final Set<String> parsedProps = new HashSet<>();
|
||||||
|
private final boolean thread;
|
||||||
|
|
||||||
|
HelidonFormatter() {
|
||||||
|
thread = format.contains(THREAD_TOKEN) || format.contains("%X{" + THREAD + "}");
|
||||||
|
Matcher matcher = X_VALUE.matcher(format);
|
||||||
|
while (matcher.find()) {
|
||||||
|
parsedProps.add(matcher.group(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(LogRecord record) {
|
||||||
|
String message = thread ? thread() : format;
|
||||||
|
for (String parsedKey : parsedProps) {
|
||||||
|
String value = HelidonMdc.get(parsedKey).orElse("");
|
||||||
|
message = PATTERN_CACHE.computeIfAbsent(parsedKey, key -> Pattern.compile("%X\\{" + key + "}"))
|
||||||
|
.matcher(message).replaceAll(value);
|
||||||
|
}
|
||||||
|
return formatRow(record, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String thread() {
|
||||||
|
String currentThread = Thread.currentThread().toString();
|
||||||
|
String message = PATTERN_CACHE.computeIfAbsent(THREAD, key -> Pattern.compile("%X\\{" + THREAD + "}"))
|
||||||
|
.matcher(format).replaceAll(currentThread);
|
||||||
|
message = THREAD_PATTERN.matcher(message).replaceAll(currentThread);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Copied from SimpleFormatter
|
||||||
|
private String formatRow(LogRecord record, String format) {
|
||||||
|
ZonedDateTime zdt = ZonedDateTime.ofInstant(
|
||||||
|
record.getInstant(), ZoneId.systemDefault());
|
||||||
|
String source;
|
||||||
|
if (record.getSourceClassName() != null) {
|
||||||
|
source = record.getSourceClassName();
|
||||||
|
if (record.getSourceMethodName() != null) {
|
||||||
|
source += " " + record.getSourceMethodName();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
source = record.getLoggerName();
|
||||||
|
}
|
||||||
|
String message = formatMessage(record);
|
||||||
|
String throwable = "";
|
||||||
|
if (record.getThrown() != null) {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
pw.println();
|
||||||
|
record.getThrown().printStackTrace(pw);
|
||||||
|
pw.close();
|
||||||
|
throwable = sw.toString();
|
||||||
|
}
|
||||||
|
return String.format(format,
|
||||||
|
zdt,
|
||||||
|
source,
|
||||||
|
record.getLoggerName(),
|
||||||
|
record.getLevel().getLocalizedName(),
|
||||||
|
message,
|
||||||
|
throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
logging/jul/src/main/java/io/helidon/logging/jul/JulMdc.java
Normal file
62
logging/jul/src/main/java/io/helidon/logging/jul/JulMdc.java
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.jul;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MDC implementation for Java Util Logging framework.
|
||||||
|
*/
|
||||||
|
public class JulMdc {
|
||||||
|
|
||||||
|
private static final ThreadLocal<Map<String, String>> MDC_PROPERTIES = ThreadLocal.withInitial(HashMap::new);
|
||||||
|
|
||||||
|
private JulMdc() {
|
||||||
|
throw new IllegalStateException("This class cannot be instantiated");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put(String key, String value) {
|
||||||
|
MDC_PROPERTIES.get().put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value bound to the key from the MDC storage.
|
||||||
|
*
|
||||||
|
* @param key key value
|
||||||
|
* @return value bound to the key
|
||||||
|
*/
|
||||||
|
public static String get(String key) {
|
||||||
|
return MDC_PROPERTIES.get().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove(String key) {
|
||||||
|
MDC_PROPERTIES.get().remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear() {
|
||||||
|
MDC_PROPERTIES.get().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, String> properties() {
|
||||||
|
return new HashMap<>(MDC_PROPERTIES.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void properties(Map<String, String> properties) {
|
||||||
|
MDC_PROPERTIES.set(new HashMap<>(properties));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.jul;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.helidon.common.context.spi.DataPropagationProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is propagator of JUL MDC values between different threads.
|
||||||
|
* This class is loaded and used via SPI.
|
||||||
|
*/
|
||||||
|
public class JulMdcPropagator implements DataPropagationProvider<Map<String, String>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> data() {
|
||||||
|
return JulMdc.properties();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void propagateData(Map<String, String> data) {
|
||||||
|
JulMdc.properties(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearData() {
|
||||||
|
JulMdc.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.jul;
|
||||||
|
|
||||||
|
import io.helidon.logging.common.spi.MdcProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider for setting MDC values to the Java Util Logging MDC support.
|
||||||
|
* This class is loaded and used via SPI.
|
||||||
|
*/
|
||||||
|
public class JulMdcProvider implements MdcProvider {
|
||||||
|
@Override
|
||||||
|
public void put(String key, String value) {
|
||||||
|
JulMdc.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(String key) {
|
||||||
|
JulMdc.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
JulMdc.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String key) {
|
||||||
|
return JulMdc.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon Java util logging MDC support.
|
||||||
|
*/
|
||||||
|
package io.helidon.logging.jul;
|
||||||
31
logging/jul/src/main/java/module-info.java
Normal file
31
logging/jul/src/main/java/module-info.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon Java Util Logging MDC support module.
|
||||||
|
*/
|
||||||
|
module io.helidon.logging.jul {
|
||||||
|
requires java.logging;
|
||||||
|
|
||||||
|
requires io.helidon.common;
|
||||||
|
requires io.helidon.common.context;
|
||||||
|
requires io.helidon.logging.common;
|
||||||
|
|
||||||
|
exports io.helidon.logging.jul;
|
||||||
|
|
||||||
|
provides io.helidon.common.context.spi.DataPropagationProvider with io.helidon.logging.jul.JulMdcPropagator;
|
||||||
|
provides io.helidon.logging.common.spi.MdcProvider with io.helidon.logging.jul.JulMdcProvider;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
io.helidon.logging.jul.JulMdcPropagator
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
io.helidon.logging.jul.JulMdcProvider
|
||||||
108
logging/jul/src/test/java/io/helidon/logging/jul/JulMdcTest.java
Normal file
108
logging/jul/src/test/java/io/helidon/logging/jul/JulMdcTest.java
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.jul;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import io.helidon.common.LogConfig;
|
||||||
|
import io.helidon.common.context.Context;
|
||||||
|
import io.helidon.common.context.Contexts;
|
||||||
|
import io.helidon.common.context.ExecutorException;
|
||||||
|
import io.helidon.logging.common.HelidonMdc;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.endsWith;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test proper function of Jul MDC propagator and provider.
|
||||||
|
*/
|
||||||
|
public class JulMdcTest {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(JulMdcTest.class.getName());
|
||||||
|
private static final ByteArrayOutputStream OUTPUT_STREAM = new ByteArrayOutputStream();
|
||||||
|
private static final PrintStream TEST_STREAM = new PrintStream(OUTPUT_STREAM);
|
||||||
|
|
||||||
|
private static final String TEST_KEY = "test";
|
||||||
|
private static final String TEST_VALUE = "value";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMdc() {
|
||||||
|
PrintStream original = System.out;
|
||||||
|
try {
|
||||||
|
System.setOut(TEST_STREAM);
|
||||||
|
LogConfig.initClass();
|
||||||
|
OUTPUT_STREAM.reset();
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
String message = "This is test logging message";
|
||||||
|
String thread = Thread.currentThread().toString();
|
||||||
|
String logMessage = logMessage(message);
|
||||||
|
assertThat(logMessage, endsWith(thread + ": " + message + " " + TEST_VALUE + System.lineSeparator()));
|
||||||
|
|
||||||
|
HelidonMdc.remove(TEST_KEY);
|
||||||
|
logMessage = logMessage(message);
|
||||||
|
assertThat(logMessage, endsWith(thread + ": " + message + " " + System.lineSeparator()));
|
||||||
|
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
HelidonMdc.clear();
|
||||||
|
logMessage = logMessage(message);
|
||||||
|
assertThat(logMessage, endsWith(thread + ": " + message + " " + System.lineSeparator()));
|
||||||
|
} finally {
|
||||||
|
System.setOut(original);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String logMessage(String message) {
|
||||||
|
try {
|
||||||
|
LOGGER.info(message);
|
||||||
|
return OUTPUT_STREAM.toString();
|
||||||
|
} finally {
|
||||||
|
OUTPUT_STREAM.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThreadPropagation() {
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
Context context = Context.create();
|
||||||
|
ExecutorService executor = Contexts.wrap(Executors.newFixedThreadPool(1));
|
||||||
|
|
||||||
|
Contexts.runInContext(context, () -> {
|
||||||
|
try {
|
||||||
|
String value = executor.submit(new TestCallable()).get();
|
||||||
|
assertThat(value, is(TEST_VALUE));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ExecutorException("failed to execute", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class TestCallable implements Callable<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String call() {
|
||||||
|
return JulMdc.get(TEST_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
24
logging/jul/src/test/resources/logging.properties
Normal file
24
logging/jul/src/test/resources/logging.properties
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Send messages to the console
|
||||||
|
handlers=io.helidon.logging.jul.HelidonConsoleHandler
|
||||||
|
|
||||||
|
# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
|
||||||
|
java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s %X{test}%n
|
||||||
|
|
||||||
|
# Global logging level. Can be overridden by specific loggers
|
||||||
|
.level=INFO
|
||||||
63
logging/log4j/pom.xml
Normal file
63
logging/log4j/pom.xml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
~
|
||||||
|
~ 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="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>helidon-logging-project</artifactId>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<version>2.1.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>helidon-logging-log4j</artifactId>
|
||||||
|
<name>Helidon Log4J Integration</name>
|
||||||
|
|
||||||
|
<!-- Javadoc should not run here since log4j is multi-release jar and javadoc plugin does not recognize it as module.
|
||||||
|
This module also does not provide any specific user API so it is not required to have javadoc. -->
|
||||||
|
<properties>
|
||||||
|
<maven.javadoc.skip>true</maven.javadoc.skip>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.common</groupId>
|
||||||
|
<artifactId>helidon-common-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<artifactId>helidon-logging-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-all</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.log4j;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.helidon.common.context.spi.DataPropagationProvider;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is propagator of Log4j MDC values between different threads.
|
||||||
|
* This class is loaded and used via SPI.
|
||||||
|
*/
|
||||||
|
public class Log4jMdcPropagator implements DataPropagationProvider<Map<String, String>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> data() {
|
||||||
|
return ThreadContext.getContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void propagateData(Map<String, String> data) {
|
||||||
|
ThreadContext.putAll(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearData() {
|
||||||
|
ThreadContext.clearAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.log4j;
|
||||||
|
|
||||||
|
import io.helidon.logging.common.spi.MdcProvider;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider for setting MDC values to the Log4j MDC support.
|
||||||
|
* This class is loaded and used via SPI.
|
||||||
|
*/
|
||||||
|
public class Log4jMdcProvider implements MdcProvider {
|
||||||
|
@Override
|
||||||
|
public void put(String key, String value) {
|
||||||
|
ThreadContext.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(String key) {
|
||||||
|
ThreadContext.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
ThreadContext.clearAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String key) {
|
||||||
|
return ThreadContext.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon Log4j MDC propagation support.
|
||||||
|
*/
|
||||||
|
package io.helidon.logging.log4j;
|
||||||
29
logging/log4j/src/main/java/module-info.java
Normal file
29
logging/log4j/src/main/java/module-info.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon Log4j MDC module.
|
||||||
|
*/
|
||||||
|
module io.helidon.logging.log4j {
|
||||||
|
requires io.helidon.common.context;
|
||||||
|
requires org.apache.logging.log4j;
|
||||||
|
requires io.helidon.logging.common;
|
||||||
|
|
||||||
|
exports io.helidon.logging.log4j;
|
||||||
|
|
||||||
|
provides io.helidon.logging.common.spi.MdcProvider with io.helidon.logging.log4j.Log4jMdcProvider;
|
||||||
|
provides io.helidon.common.context.spi.DataPropagationProvider with io.helidon.logging.log4j.Log4jMdcPropagator;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
io.helidon.logging.log4j.Log4jMdcPropagator
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
io.helidon.logging.log4j.Log4jMdcProvider
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.log4j;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import io.helidon.common.context.Context;
|
||||||
|
import io.helidon.common.context.Contexts;
|
||||||
|
import io.helidon.common.context.ExecutorException;
|
||||||
|
import io.helidon.logging.common.HelidonMdc;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test proper function of Log4j MDC propagator and provider.
|
||||||
|
*/
|
||||||
|
public class Log4jMdcTest {
|
||||||
|
|
||||||
|
private static final String TEST_KEY = "test";
|
||||||
|
private static final String TEST_VALUE = "value";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMdc() {
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
assertThat(ThreadContext.get(TEST_KEY), is(TEST_VALUE));
|
||||||
|
HelidonMdc.remove(TEST_KEY);
|
||||||
|
assertThat(ThreadContext.get(TEST_KEY), nullValue());
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
HelidonMdc.clear();
|
||||||
|
assertThat(ThreadContext.get(TEST_KEY), nullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThreadPropagation() {
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
Context context = Context.create();
|
||||||
|
ExecutorService executor = Contexts.wrap(Executors.newFixedThreadPool(1));
|
||||||
|
|
||||||
|
Contexts.runInContext(context, () -> {
|
||||||
|
try {
|
||||||
|
String value = executor.submit(new TestCallable()).get();
|
||||||
|
assertThat(value, is(TEST_VALUE));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ExecutorException("failed to execute", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class TestCallable implements Callable<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String call() {
|
||||||
|
return ThreadContext.get(TEST_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
39
logging/pom.xml
Normal file
39
logging/pom.xml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
~
|
||||||
|
~ 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="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>helidon-project</artifactId>
|
||||||
|
<groupId>io.helidon</groupId>
|
||||||
|
<version>2.1.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<artifactId>helidon-logging-project</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>Helidon Logging Project</name>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>common</module>
|
||||||
|
<module>jul</module>
|
||||||
|
<module>slf4j</module>
|
||||||
|
<module>log4j</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
</project>
|
||||||
61
logging/slf4j/pom.xml
Normal file
61
logging/slf4j/pom.xml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
~
|
||||||
|
~ 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="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>helidon-logging-project</artifactId>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<version>2.1.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>helidon-logging-slf4j</artifactId>
|
||||||
|
<name>Helidon SLF4J Integration</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.common</groupId>
|
||||||
|
<artifactId>helidon-common-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.helidon.logging</groupId>
|
||||||
|
<artifactId>helidon-logging-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-all</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-jdk14</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.slf4j;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.helidon.common.context.spi.DataPropagationProvider;
|
||||||
|
|
||||||
|
import org.slf4j.MDC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is propagator of Slf4j MDC values between different threads.
|
||||||
|
* This class is loaded and used via SPI.
|
||||||
|
*/
|
||||||
|
public class Slf4jMdcPropagator implements DataPropagationProvider<Map<String, String>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> data() {
|
||||||
|
return MDC.getCopyOfContextMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void propagateData(Map<String, String> data) {
|
||||||
|
MDC.setContextMap(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearData() {
|
||||||
|
MDC.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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 io.helidon.logging.slf4j;
|
||||||
|
|
||||||
|
|
||||||
|
import io.helidon.logging.common.spi.MdcProvider;
|
||||||
|
|
||||||
|
import org.slf4j.MDC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider for setting MDC values to the Slf4j MDC support.
|
||||||
|
* This class is loaded and used via SPI.
|
||||||
|
*/
|
||||||
|
public class Slf4jMdcProvider implements MdcProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(String key, String value) {
|
||||||
|
MDC.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(String key) {
|
||||||
|
MDC.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
MDC.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(String key) {
|
||||||
|
return MDC.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon Slf4J MDC propagation support.
|
||||||
|
*/
|
||||||
|
package io.helidon.logging.slf4j;
|
||||||
30
logging/slf4j/src/main/java/module-info.java
Normal file
30
logging/slf4j/src/main/java/module-info.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helidon Slf4j MDC module.
|
||||||
|
*/
|
||||||
|
module io.helidon.logging.slf4j {
|
||||||
|
requires io.helidon.common.context;
|
||||||
|
requires io.helidon.logging.common;
|
||||||
|
|
||||||
|
requires slf4j.api;
|
||||||
|
|
||||||
|
exports io.helidon.logging.slf4j;
|
||||||
|
|
||||||
|
provides io.helidon.common.context.spi.DataPropagationProvider with io.helidon.logging.slf4j.Slf4jMdcPropagator;
|
||||||
|
provides io.helidon.logging.common.spi.MdcProvider with io.helidon.logging.slf4j.Slf4jMdcProvider;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
io.helidon.logging.slf4j.Slf4jMdcPropagator
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
io.helidon.logging.slf4j.Slf4jMdcProvider
|
||||||
76
logging/slf4j/src/test/java/Slf4jMdcTest.java
Normal file
76
logging/slf4j/src/test/java/Slf4jMdcTest.java
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import io.helidon.common.context.Context;
|
||||||
|
import io.helidon.common.context.Contexts;
|
||||||
|
import io.helidon.common.context.ExecutorException;
|
||||||
|
import io.helidon.logging.common.HelidonMdc;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.slf4j.MDC;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test proper function of Slf4j MDC propagator and provider.
|
||||||
|
*/
|
||||||
|
public class Slf4jMdcTest {
|
||||||
|
|
||||||
|
private static final String TEST_KEY = "test";
|
||||||
|
private static final String TEST_VALUE = "value";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMdc() {
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
assertThat(MDC.get(TEST_KEY), is(TEST_VALUE));
|
||||||
|
HelidonMdc.remove(TEST_KEY);
|
||||||
|
assertThat(MDC.get(TEST_KEY), nullValue());
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
HelidonMdc.clear();
|
||||||
|
assertThat(MDC.get(TEST_KEY), nullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThreadPropagation() {
|
||||||
|
HelidonMdc.set(TEST_KEY, TEST_VALUE);
|
||||||
|
Context context = Context.create();
|
||||||
|
ExecutorService executor = Contexts.wrap(Executors.newFixedThreadPool(1));
|
||||||
|
|
||||||
|
Contexts.runInContext(context, () -> {
|
||||||
|
try {
|
||||||
|
String value = executor.submit(new TestCallable()).get();
|
||||||
|
assertThat(value, is(TEST_VALUE));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ExecutorException("failed to execute", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class TestCallable implements Callable<String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String call() {
|
||||||
|
return MDC.get(TEST_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user