blob: b57c061a4f3a57ea7f48e412997a08c19c6d285b [file] [log] [blame]
/*
* 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.camel.opentelemetry;
import java.util.Set;
import io.grpc.Context;
import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.context.Scope;
import io.opentelemetry.trace.DefaultTracer;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.SpanContext;
import io.opentelemetry.trace.Tracer;
import io.opentelemetry.trace.TracingContextUtils;
import org.apache.camel.Exchange;
import org.apache.camel.api.management.ManagedResource;
import org.apache.camel.opentelemetry.propagators.OpenTelemetryGetter;
import org.apache.camel.opentelemetry.propagators.OpenTelemetrySetter;
import org.apache.camel.tracing.ExtractAdapter;
import org.apache.camel.tracing.InjectAdapter;
import org.apache.camel.tracing.SpanAdapter;
import org.apache.camel.tracing.SpanDecorator;
import org.apache.camel.tracing.SpanKind;
import org.apache.camel.tracing.decorators.AbstractInternalSpanDecorator;
@ManagedResource(description = "OpenTelemetryTracer")
public class OpenTelemetryTracer extends org.apache.camel.tracing.Tracer {
private Tracer tracer;
public Tracer getTracer() {
return tracer;
}
public void setTracer(Tracer tracer) {
this.tracer = tracer;
}
private Span.Kind mapToSpanKind(SpanKind kind) {
switch (kind) {
case SPAN_KIND_CLIENT: return Span.Kind.CLIENT;
case SPAN_KIND_SERVER: return Span.Kind.SERVER;
case CONSUMER: return Span.Kind.CONSUMER;
case PRODUCER: return Span.Kind.PRODUCER;
default: return Span.Kind.SERVER;
}
}
@Override
protected void initTracer() {
if (tracer == null) {
Set<Tracer> tracers = getCamelContext().getRegistry().findByType(Tracer.class);
if (tracers.size() == 1) {
tracer = tracers.iterator().next();
}
}
if (tracer == null) {
// No tracer is available, so setup NoopTracer
tracer = DefaultTracer.getInstance();
}
}
@Override
protected SpanAdapter startSendingEventSpan(String operationName, SpanKind kind, SpanAdapter parent) {
Span.Builder builder = tracer.spanBuilder(operationName).setSpanKind(mapToSpanKind(kind));
if (parent != null) {
OpenTelemetrySpanAdapter oTelSpanWrapper = (OpenTelemetrySpanAdapter) parent;
Span parentSpan = oTelSpanWrapper.getOpenTelemetrySpan();
builder = builder.setParent(parentSpan);
}
return new OpenTelemetrySpanAdapter(builder.startSpan());
}
@Override
protected SpanAdapter startExchangeBeginSpan(Exchange exchange, SpanDecorator sd, String operationName, SpanKind kind, SpanAdapter parent) {
Span.Builder builder = tracer.spanBuilder(operationName);
if (parent != null) {
OpenTelemetrySpanAdapter spanFromExchange = (OpenTelemetrySpanAdapter) parent;
builder = builder.setParent(spanFromExchange.getOpenTelemetrySpan());
} else {
ExtractAdapter adapter = sd.getExtractAdapter(exchange.getIn().getHeaders(), encoding);
Context ctx = OpenTelemetry.getPropagators().getHttpTextFormat().extract(Context.current(), adapter, new OpenTelemetryGetter(adapter));
Span span = TracingContextUtils.getSpan(ctx);
SpanContext parentFromHeaders = span.getContext();
if (parentFromHeaders != null && parentFromHeaders.isValid()) {
builder.setParent(parentFromHeaders).setSpanKind(mapToSpanKind(sd.getReceiverSpanKind()));
} else if (!(sd instanceof AbstractInternalSpanDecorator)) {
builder.setSpanKind(mapToSpanKind(sd.getReceiverSpanKind()));
}
}
return new OpenTelemetrySpanAdapter(builder.startSpan());
}
@Override
protected void finishSpan(SpanAdapter span) {
OpenTelemetrySpanAdapter openTracingSpanWrapper = (OpenTelemetrySpanAdapter) span;
openTracingSpanWrapper.getOpenTelemetrySpan().end();
}
@Override
protected void inject(SpanAdapter span, InjectAdapter adapter) {
OpenTelemetrySpanAdapter spanFromExchange = (OpenTelemetrySpanAdapter) span;
try (Scope scope = tracer.withSpan(spanFromExchange.getOpenTelemetrySpan())) {
OpenTelemetry.getPropagators().getHttpTextFormat().inject(Context.current(), adapter, new OpenTelemetrySetter());
}
}
}