diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 00000000..44254ea8 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + + org.commonjava.util + o11yphant + 1.9.2-SNAPSHOT + + + o11yphant-common + + \ No newline at end of file diff --git a/common/src/main/java/org/commonjava/o11yphant/common/thread/ThreadContext.java b/common/src/main/java/org/commonjava/o11yphant/common/thread/ThreadContext.java new file mode 100644 index 00000000..48881b41 --- /dev/null +++ b/common/src/main/java/org/commonjava/o11yphant/common/thread/ThreadContext.java @@ -0,0 +1,275 @@ +/** + * Copyright (C) 2013-2022 Red Hat, Inc. (https://github.com/Commonjava/weft) + * + * 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.commonjava.o11yphant.common.thread; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; + +/** + * (Copied from weft: https://github.com/Commonjava/weft) + * + * This {@link ThreadContext} keeps a count of the number of threads referencing it, and can run finalization logic + * when that number hits 0. + * + * Created by jdcasey on 1/3/17. + */ +public class ThreadContext + implements Map +{ + private static ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); + + private final Map contextMap = new ConcurrentHashMap<>(); + + private Map mdcMap; // mapped diagnostic context + + private int refs = 1; + + private List> finalizers = new ArrayList<>(); + + public static ThreadContext getContext( boolean create ) + { + ThreadContext threadContext = THREAD_LOCAL.get(); + if ( threadContext == null && create ) + { + threadContext = new ThreadContext(); + THREAD_LOCAL.set( threadContext ); + } + + if ( threadContext != null ) + { + threadContext.mdcMap = MDC.getCopyOfContextMap(); + } + + return threadContext; + } + + public static ThreadContext setContext( ThreadContext ctx ) + { + ThreadContext oldCtx = swapContext( ctx ); + if ( ctx != null && ctx.mdcMap != null ) + { + MDC.setContextMap(ctx.mdcMap); + } + return oldCtx; + } + + private static ThreadContext swapContext( final ThreadContext ctx ) + { + ThreadContext oldCtx = THREAD_LOCAL.get(); + if ( oldCtx != null ) + { + Logger logger = LoggerFactory.getLogger( ThreadContext.class ); + oldCtx.refs--; + logger.trace( "context refs: {}", oldCtx.refs ); + oldCtx.runFinalizersIfDone(); + } + + if ( ctx != null ) + { + THREAD_LOCAL.set( ctx ); + ctx.refs++; + } + else + { + THREAD_LOCAL.remove(); + } + + return oldCtx; + } + + /** + * Provide some finalizer logic to handle the scenario where the number of "live" threads referencing this context + * drops to 0. Before this happens, any contextual information in this ThreadContext may be needed by running threads, + * and it's not safe to clean up. However, since the context may contain {@link java.io.Closeable} instances and + * the like, it's important to have some point where they will be cleaned up. + * @since 1.5 + * @param finalizer + */ + public synchronized void registerFinalizer( Consumer finalizer ) + { + if ( !this.finalizers.contains( finalizer ) ) + { + Logger logger = LoggerFactory.getLogger( getClass() ); + logger.debug( "Registering finalizer: {} on ThreadContext: {}", finalizer, this ); + this.finalizers.add( finalizer ); + } + } + + /** + * If the thread reference count on this context drops to zero, run any finalization logic that might be registered. + */ + private synchronized void runFinalizersIfDone() + { + Logger logger = LoggerFactory.getLogger( getClass() ); + if ( refs < 1 && finalizers != null ) + { + logger.debug( "Running finalizers for ThreadContext: {}", this ); + finalizers.forEach( c->{ + if ( c != null ) + { + logger.debug( "Running finalizer: {} for ThreadContext: {}", c, this ); + + try + { + c.accept( this ); + } + catch ( Throwable t ) + { + logger.error( "Caught error while running finalizer: " + c + " on ThreadContext: " + this, t ); + } + + logger.trace( "Finalizer: {} done for ThreadContext: {}", c, this ); + } + } ); + } + } + + public static void clearContext() + { + swapContext( null ); + MDC.clear(); + } + + private ThreadContext(){} + + public int size() + { + return contextMap.size(); + } + + public boolean isEmpty() + { + return contextMap.isEmpty(); + } + + public void putAll( Map map ) + { + contextMap.putAll( map ); + } + + public Collection values() + { + return contextMap.values(); + } + + public Object merge( String key, Object value, BiFunction remappingFunction ) + { + return contextMap.merge( key, value, remappingFunction ); + } + + public Set keySet() + { + return contextMap.keySet(); + } + + public void forEach( BiConsumer action ) + { + contextMap.forEach( action ); + } + + public Object computeIfPresent( String key, BiFunction remappingFunction ) + { + return contextMap.computeIfPresent( key, remappingFunction ); + } + + public void clear() + { + contextMap.clear(); + } + + public boolean containsValue( Object o ) + { + return contextMap.containsValue( o ); + } + + public Object put( String s, Object o ) + { + return contextMap.put( s, o ); + } + + public void replaceAll( BiFunction function ) + { + contextMap.replaceAll( function ); + } + + public Object get( Object o ) + { + return contextMap.get( o ); + } + + public boolean containsKey( Object o ) + { + return contextMap.containsKey( o ); + } + + public Set> entrySet() + { + return contextMap.entrySet(); + } + + public boolean replace( String key, Object oldValue, Object newValue ) + { + return contextMap.replace( key, oldValue, newValue ); + } + + public Object computeIfAbsent( String key, Function mappingFunction ) + { + return contextMap.computeIfAbsent( key, mappingFunction ); + } + + public Object compute( String key, BiFunction remappingFunction ) + { + return contextMap.compute( key, remappingFunction ); + } + + public Object putIfAbsent( String key, Object value ) + { + return contextMap.putIfAbsent( key, value ); + } + + public Object remove( Object o ) + { + return contextMap.remove( o ); + } + + public Object getOrDefault( Object key, Object defaultValue ) + { + return contextMap.getOrDefault( key, defaultValue ); + } + + public boolean remove( Object key, Object value ) + { + return contextMap.remove( key, value ); + } + + public Object replace( String key, Object value ) + { + return contextMap.replace( key, value ); + } + +} diff --git a/metrics/common/pom.xml b/metrics/common/pom.xml index 6b6eaf52..6d7ab807 100644 --- a/metrics/common/pom.xml +++ b/metrics/common/pom.xml @@ -32,11 +32,11 @@ org.commonjava.util - o11yphant-metrics-api + o11yphant-common - org.commonjava.cdi.util - weft + org.commonjava.util + o11yphant-metrics-api io.dropwizard.metrics diff --git a/metrics/common/src/main/java/org/commonjava/o11yphant/metrics/AbstractTrafficClassifier.java b/metrics/common/src/main/java/org/commonjava/o11yphant/metrics/AbstractTrafficClassifier.java index dc421923..e6ab5f71 100644 --- a/metrics/common/src/main/java/org/commonjava/o11yphant/metrics/AbstractTrafficClassifier.java +++ b/metrics/common/src/main/java/org/commonjava/o11yphant/metrics/AbstractTrafficClassifier.java @@ -15,7 +15,7 @@ */ package org.commonjava.o11yphant.metrics; -import org.commonjava.cdi.util.weft.ThreadContext; +import org.commonjava.o11yphant.common.thread.ThreadContext; import java.util.*; diff --git a/metrics/common/src/main/java/org/commonjava/o11yphant/metrics/RequestContextHelper.java b/metrics/common/src/main/java/org/commonjava/o11yphant/metrics/RequestContextHelper.java index b542edd1..f3948a8b 100644 --- a/metrics/common/src/main/java/org/commonjava/o11yphant/metrics/RequestContextHelper.java +++ b/metrics/common/src/main/java/org/commonjava/o11yphant/metrics/RequestContextHelper.java @@ -15,7 +15,7 @@ */ package org.commonjava.o11yphant.metrics; -import org.commonjava.cdi.util.weft.ThreadContext; +import org.commonjava.o11yphant.common.thread.ThreadContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/metrics/core/pom.xml b/metrics/core/pom.xml index a9a859e1..f252b183 100644 --- a/metrics/core/pom.xml +++ b/metrics/core/pom.xml @@ -38,11 +38,6 @@ o11yphant-metrics-common - - org.commonjava.cdi.util - weft - - io.dropwizard.metrics metrics-jvm diff --git a/metrics/core/src/main/java/org/commonjava/o11yphant/metrics/DefaultMetricsManager.java b/metrics/core/src/main/java/org/commonjava/o11yphant/metrics/DefaultMetricsManager.java index 3af3fd2c..af5f2506 100644 --- a/metrics/core/src/main/java/org/commonjava/o11yphant/metrics/DefaultMetricsManager.java +++ b/metrics/core/src/main/java/org/commonjava/o11yphant/metrics/DefaultMetricsManager.java @@ -16,7 +16,7 @@ package org.commonjava.o11yphant.metrics; import com.codahale.metrics.health.HealthCheckRegistry; -import org.commonjava.cdi.util.weft.ThreadContext; +import org.commonjava.o11yphant.common.thread.ThreadContext; import org.commonjava.o11yphant.metrics.annotation.MetricWrapper; import org.commonjava.o11yphant.metrics.annotation.MetricWrapperEnd; import org.commonjava.o11yphant.metrics.annotation.MetricWrapperNamed; diff --git a/pom.xml b/pom.xml index d66ea454..22e38573 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,7 @@ metrics trace + common o11yphant :: Parent @@ -56,7 +57,6 @@ 0.16.0 1.2.12 2.2.28.Final - 1.22 1.16 3.11.5 4.5.13 @@ -81,6 +81,11 @@ import + + org.commonjava.util + o11yphant-common + 1.9.2-SNAPSHOT + org.commonjava.util o11yphant-trace-api @@ -191,12 +196,6 @@ ${logbackVersion} - - org.commonjava.cdi.util - weft - ${weftVersion} - - org.commonjava.util jhttpc diff --git a/trace/api/pom.xml b/trace/api/pom.xml index 4435bbab..3bfdd650 100644 --- a/trace/api/pom.xml +++ b/trace/api/pom.xml @@ -34,10 +34,6 @@ org.commonjava.util o11yphant-metrics-api - - org.commonjava.cdi.util - weft - org.apache.httpcomponents httpclient diff --git a/trace/api/src/main/java/org/commonjava/o11yphant/trace/thread/TraceThreadContextualizer.java b/trace/api/src/main/java/org/commonjava/o11yphant/trace/thread/TraceThreadContextualizer.java index bc817b0e..c028050a 100644 --- a/trace/api/src/main/java/org/commonjava/o11yphant/trace/thread/TraceThreadContextualizer.java +++ b/trace/api/src/main/java/org/commonjava/o11yphant/trace/thread/TraceThreadContextualizer.java @@ -31,7 +31,6 @@ * limitations under the License. */ -import org.commonjava.cdi.util.weft.ThreadContextualizer; import org.commonjava.o11yphant.trace.TraceManager; import org.commonjava.o11yphant.trace.TracerConfiguration; import org.commonjava.o11yphant.trace.spi.adapter.SpanAdapter; @@ -41,7 +40,6 @@ import java.util.Optional; public class TraceThreadContextualizer - implements ThreadContextualizer { private static final String THREAD_NAME = "thread.name"; @@ -67,13 +65,11 @@ public TraceThreadContextualizer( TracerConfiguration configuration, TraceManage this.tracingContext = tracingContext; } - @Override public String getId() { return "honeycomb.threadpool.spanner"; } - @Override public Object extractCurrentContext() { if ( configuration.isEnabled() ) @@ -86,7 +82,6 @@ public Object extractCurrentContext() return null; } - @Override public void setChildContext( final Object parentContext ) { if ( configuration.isEnabled() ) @@ -112,7 +107,6 @@ public void setChildContext( final Object parentContext ) } } - @Override @SuppressWarnings( "PMD" ) public void clearContext() { diff --git a/trace/otel/pom.xml b/trace/otel/pom.xml index 56106bdb..8e06d0ed 100644 --- a/trace/otel/pom.xml +++ b/trace/otel/pom.xml @@ -46,6 +46,10 @@ io.opentelemetry opentelemetry-exporter-logging + + org.commonjava.util + o11yphant-common + org.commonjava.util o11yphant-trace-api diff --git a/trace/otel/src/main/java/org/commonjava/o11yphant/otel/impl/OtelThreadTracingContext.java b/trace/otel/src/main/java/org/commonjava/o11yphant/otel/impl/OtelThreadTracingContext.java index 081390ca..25401a55 100644 --- a/trace/otel/src/main/java/org/commonjava/o11yphant/otel/impl/OtelThreadTracingContext.java +++ b/trace/otel/src/main/java/org/commonjava/o11yphant/otel/impl/OtelThreadTracingContext.java @@ -19,7 +19,7 @@ import io.opentelemetry.context.ContextStorage; import io.opentelemetry.context.ContextStorageProvider; import io.opentelemetry.context.Scope; -import org.commonjava.cdi.util.weft.ThreadContext; +import org.commonjava.o11yphant.common.thread.ThreadContext; import org.commonjava.o11yphant.trace.thread.ThreadTracingContext; import javax.annotation.Nonnull;