diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 9c76144b44a8f..16d6bda2e4159 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -2859,6 +2859,11 @@ jaeger-thrift ${jaeger.version} + + io.jaegertracing + jaeger-zipkin + ${jaeger.version} + com.h2database h2 diff --git a/extensions/jaeger/deployment/pom.xml b/extensions/jaeger/deployment/pom.xml index d016032ea322d..a388dedc6ddfa 100644 --- a/extensions/jaeger/deployment/pom.xml +++ b/extensions/jaeger/deployment/pom.xml @@ -41,6 +41,11 @@ quarkus-smallrye-metrics-deployment test + + org.mockito + mockito-inline + test + diff --git a/extensions/jaeger/deployment/src/test/java/io/quarkus/jaeger/test/QuarkusJaegerTracerTest.java b/extensions/jaeger/deployment/src/test/java/io/quarkus/jaeger/test/QuarkusJaegerTracerTest.java new file mode 100644 index 0000000000000..acb636355bdd0 --- /dev/null +++ b/extensions/jaeger/deployment/src/test/java/io/quarkus/jaeger/test/QuarkusJaegerTracerTest.java @@ -0,0 +1,73 @@ +package io.quarkus.jaeger.test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import io.jaegertracing.Configuration; +import io.jaegertracing.internal.JaegerTracer; +import io.jaegertracing.internal.JaegerTracer.Builder; +import io.jaegertracing.spi.Reporter; +import io.jaegertracing.zipkin.ZipkinV2Reporter; +import io.opentracing.Tracer; +import io.quarkus.jaeger.runtime.QuarkusJaegerTracer; + +public class QuarkusJaegerTracerTest { + + @Test + public void withzipkinCompatibilityMode() { + + try (MockedStatic mockedStaticConfiguration = Mockito.mockStatic(Configuration.class)) { + Configuration mockedInstanceConfiguration = Mockito.mock(Configuration.class); + Builder mockedBuilder = Mockito.mock(Builder.class); + Tracer mockedTracer = Mockito.mock(JaegerTracer.class); + + mockedStaticConfiguration.when(() -> Configuration.fromEnv()).thenReturn(mockedInstanceConfiguration); + mockedStaticConfiguration.when(() -> mockedInstanceConfiguration.withMetricsFactory(Mockito.any())).thenReturn(mockedInstanceConfiguration); + mockedStaticConfiguration.when(() -> mockedInstanceConfiguration.getTracerBuilder()).thenReturn(mockedBuilder); + mockedStaticConfiguration.when(() -> mockedBuilder.withScopeManager(Mockito.any())).thenReturn(mockedBuilder); + mockedStaticConfiguration.when(() -> mockedBuilder.withReporter(Mockito.any())).thenReturn(mockedBuilder); + mockedStaticConfiguration.when(() -> mockedBuilder.build()).thenReturn(mockedTracer); + + QuarkusJaegerTracer tracer = new QuarkusJaegerTracer(); + tracer.setZipkinCompatibilityMode(true); + tracer.setEndpoint("http://localhost"); + tracer.toString(); + tracer.close(); + + ArgumentCaptor argument = ArgumentCaptor.forClass(Reporter.class); + Mockito.verify(mockedBuilder).withReporter(argument.capture()); + assertEquals(ZipkinV2Reporter.class, argument.getValue().getClass()); + } + + } + + @Test + public void withoutZipkinCompatibilityMode() { + try (MockedStatic mockedStaticConfiguration = Mockito.mockStatic(Configuration.class)) { + Configuration mockedInstanceConfiguration = Mockito.mock(Configuration.class); + Builder mockedBuilder = Mockito.mock(Builder.class); + Tracer mockedTracer = Mockito.mock(JaegerTracer.class); + + mockedStaticConfiguration.when(() -> Configuration.fromEnv()).thenReturn(mockedInstanceConfiguration); + mockedStaticConfiguration.when(() -> mockedInstanceConfiguration.withMetricsFactory(Mockito.any())).thenReturn(mockedInstanceConfiguration); + mockedStaticConfiguration.when(() -> mockedInstanceConfiguration.getTracerBuilder()).thenReturn(mockedBuilder); + mockedStaticConfiguration.when(() -> mockedBuilder.withScopeManager(Mockito.any())).thenReturn(mockedBuilder); + mockedStaticConfiguration.when(() -> mockedBuilder.withReporter(Mockito.any())).thenReturn(mockedBuilder); + mockedStaticConfiguration.when(() -> mockedBuilder.build()).thenReturn(mockedTracer); + + QuarkusJaegerTracer tracer = new QuarkusJaegerTracer(); + tracer.toString(); + tracer.close(); + + ArgumentCaptor argument = ArgumentCaptor.forClass(Reporter.class); + Mockito.verify(mockedBuilder).withReporter(argument.capture()); + assertNull(argument.getValue()); + } + } + +} diff --git a/extensions/jaeger/runtime/pom.xml b/extensions/jaeger/runtime/pom.xml index f7a3c3b1a6375..a9f27ebaca708 100644 --- a/extensions/jaeger/runtime/pom.xml +++ b/extensions/jaeger/runtime/pom.xml @@ -32,6 +32,20 @@ + + io.jaegertracing + jaeger-zipkin + + + commons-logging + commons-logging + + + javax.annotation + javax.annotation-api + + + jakarta.activation diff --git a/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/JaegerConfig.java b/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/JaegerConfig.java index d01892100ec28..d5ca8f2419fe1 100644 --- a/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/JaegerConfig.java +++ b/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/JaegerConfig.java @@ -118,4 +118,9 @@ public class JaegerConfig { @ConfigItem(defaultValue = "true") public Boolean logTraceContext; + /** + * Whether the jaeger should run in zipkin compatibility mode + */ + @ConfigItem + public Optional zipkinCompatibilityMode; } diff --git a/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/JaegerDeploymentRecorder.java b/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/JaegerDeploymentRecorder.java index 7140d386f2219..06df5e573cc71 100644 --- a/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/JaegerDeploymentRecorder.java +++ b/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/JaegerDeploymentRecorder.java @@ -62,6 +62,9 @@ private synchronized void registerTracer(JaegerConfig jaeger, ApplicationConfig private void initTracerConfig(JaegerConfig jaeger) { initTracerProperty("JAEGER_ENDPOINT", jaeger.endpoint, uri -> uri.toString()); + if (jaeger.endpoint.isPresent()) { + quarkusTracer.setEndpoint(jaeger.endpoint.get().toString()); + } initTracerProperty("JAEGER_AUTH_TOKEN", jaeger.authToken, token -> token); initTracerProperty("JAEGER_USER", jaeger.user, user -> user); initTracerProperty("JAEGER_PASSWORD", jaeger.password, pw -> pw); @@ -79,6 +82,9 @@ private void initTracerConfig(JaegerConfig jaeger) { initTracerProperty("JAEGER_PROPAGATION", jaeger.propagation, format -> format.toString()); initTracerProperty("JAEGER_SENDER_FACTORY", jaeger.senderFactory, sender -> sender); quarkusTracer.setLogTraceContext(jaeger.logTraceContext); + if (jaeger.zipkinCompatibilityMode.isPresent()) { + quarkusTracer.setZipkinCompatibilityMode(jaeger.zipkinCompatibilityMode.get()); + } } private void initTracerProperty(String property, Optional value, Function accessor) { diff --git a/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/QuarkusJaegerTracer.java b/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/QuarkusJaegerTracer.java index 49f64a7ee2b24..fad5e7ecece66 100644 --- a/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/QuarkusJaegerTracer.java +++ b/extensions/jaeger/runtime/src/main/java/io/quarkus/jaeger/runtime/QuarkusJaegerTracer.java @@ -3,6 +3,7 @@ import io.jaegertracing.Configuration; import io.jaegertracing.internal.JaegerTracer; import io.jaegertracing.spi.MetricsFactory; +import io.jaegertracing.zipkin.ZipkinV2Reporter; import io.opentracing.Scope; import io.opentracing.ScopeManager; import io.opentracing.Span; @@ -10,6 +11,8 @@ import io.opentracing.Tracer; import io.opentracing.propagation.Format; import io.opentracing.util.ThreadLocalScopeManager; +import zipkin2.reporter.AsyncReporter; +import zipkin2.reporter.urlconnection.URLConnectionSender; public class QuarkusJaegerTracer implements Tracer { @@ -17,6 +20,8 @@ public class QuarkusJaegerTracer implements Tracer { private boolean logTraceContext; private MetricsFactory metricsFactory; + private boolean zipkinCompatibilityMode = false; + private String endpoint = null; private final ScopeManager scopeManager = new ScopeManager() { @@ -71,10 +76,15 @@ private Tracer tracer() { if (tracer == null) { synchronized (this) { if (tracer == null) { + ZipkinV2Reporter reporter = null; + if (zipkinCompatibilityMode) { + reporter = new ZipkinV2Reporter(AsyncReporter.create(URLConnectionSender.create(endpoint))); + } tracer = Configuration.fromEnv() .withMetricsFactory(metricsFactory) .getTracerBuilder() .withScopeManager(scopeManager) + .withReporter(reporter) .build(); } } @@ -124,4 +134,12 @@ public Span activeSpan() { public Scope activateSpan(final Span span) { return tracer.activateSpan(span); } + + public void setZipkinCompatibilityMode(boolean zipkinCompatibilityMode) { + this.zipkinCompatibilityMode = zipkinCompatibilityMode; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } }