feat: add brave to core (#12814)

This commit is contained in:
conghuhu 2023-08-14 15:42:40 +08:00 committed by GitHub
parent 5ae875d951
commit 629bee3987
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 677 additions and 179 deletions

View File

@ -107,5 +107,12 @@
<artifactId>zipkin-reporter-brave</artifactId>
<optional>true</optional>
</dependency>
<!-- sender -->
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-urlconnection</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -1,66 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.exporter;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.otlp.OTlpExporter;
import org.apache.dubbo.tracing.exporter.zipkin.ZipkinExporter;
import brave.handler.SpanHandler;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.ArrayList;
import java.util.List;
public class TraceExporterFactory {
private final static ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(TraceExporterFactory.class);
/**
* for OTel
*/
public static List<SpanExporter> getSpanExporters(ApplicationModel applicationModel, ExporterConfig exporterConfig) {
ExporterConfig.ZipkinConfig zipkinConfig = exporterConfig.getZipkinConfig();
ExporterConfig.OtlpConfig otlpConfig = exporterConfig.getOtlpConfig();
List<SpanExporter> res = new ArrayList<>();
if (zipkinConfig != null && StringUtils.isNotEmpty(zipkinConfig.getEndpoint())) {
ZipkinExporter zipkinExporter = new ZipkinExporter(applicationModel, zipkinConfig);
LOGGER.info("Create zipkin span exporter.");
res.add(zipkinExporter.getSpanExporter());
}
if (otlpConfig != null && StringUtils.isNotEmpty(otlpConfig.getEndpoint())) {
OTlpExporter otlpExporter = new OTlpExporter(applicationModel, otlpConfig);
LOGGER.info("Create OTlp span exporter.");
res.add(otlpExporter.getSpanExporter());
}
return res;
}
/**
* for Brave
*/
public static List<SpanHandler> getSpanHandlers(ApplicationModel applicationModel, ExporterConfig exporterConfig) {
List<SpanHandler> res = new ArrayList<>();
// TODO brave SpanHandler impl
return res;
}
}

View File

@ -18,9 +18,7 @@ package org.apache.dubbo.tracing.exporter.otlp;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.TraceExporter;
import brave.handler.SpanHandler;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
@ -28,18 +26,12 @@ import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.Map;
public class OTlpExporter implements TraceExporter {
/**
* OTlp span exporter for OTel.
*/
public class OTlpSpanExporter {
private final ApplicationModel applicationModel;
private final ExporterConfig.OtlpConfig otlpConfig;
public OTlpExporter(ApplicationModel applicationModel, ExporterConfig.OtlpConfig otlpConfig) {
this.applicationModel = applicationModel;
this.otlpConfig = otlpConfig;
}
@Override
public SpanExporter getSpanExporter() {
public static SpanExporter getSpanExporter(ApplicationModel applicationModel, ExporterConfig.OtlpConfig otlpConfig) {
OtlpGrpcSpanExporter externalOTlpGrpcSpanExporter = applicationModel.getBeanFactory().getBean(OtlpGrpcSpanExporter.class);
if (externalOTlpGrpcSpanExporter != null) {
return externalOTlpGrpcSpanExporter;
@ -57,10 +49,4 @@ public class OTlpExporter implements TraceExporter {
}
return builder.build();
}
@Override
public SpanHandler getSpanHandler() {
// OTlp is only belong to OTel.
return null;
}
}

View File

@ -18,43 +18,26 @@ package org.apache.dubbo.tracing.exporter.zipkin;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.TraceExporter;
import brave.handler.SpanHandler;
import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import zipkin2.Span;
import zipkin2.codec.BytesEncoder;
import zipkin2.codec.SpanBytesEncoder;
public class ZipkinExporter implements TraceExporter {
/**
* Zipkin span exporter for OTel.
*/
public class ZipkinSpanExporter {
private final ApplicationModel applicationModel;
private final ExporterConfig.ZipkinConfig zipkinConfig;
public ZipkinExporter(ApplicationModel applicationModel, ExporterConfig.ZipkinConfig zipkinConfig) {
this.applicationModel = applicationModel;
this.zipkinConfig = zipkinConfig;
}
@Override
public SpanExporter getSpanExporter() {
BytesEncoder<Span> encoder = getSpanBytesEncoder();
return ZipkinSpanExporter.builder()
.setEncoder(encoder)
public static io.opentelemetry.sdk.trace.export.SpanExporter getSpanExporter(ApplicationModel applicationModel, ExporterConfig.ZipkinConfig zipkinConfig) {
return io.opentelemetry.exporter.zipkin.ZipkinSpanExporter.builder()
.setEncoder(getSpanBytesEncoder(applicationModel))
.setEndpoint(zipkinConfig.getEndpoint())
.setReadTimeout(zipkinConfig.getReadTimeout())
.build();
}
@Override
public SpanHandler getSpanHandler() {
// TODO SpanHandler of Brave impl
return null;
}
private BytesEncoder<Span> getSpanBytesEncoder() {
BytesEncoder<Span> encoder = applicationModel.getBeanFactory().getBean(BytesEncoder.class);
private static BytesEncoder<Span> getSpanBytesEncoder(ApplicationModel applicationModel) {
BytesEncoder<zipkin2.Span> encoder = applicationModel.getBeanFactory().getBean(BytesEncoder.class);
return encoder == null ? SpanBytesEncoder.JSON_V2 : encoder;
}
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.exporter.zipkin;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import brave.handler.SpanHandler;
import zipkin2.Span;
import zipkin2.codec.BytesEncoder;
import zipkin2.codec.SpanBytesEncoder;
import zipkin2.reporter.AsyncReporter;
import zipkin2.reporter.urlconnection.URLConnectionSender;
/**
* Zipkin span handler for Brave.
*/
public class ZipkinSpanHandler {
public static SpanHandler getSpanHandler(ApplicationModel applicationModel, ExporterConfig.ZipkinConfig zipkinConfig) {
URLConnectionSender sender = applicationModel.getBeanFactory().getBean(URLConnectionSender.class);
if (sender == null) {
URLConnectionSender.Builder builder = URLConnectionSender.newBuilder();
builder.connectTimeout((int) zipkinConfig.getConnectTimeout().toMillis());
builder.readTimeout((int) zipkinConfig.getReadTimeout().toMillis());
builder.endpoint(zipkinConfig.getEndpoint());
sender = builder.build();
}
AsyncReporter<Span> spanReporter = AsyncReporter.builder(sender).build(getSpanBytesEncoder(applicationModel));
return zipkin2.reporter.brave.ZipkinSpanHandler.newBuilder(spanReporter).build();
}
private static BytesEncoder<zipkin2.Span> getSpanBytesEncoder(ApplicationModel applicationModel) {
BytesEncoder<zipkin2.Span> encoder = applicationModel.getBeanFactory().getBean(BytesEncoder.class);
return encoder == null ? SpanBytesEncoder.JSON_V2 : encoder;
}
}

View File

@ -18,14 +18,20 @@ package org.apache.dubbo.tracing.tracer.brave;
import org.apache.dubbo.tracing.tracer.PropagatorProvider;
import io.micrometer.tracing.brave.bridge.BravePropagator;
import io.micrometer.tracing.propagation.Propagator;
public class BravePropagatorProvider implements PropagatorProvider {
private static Propagator propagator;
@Override
public Propagator getPropagator() {
// TODO impl
return null;
return propagator;
}
protected static void createMicrometerPropagator(brave.Tracing tracing) {
propagator = new BravePropagator(tracing);
}
}

View File

@ -16,15 +16,40 @@
*/
package org.apache.dubbo.tracing.tracer.brave;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.TracingConfig;
import org.apache.dubbo.config.nested.BaggageConfig;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.zipkin.ZipkinSpanHandler;
import org.apache.dubbo.tracing.tracer.TracerProvider;
import org.apache.dubbo.tracing.utils.PropagationType;
import io.micrometer.tracing.CurrentTraceContext;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.brave.bridge.BraveBaggageManager;
import io.micrometer.tracing.brave.bridge.BraveCurrentTraceContext;
import io.micrometer.tracing.brave.bridge.BraveTracer;
import io.micrometer.tracing.brave.bridge.W3CPropagation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.apache.dubbo.tracing.utils.ObservationConstants.DEFAULT_APPLICATION_NAME;
import static org.apache.dubbo.tracing.utils.ObservationSupportUtil.isSupportBraveURLSender;
public class BraveProvider implements TracerProvider {
private final static ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(BraveProvider.class);
private static final BraveBaggageManager BRAVE_BAGGAGE_MANAGER = new BraveBaggageManager();
private final ApplicationModel applicationModel;
private final TracingConfig tracingConfig;
@ -35,7 +60,139 @@ public class BraveProvider implements TracerProvider {
@Override
public Tracer getTracer() {
// TODO impl
return null;
// [Brave component] SpanHandler is a component that gets called when a span is finished.
List<brave.handler.SpanHandler> spanHandlerList = getSpanHandlers();
String applicationName = applicationModel.getApplicationConfigManager().getApplication()
.map(ApplicationConfig::getName)
.orElse(DEFAULT_APPLICATION_NAME);
// [Brave component] CurrentTraceContext is a Brave component that allows you to
// retrieve the current TraceContext.
brave.propagation.ThreadLocalCurrentTraceContext braveCurrentTraceContext = brave.propagation.ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(correlationScopeDecorator()) // Brave's automatic MDC setup
.build();
// [Micrometer Tracing component] A Micrometer Tracing wrapper for Brave's CurrentTraceContext
CurrentTraceContext bridgeContext = new BraveCurrentTraceContext(braveCurrentTraceContext);
// [Brave component] Tracing is the root component that allows to configure the
// tracer, handlers, context propagation etc.
brave.Tracing.Builder builder = brave.Tracing.newBuilder()
.currentTraceContext(braveCurrentTraceContext)
.supportsJoin(false)
.traceId128Bit(true)
.localServiceName(applicationName)
// For Baggage to work you need to provide a list of fields to propagate
.propagationFactory(PropagatorFactory.getPropagationFactory(tracingConfig))
.sampler(getSampler());
spanHandlerList.forEach(builder::addSpanHandler);
brave.Tracing tracing = builder.build();
BravePropagatorProvider.createMicrometerPropagator(tracing);
// [Brave component] Tracer is a component that handles the life-cycle of a span
brave.Tracer braveTracer = tracing.tracer();
// [Micrometer Tracing component] A Micrometer Tracing wrapper for Brave's Tracer
return new BraveTracer(braveTracer, bridgeContext, BRAVE_BAGGAGE_MANAGER);
}
private List<brave.handler.SpanHandler> getSpanHandlers() {
ExporterConfig exporterConfig = tracingConfig.getTracingExporter();
List<brave.handler.SpanHandler> res = new ArrayList<>();
if (!isSupportBraveURLSender()) {
return res;
}
ExporterConfig.ZipkinConfig zipkinConfig = exporterConfig.getZipkinConfig();
if (zipkinConfig != null && StringUtils.isNotEmpty(zipkinConfig.getEndpoint())) {
LOGGER.info("Create zipkin span handler.");
res.add(ZipkinSpanHandler.getSpanHandler(applicationModel, zipkinConfig));
}
return res;
}
private brave.sampler.Sampler getSampler() {
return brave.sampler.Sampler.create(tracingConfig.getSampling().getProbability());
}
private Optional<brave.baggage.CorrelationScopeCustomizer> correlationFieldsCorrelationScopeCustomizer() {
BaggageConfig.Correlation correlation = tracingConfig.getBaggage().getCorrelation();
boolean enabled = correlation.isEnabled();
if (!enabled) {
return Optional.empty();
}
return Optional.of((builder) -> {
List<String> correlationFields = correlation.getFields();
for (String field : correlationFields) {
builder.add(brave.baggage.CorrelationScopeConfig.SingleCorrelationField.newBuilder(brave.baggage.BaggageField.create(field))
.flushOnUpdate().build());
}
});
}
private brave.propagation.CurrentTraceContext.ScopeDecorator correlationScopeDecorator() {
brave.baggage.CorrelationScopeDecorator.Builder builder = brave.context.slf4j.MDCScopeDecorator.newBuilder();
correlationFieldsCorrelationScopeCustomizer().ifPresent((customizer) -> customizer.customize(builder));
return builder.build();
}
static class PropagatorFactory {
public static brave.propagation.Propagation.Factory getPropagationFactory(TracingConfig tracingConfig) {
BaggageConfig baggageConfig = tracingConfig.getBaggage();
if (baggageConfig == null || !baggageConfig.getEnabled()) {
return getPropagationFactoryWithoutBaggage(tracingConfig);
}
return getPropagationFactoryWithBaggage(tracingConfig);
}
private static brave.propagation.Propagation.Factory getPropagationFactoryWithoutBaggage(TracingConfig tracingConfig) {
PropagationType propagationType = PropagationType.forValue(tracingConfig.getPropagation().getType());
if (PropagationType.W3C == propagationType) {
return new io.micrometer.tracing.brave.bridge.W3CPropagation();
} else {
// Brave default propagation is B3
return brave.propagation.B3Propagation.newFactoryBuilder().injectFormat(brave.propagation.B3Propagation.Format.SINGLE_NO_PARENT).build();
}
}
private static brave.propagation.Propagation.Factory getPropagationFactoryWithBaggage(TracingConfig tracingConfig) {
PropagationType propagationType = PropagationType.forValue(tracingConfig.getPropagation().getType());
brave.propagation.Propagation.Factory delegate;
if (PropagationType.W3C == propagationType) {
delegate = new W3CPropagation(BRAVE_BAGGAGE_MANAGER, Collections.emptyList());
} else {
// Brave default propagation is B3
delegate = brave.propagation.B3Propagation.newFactoryBuilder().injectFormat(brave.propagation.B3Propagation.Format.SINGLE_NO_PARENT).build();
}
return getBaggageFactoryBuilder(delegate, tracingConfig).build();
}
private static brave.baggage.BaggagePropagation.FactoryBuilder getBaggageFactoryBuilder(brave.propagation.Propagation.Factory delegate, TracingConfig tracingConfig) {
brave.baggage.BaggagePropagation.FactoryBuilder builder = brave.baggage.BaggagePropagation.newFactoryBuilder(delegate);
getBaggagePropagationCustomizers(tracingConfig).forEach((customizer) -> customizer.customize(builder));
return builder;
}
private static List<brave.baggage.BaggagePropagationCustomizer> getBaggagePropagationCustomizers(TracingConfig tracingConfig) {
List<brave.baggage.BaggagePropagationCustomizer> res = new ArrayList<>();
if (tracingConfig.getBaggage().getCorrelation().isEnabled()) {
res.add(remoteFieldsBaggagePropagationCustomizer(tracingConfig));
}
return res;
}
private static brave.baggage.BaggagePropagationCustomizer remoteFieldsBaggagePropagationCustomizer(TracingConfig tracingConfig) {
return (builder) -> {
List<String> remoteFields = tracingConfig.getBaggage().getRemoteFields();
for (String fieldName : remoteFields) {
builder.add(brave.baggage.BaggagePropagationConfig.SingleBaggageField.remote(brave.baggage.BaggageField.create(fieldName)));
}
};
}
}
}

View File

@ -18,13 +18,19 @@ package org.apache.dubbo.tracing.tracer.otel;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.lang.Nullable;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.TracingConfig;
import org.apache.dubbo.config.nested.BaggageConfig;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.config.nested.PropagationConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.exporter.TraceExporterFactory;
import org.apache.dubbo.tracing.exporter.otlp.OTlpSpanExporter;
import org.apache.dubbo.tracing.exporter.zipkin.ZipkinSpanExporter;
import org.apache.dubbo.tracing.tracer.TracerProvider;
import org.apache.dubbo.tracing.utils.PropagationType;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.otel.bridge.CompositeSpanExporter;
@ -36,28 +42,17 @@ import io.micrometer.tracing.otel.bridge.OtelTracer;
import io.micrometer.tracing.otel.bridge.Slf4JBaggageEventListener;
import io.micrometer.tracing.otel.bridge.Slf4JEventListener;
import io.micrometer.tracing.otel.propagation.BaggageTextMapPropagator;
import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.ContextStorage;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.extension.trace.propagation.B3Propagator;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.apache.dubbo.tracing.utils.ObservationConstants.DEFAULT_APPLICATION_NAME;
public class OpenTelemetryProvider implements TracerProvider {
private static final String DEFAULT_APPLICATION_NAME = "dubbo-application";
private final static ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(OpenTelemetryProvider.class);
private final ApplicationModel applicationModel;
private final TracingConfig tracingConfig;
@ -72,7 +67,7 @@ public class OpenTelemetryProvider implements TracerProvider {
@Override
public Tracer getTracer() {
// [OTel component] SpanExporter is a component that gets called when a span is finished.
List<SpanExporter> spanExporters = TraceExporterFactory.getSpanExporters(applicationModel, tracingConfig.getTracingExporter());
List<io.opentelemetry.sdk.trace.export.SpanExporter> spanExporters = getSpanExporters();
String applicationName = applicationModel.getApplicationConfigManager().getApplication()
.map(ApplicationConfig::getName)
@ -84,18 +79,18 @@ public class OpenTelemetryProvider implements TracerProvider {
this.otelCurrentTraceContext = createCurrentTraceContext();
// [OTel component] SdkTracerProvider is an SDK implementation for TracerProvider
SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
io.opentelemetry.sdk.trace.SdkTracerProvider sdkTracerProvider = io.opentelemetry.sdk.trace.SdkTracerProvider.builder()
.setSampler(getSampler())
.setResource(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName)))
.addSpanProcessor(BatchSpanProcessor
.setResource(io.opentelemetry.sdk.resources.Resource.create(io.opentelemetry.api.common.Attributes.of(io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME, applicationName)))
.addSpanProcessor(io.opentelemetry.sdk.trace.export.BatchSpanProcessor
.builder(new CompositeSpanExporter(spanExporters, null, null, null))
.build())
.build();
ContextPropagators otelContextPropagators = createOtelContextPropagators();
io.opentelemetry.context.propagation.ContextPropagators otelContextPropagators = createOtelContextPropagators();
// [OTel component] The SDK implementation of OpenTelemetry
OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder()
io.opentelemetry.sdk.OpenTelemetrySdk openTelemetrySdk = io.opentelemetry.sdk.OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider)
.setPropagators(otelContextPropagators)
.build();
@ -113,14 +108,31 @@ public class OpenTelemetryProvider implements TracerProvider {
Collections.emptyList()));
}
private List<io.opentelemetry.sdk.trace.export.SpanExporter> getSpanExporters() {
ExporterConfig exporterConfig = tracingConfig.getTracingExporter();
ExporterConfig.ZipkinConfig zipkinConfig = exporterConfig.getZipkinConfig();
ExporterConfig.OtlpConfig otlpConfig = exporterConfig.getOtlpConfig();
List<io.opentelemetry.sdk.trace.export.SpanExporter> res = new ArrayList<>();
if (zipkinConfig != null && StringUtils.isNotEmpty(zipkinConfig.getEndpoint())) {
LOGGER.info("Create zipkin span exporter.");
res.add(ZipkinSpanExporter.getSpanExporter(applicationModel, zipkinConfig));
}
if (otlpConfig != null && StringUtils.isNotEmpty(otlpConfig.getEndpoint())) {
LOGGER.info("Create OTlp span exporter.");
res.add(OTlpSpanExporter.getSpanExporter(applicationModel, otlpConfig));
}
return res;
}
/**
* sampler with probability
*
* @return sampler
*/
private Sampler getSampler() {
Sampler rootSampler = Sampler.traceIdRatioBased(tracingConfig.getSampling().getProbability());
return Sampler.parentBased(rootSampler);
private io.opentelemetry.sdk.trace.samplers.Sampler getSampler() {
io.opentelemetry.sdk.trace.samplers.Sampler rootSampler = io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(tracingConfig.getSampling().getProbability());
return io.opentelemetry.sdk.trace.samplers.Sampler.parentBased(rootSampler);
}
private List<EventListener> getEventListeners() {
@ -141,13 +153,13 @@ public class OpenTelemetryProvider implements TracerProvider {
}
private OtelCurrentTraceContext createCurrentTraceContext() {
ContextStorage.addWrapper(new EventPublishingContextWrapper(publisher));
io.opentelemetry.context.ContextStorage.addWrapper(new EventPublishingContextWrapper(publisher));
return new OtelCurrentTraceContext();
}
private ContextPropagators createOtelContextPropagators() {
return ContextPropagators.create(
TextMapPropagator.composite(
private io.opentelemetry.context.propagation.ContextPropagators createOtelContextPropagators() {
return io.opentelemetry.context.propagation.ContextPropagators.create(
io.opentelemetry.context.propagation.TextMapPropagator.composite(
PropagatorFactory.getPropagator(tracingConfig.getPropagation(),
tracingConfig.getBaggage(),
otelCurrentTraceContext
@ -172,41 +184,44 @@ public class OpenTelemetryProvider implements TracerProvider {
static class PropagatorFactory {
public static TextMapPropagator getPropagator(PropagationConfig propagationConfig,
@Nullable BaggageConfig baggageConfig,
@Nullable OtelCurrentTraceContext currentTraceContext) {
public static io.opentelemetry.context.propagation.TextMapPropagator getPropagator(PropagationConfig propagationConfig,
@Nullable BaggageConfig baggageConfig,
@Nullable OtelCurrentTraceContext currentTraceContext) {
if (baggageConfig == null || !baggageConfig.getEnabled()) {
return getPropagatorWithoutBaggage(propagationConfig);
}
return getPropagatorWithBaggage(propagationConfig, baggageConfig, currentTraceContext);
}
private static TextMapPropagator getPropagatorWithoutBaggage(PropagationConfig propagationConfig) {
private static io.opentelemetry.context.propagation.TextMapPropagator getPropagatorWithoutBaggage(PropagationConfig propagationConfig) {
String type = propagationConfig.getType();
if ("B3".equals(type)) {
return B3Propagator.injectingSingleHeader();
} else if ("W3C".equals(type)) {
return W3CTraceContextPropagator.getInstance();
PropagationType propagationType = PropagationType.forValue(type);
if (PropagationType.B3 == propagationType) {
return io.opentelemetry.extension.trace.propagation.B3Propagator.injectingSingleHeader();
} else if (PropagationType.W3C == propagationType) {
return io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator.getInstance();
}
return TextMapPropagator.noop();
return io.opentelemetry.context.propagation.TextMapPropagator.noop();
}
private static TextMapPropagator getPropagatorWithBaggage(PropagationConfig propagationConfig,
BaggageConfig baggageConfig,
OtelCurrentTraceContext currentTraceContext) {
private static io.opentelemetry.context.propagation.TextMapPropagator getPropagatorWithBaggage(PropagationConfig propagationConfig,
BaggageConfig baggageConfig,
OtelCurrentTraceContext currentTraceContext) {
String type = propagationConfig.getType();
if ("B3".equals(type)) {
PropagationType propagationType = PropagationType.forValue(type);
if (PropagationType.B3 == propagationType) {
List<String> remoteFields = baggageConfig.getRemoteFields();
return TextMapPropagator.composite(B3Propagator.injectingSingleHeader(),
return io.opentelemetry.context.propagation.TextMapPropagator.composite(io.opentelemetry.extension.trace.propagation.B3Propagator.injectingSingleHeader(),
new BaggageTextMapPropagator(remoteFields,
new OtelBaggageManager(currentTraceContext, remoteFields, Collections.emptyList())));
} else if ("W3C".equals(type)) {
} else if (PropagationType.W3C == propagationType) {
List<String> remoteFields = baggageConfig.getRemoteFields();
return TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(),
W3CBaggagePropagator.getInstance(), new BaggageTextMapPropagator(remoteFields,
return io.opentelemetry.context.propagation.TextMapPropagator.composite(io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator.getInstance(),
io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator.getInstance(), new BaggageTextMapPropagator(remoteFields,
new OtelBaggageManager(currentTraceContext, remoteFields, Collections.emptyList())));
}
return TextMapPropagator.noop();
return io.opentelemetry.context.propagation.TextMapPropagator.noop();
}
}
}

View File

@ -14,24 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.tracing.exporter;
import brave.handler.SpanHandler;
import io.opentelemetry.sdk.trace.export.SpanExporter;
package org.apache.dubbo.tracing.utils;
public interface TraceExporter {
public class ObservationConstants {
/**
* for otel
*
* @return
*/
SpanExporter getSpanExporter();
/**
* for brave
*
* @return
*/
SpanHandler getSpanHandler();
public static final String DEFAULT_APPLICATION_NAME = "dubbo-application";
}

View File

@ -43,6 +43,10 @@ public class ObservationSupportUtil {
&& isClassPresent("brave.Tracing");
}
public static boolean isSupportBraveURLSender() {
return isClassPresent("zipkin2.reporter.urlconnection.URLConnectionSender");
}
private static boolean isClassPresent(String className) {
return ClassUtils.isPresent(className, ObservationSupportUtil.class.getClassLoader());
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.utils;
public enum PropagationType {
W3C("W3C"),
B3("B3");
private final String value;
PropagationType(String type) {
this.value = type;
}
public String getValue() {
return value;
}
public static PropagationType forValue(String value) {
PropagationType[] values = values();
for (PropagationType type : values) {
if (type.getValue().equals(value)) {
return type;
}
}
return null;
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.exporter.otlp;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class OTlpSpanExporterTest {
@Test
void getSpanExporter() {
ExporterConfig.OtlpConfig otlpConfig = mock(ExporterConfig.OtlpConfig.class);
when(otlpConfig.getEndpoint()).thenReturn("http://localhost:9411/api/v2/spans");
when(otlpConfig.getTimeout()).thenReturn(Duration.ofSeconds(5));
when(otlpConfig.getCompressionMethod()).thenReturn("gzip");
SpanExporter spanExporter = OTlpSpanExporter.getSpanExporter(ApplicationModel.defaultModel(), otlpConfig);
Assertions.assertNotNull(spanExporter);
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.exporter.zipkin;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class ZipkinSpanExporterTest {
@Test
void getSpanExporter() {
ExporterConfig.ZipkinConfig zipkinConfig = mock(ExporterConfig.ZipkinConfig.class);
when(zipkinConfig.getEndpoint()).thenReturn("http://localhost:9411/api/v2/spans");
when(zipkinConfig.getConnectTimeout()).thenReturn(Duration.ofSeconds(5));
when(zipkinConfig.getReadTimeout()).thenReturn(Duration.ofSeconds(5));
SpanExporter spanExporter = ZipkinSpanExporter.getSpanExporter(ApplicationModel.defaultModel(), zipkinConfig);
Assertions.assertNotNull(spanExporter);
}
}

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.exporter.zipkin;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import brave.handler.SpanHandler;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class ZipkinSpanHandlerTest {
@Test
void getSpanHandler() {
ExporterConfig.ZipkinConfig zipkinConfig = mock(ExporterConfig.ZipkinConfig.class);
when(zipkinConfig.getEndpoint()).thenReturn("http://localhost:9411/api/v2/spans");
when(zipkinConfig.getConnectTimeout()).thenReturn(Duration.ofSeconds(5));
SpanHandler spanHandler = ZipkinSpanHandler.getSpanHandler(ApplicationModel.defaultModel(), zipkinConfig);
Assertions.assertNotNull(spanHandler);
}
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.tracer.brave;
import org.apache.dubbo.common.utils.Assert;
import brave.Tracing;
import io.micrometer.tracing.propagation.Propagator;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.mock;
class BravePropagatorProviderTest {
@Test
void testBravePropagatorProvider() {
Tracing tracing = mock(Tracing.class);
BravePropagatorProvider.createMicrometerPropagator(tracing);
BravePropagatorProvider bravePropagatorProvider = new BravePropagatorProvider();
Propagator propagator = bravePropagatorProvider.getPropagator();
Assert.notNull(propagator, "Propagator don't be null.");
}
}

View File

@ -0,0 +1,86 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.tracer.brave;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.config.TracingConfig;
import org.apache.dubbo.config.nested.BaggageConfig;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.config.nested.PropagationConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.utils.PropagationType;
import brave.propagation.Propagation;
import io.micrometer.tracing.Tracer;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class BraveProviderTest {
@Test
void testGetTracer() {
TracingConfig tracingConfig = new TracingConfig();
tracingConfig.setEnabled(true);
ExporterConfig exporterConfig = new ExporterConfig();
exporterConfig.setZipkinConfig(new ExporterConfig.ZipkinConfig(""));
tracingConfig.setTracingExporter(exporterConfig);
BraveProvider braveProvider = new BraveProvider(ApplicationModel.defaultModel(), tracingConfig);
Tracer tracer = braveProvider.getTracer();
Assert.notNull(tracer, "Tracer should not be null.");
assertEquals(io.micrometer.tracing.brave.bridge.BraveTracer.class, tracer.getClass());
}
@Test
void testGetPropagator() {
TracingConfig tracingConfig = mock(TracingConfig.class);
PropagationConfig propagationConfig = mock(PropagationConfig.class);
when(tracingConfig.getPropagation()).thenReturn(propagationConfig);
BaggageConfig baggageConfig = mock(BaggageConfig.class);
when(tracingConfig.getBaggage()).thenReturn(baggageConfig);
// no baggage
when(baggageConfig.getEnabled()).thenReturn(Boolean.FALSE);
when(propagationConfig.getType()).thenReturn(PropagationType.W3C.getValue());
Propagation.Factory w3cPropagationFactoryWithoutBaggage = BraveProvider.PropagatorFactory.getPropagationFactory(tracingConfig);
assertEquals(io.micrometer.tracing.brave.bridge.W3CPropagation.class, w3cPropagationFactoryWithoutBaggage.getClass());
when(propagationConfig.getType()).thenReturn(PropagationType.B3.getValue());
Propagation.Factory b3PropagationFactoryWithoutBaggage = BraveProvider.PropagatorFactory.getPropagationFactory(tracingConfig);
Assert.notNull(b3PropagationFactoryWithoutBaggage, "b3PropagationFactoryWithoutBaggage should not be null.");
// with baggage
when(baggageConfig.getEnabled()).thenReturn(Boolean.TRUE);
BaggageConfig.Correlation correlation = mock(BaggageConfig.Correlation.class);
when(correlation.isEnabled()).thenReturn(Boolean.TRUE);
when(baggageConfig.getCorrelation()).thenReturn(correlation);
List<String> remoteFields = new ArrayList<>();
for (int i = 0; i < 10; i++) {
remoteFields.add("test-hd-" + i);
}
when(baggageConfig.getRemoteFields()).thenReturn(remoteFields);
Propagation.Factory propagationFactoryWithBaggage = BraveProvider.PropagatorFactory.getPropagationFactory(tracingConfig);
Assert.notNull(propagationFactoryWithBaggage, "propagationFactoryWithBaggage should not be null.");
}
}

View File

@ -23,6 +23,7 @@ import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.propagation.ContextPropagators;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
class OTelPropagatorProviderTest {

View File

@ -20,15 +20,23 @@ import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.config.TracingConfig;
import org.apache.dubbo.config.nested.BaggageConfig;
import org.apache.dubbo.config.nested.ExporterConfig;
import org.apache.dubbo.config.nested.PropagationConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.tracing.tracer.TracerProvider;
import org.apache.dubbo.tracing.tracer.TracerProviderFactory;
import org.apache.dubbo.tracing.utils.PropagationType;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.otel.bridge.OtelCurrentTraceContext;
import io.micrometer.tracing.otel.bridge.OtelTracer;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.extension.trace.propagation.B3Propagator;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class OpenTelemetryProviderTest {
@ -50,4 +58,28 @@ class OpenTelemetryProviderTest {
Tracer tracer2 = tracerProvider2.getTracer();
assertEquals(OtelTracer.class, tracer2.getClass());
}
@Test
void testGetPropagator() {
PropagationConfig propagationConfig = mock(PropagationConfig.class);
BaggageConfig baggageConfig = mock(BaggageConfig.class);
OtelCurrentTraceContext otelCurrentTraceContext = mock(OtelCurrentTraceContext.class);
when(baggageConfig.getEnabled()).thenReturn(Boolean.FALSE);
when(propagationConfig.getType()).thenReturn(PropagationType.B3.getValue());
TextMapPropagator b3PropagatorWithoutBaggage = OpenTelemetryProvider.PropagatorFactory.getPropagator(propagationConfig, baggageConfig, otelCurrentTraceContext);
assertEquals(B3Propagator.class, b3PropagatorWithoutBaggage.getClass());
when(propagationConfig.getType()).thenReturn(PropagationType.W3C.getValue());
TextMapPropagator w3cPropagatorWithoutBaggage = OpenTelemetryProvider.PropagatorFactory.getPropagator(propagationConfig, baggageConfig, otelCurrentTraceContext);
assertEquals(W3CTraceContextPropagator.class, w3cPropagatorWithoutBaggage.getClass());
when(baggageConfig.getEnabled()).thenReturn(Boolean.TRUE);
TextMapPropagator propagatorWithBaggage = OpenTelemetryProvider.PropagatorFactory.getPropagator(propagationConfig, baggageConfig, otelCurrentTraceContext);
Assert.notNull(propagatorWithBaggage, "PropagatorWithBaggage should not be null");
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.dubbo.tracing.utils;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
class PropagationTypeTest {
@Test
void forValue() {
PropagationType propagationType1 = PropagationType.forValue("W3C");
assertEquals(PropagationType.W3C, propagationType1);
PropagationType propagationType2 = PropagationType.forValue("B3");
assertEquals(PropagationType.B3, propagationType2);
PropagationType propagationType3 = PropagationType.forValue("B33");
assertNull(propagationType3);
}
}