Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MDC logging support #2479

Merged
merged 15 commits into from
Nov 10, 2020
21 changes: 21 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,27 @@
<artifactId>helidon-microprofile-tests-junit5</artifactId>
<version>${helidon.version}</version>
</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>
</dependencyManagement>
</project>
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand All @@ -25,7 +25,10 @@
/**
* 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.
*
* @deprecated use io.helidon.logging.jul.HelidonConsoleHandler from helidon-logging-jul module instead
*/
@Deprecated(since = "2.1.1")
public class HelidonConsoleHandler extends StreamHandler {

/**
Expand All @@ -40,6 +43,9 @@ public HelidonConsoleHandler() {
setOutputStream(System.out);
setLevel(Level.ALL); // Handlers should not filter, loggers should
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
Expand Down
4 changes: 4 additions & 0 deletions common/context/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,9 @@
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.common</groupId>
<artifactId>helidon-common-service-loader</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand All @@ -16,8 +16,11 @@
package io.helidon.common.context;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
Expand All @@ -26,7 +29,15 @@
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;

import io.helidon.common.context.spi.DataPropagationProvider;
import io.helidon.common.serviceloader.HelidonServiceLoader;

class ContextAwareExecutorImpl implements ContextAwareExecutorService {

@SuppressWarnings("rawtypes")
private static final List<DataPropagationProvider> PROVIDERS = HelidonServiceLoader
.builder(ServiceLoader.load(DataPropagationProvider.class)).build().asList();

private final ExecutorService delegate;

ContextAwareExecutorImpl(ExecutorService toWrap) {
Expand Down Expand Up @@ -112,21 +123,39 @@ protected <T> Collection<? extends Callable<T>> wrap(Collection<? extends Callab

}

protected <T> Callable<T> wrap(Callable<T> task) {
@SuppressWarnings(value = "unchecked")
protected <T> Callable<T> wrap(Callable<T> task) {
Optional<Context> context = Contexts.context();

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 {
return task;
}
}

@SuppressWarnings(value = "unchecked")
protected Runnable wrap(Runnable command) {
Optional<Context> context = Contexts.context();

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 {
return command;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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();

}
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 5 additions & 1 deletion common/context/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,10 @@
module io.helidon.common.context {
requires java.logging;
requires io.helidon.common;
requires io.helidon.common.serviceloader;

exports io.helidon.common.context;
exports io.helidon.common.context.spi;

uses io.helidon.common.context.spi.DataPropagationProvider;
}
6 changes: 6 additions & 0 deletions dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
<version.lib.jsonp-impl>1.1.6</version.lib.jsonp-impl>
<version.lib.junit>5.6.2</version.lib.junit>
<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.maven-wagon>2.10</version.lib.maven-wagon>
<version.lib.microprofile-config>1.4</version.lib.microprofile-config>
Expand Down Expand Up @@ -742,6 +743,11 @@
<artifactId>slf4j-simple</artifactId>
<version>${version.lib.slf4j}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${version.lib.log4j}</version>
</dependency>

<dependency>
<groupId>io.smallrye</groupId>
Expand Down
37 changes: 37 additions & 0 deletions logging/common/pom.xml
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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();
}

}
Original file line number Diff line number Diff line change
@@ -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;
Loading