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

Addresses opencensus-shim trace issues under otel javaagent #4900

Merged
merged 7 commits into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.opencensusshim;

import com.google.errorprone.annotations.MustBeClosed;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import java.time.Instant;
import java.util.concurrent.TimeUnit;

/**
* Delegates <i>all</i> {@link Span} methods to some underlying Span via {@link
* DelegatingSpan#getDelegate()}.
*
* <p>If not all calls are proxied, some, such as and in particular {@link
* Span#storeInContext(Context)} and {@link Span#makeCurrent()}, will use {@code this} instead of
* the proxied {@link Span} which betrays the expectation of instance fidelity imposed by the
* underlying otel mechanisms which minted the original {@link Span}, such as the otel javaagent.
*
* <p>This proxy class simplification allows the shim to perform its duties as minimally invasively
* as possible and itself never expose its own classes and objects to callers or recipients of calls
* from the shim.
*
* <p>This addresses the inconsistency where not all methods are appropriately delegated by exposing
* a single method, {@link DelegatingSpan#getDelegate()}, to simplify and better ensure delegation
* and meeting expectations.
*/
interface DelegatingSpan extends Span {
Span getDelegate();

@Override
default Span updateName(String name) {
return getDelegate().updateName(name);
}

@Override
default SpanContext getSpanContext() {
return getDelegate().getSpanContext();
}

@Override
default boolean isRecording() {
return getDelegate().isRecording();
}

@Override
default <T> Span setAttribute(AttributeKey<T> key, T value) {
return getDelegate().setAttribute(key, value);
}

@Override
default Span setAttribute(String key, String value) {
return getDelegate().setAttribute(key, value);
}

@Override
default Span setAttribute(String key, long value) {
return getDelegate().setAttribute(key, value);
}

@Override
default Span setAttribute(String key, double value) {
return getDelegate().setAttribute(key, value);
}

@Override
default Span setAttribute(String key, boolean value) {
return getDelegate().setAttribute(key, value);
}

@Override
default Span setAttribute(AttributeKey<Long> key, int value) {
return getDelegate().setAttribute(key, value);
}

@Override
default Span setAllAttributes(Attributes attributes) {
return getDelegate().setAllAttributes(attributes);
}

@Override
default Span addEvent(String name, Attributes attributes) {
return getDelegate().addEvent(name, attributes);
}

@Override
default Span addEvent(String name, Attributes attributes, long timestamp, TimeUnit unit) {
return getDelegate().addEvent(name, attributes, timestamp, unit);
}

@Override
default Span addEvent(String name) {
return getDelegate().addEvent(name);
}

@Override
default Span addEvent(String name, long timestamp, TimeUnit unit) {
return getDelegate().addEvent(name, timestamp, unit);
}

@Override
default Span addEvent(String name, Instant timestamp) {
return getDelegate().addEvent(name, timestamp);
}

@Override
default Span addEvent(String name, Attributes attributes, Instant timestamp) {
return getDelegate().addEvent(name, attributes, timestamp);
}

@Override
default Span setStatus(StatusCode statusCode, String description) {
return getDelegate().setStatus(statusCode, description);
}

@Override
default Span setStatus(StatusCode statusCode) {
return getDelegate().setStatus(statusCode);
}

@Override
default Span recordException(Throwable exception, Attributes additionalAttributes) {
return getDelegate().recordException(exception, additionalAttributes);
}

@Override
default Span recordException(Throwable exception) {
return getDelegate().recordException(exception);
}

@Override
default void end(Instant timestamp) {
getDelegate().end(timestamp);
}

@Override
default void end() {
getDelegate().end();
}

@Override
default void end(long timestamp, TimeUnit unit) {
getDelegate().end(timestamp, unit);
}

@Override
default Context storeInContext(Context context) {
return getDelegate().storeInContext(context);
}

@MustBeClosed
@Override
default Scope makeCurrent() {
return getDelegate().makeCurrent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@
import io.opentelemetry.api.trace.StatusCode;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.annotation.Nonnull;

class OpenTelemetrySpanImpl extends Span implements io.opentelemetry.api.trace.Span {
class OpenTelemetrySpanImpl extends Span
implements io.opentelemetry.api.trace.Span, DelegatingSpan {
private static final Logger LOGGER = Logger.getLogger(OpenTelemetrySpanImpl.class.getName());
private static final EnumSet<Span.Options> RECORD_EVENTS_SPAN_OPTIONS =
EnumSet.of(Span.Options.RECORD_EVENTS);
Expand All @@ -62,15 +61,24 @@ class OpenTelemetrySpanImpl extends Span implements io.opentelemetry.api.trace.S
this.otelSpan = otelSpan;
}

// otel

@Override
public io.opentelemetry.api.trace.Span getDelegate() {
return otelSpan;
}

// opencensus

@Override
public void putAttribute(String key, AttributeValue value) {
Preconditions.checkNotNull(key, "key");
Preconditions.checkNotNull(value, "value");
value.match(
arg -> otelSpan.setAttribute(key, arg),
arg -> otelSpan.setAttribute(key, arg),
arg -> otelSpan.setAttribute(key, arg),
arg -> otelSpan.setAttribute(key, arg),
arg -> DelegatingSpan.super.setAttribute(key, arg),
arg -> DelegatingSpan.super.setAttribute(key, arg),
arg -> DelegatingSpan.super.setAttribute(key, arg),
arg -> DelegatingSpan.super.setAttribute(key, arg),
arg -> null);
}

Expand All @@ -84,14 +92,14 @@ public void putAttributes(Map<String, AttributeValue> attributes) {
public void addAnnotation(String description, Map<String, AttributeValue> attributes) {
AttributesBuilder attributesBuilder = Attributes.builder();
mapAttributes(attributes, attributesBuilder);
otelSpan.addEvent(description, attributesBuilder.build());
DelegatingSpan.super.addEvent(description, attributesBuilder.build());
}

@Override
public void addAnnotation(Annotation annotation) {
AttributesBuilder attributesBuilder = Attributes.builder();
mapAttributes(annotation.getAttributes(), attributesBuilder);
otelSpan.addEvent(annotation.getDescription(), attributesBuilder.build());
DelegatingSpan.super.addEvent(annotation.getDescription(), attributesBuilder.build());
}

@Override
Expand All @@ -101,7 +109,7 @@ public void addLink(Link link) {

@Override
public void addMessageEvent(MessageEvent messageEvent) {
otelSpan.addEvent(
DelegatingSpan.super.addEvent(
String.valueOf(messageEvent.getMessageId()),
Attributes.of(
AttributeKey.stringKey(MESSAGE_EVENT_ATTRIBUTE_KEY_TYPE),
Expand All @@ -115,70 +123,22 @@ public void addMessageEvent(MessageEvent messageEvent) {
@Override
public void setStatus(Status status) {
Preconditions.checkNotNull(status, "status");
otelSpan.setStatus(status.isOk() ? StatusCode.OK : StatusCode.ERROR);
DelegatingSpan.super.setStatus(status.isOk() ? StatusCode.OK : StatusCode.ERROR);
}

@Override
public io.opentelemetry.api.trace.Span setStatus(StatusCode canonicalCode, String description) {
return otelSpan.setStatus(canonicalCode, description);
return DelegatingSpan.super.setStatus(canonicalCode, description);
}

@Override
public void end(EndSpanOptions options) {
otelSpan.end();
}

@Override
@SuppressWarnings("ParameterPackage")
public void end(long timestamp, TimeUnit unit) {
otelSpan.end(timestamp, unit);
}

@Override
public <T> io.opentelemetry.api.trace.Span setAttribute(AttributeKey<T> key, @Nonnull T value) {
return otelSpan.setAttribute(key, value);
}

@Override
public io.opentelemetry.api.trace.Span addEvent(String name) {
return otelSpan.addEvent(name);
}

@Override
public io.opentelemetry.api.trace.Span addEvent(String name, long timestamp, TimeUnit unit) {
return otelSpan.addEvent(name, timestamp, unit);
}

@Override
public io.opentelemetry.api.trace.Span addEvent(String name, Attributes attributes) {
return otelSpan.addEvent(name, attributes);
}

@Override
public io.opentelemetry.api.trace.Span addEvent(
String name, Attributes attributes, long timestamp, TimeUnit unit) {
return otelSpan.addEvent(name, attributes, timestamp, unit);
}

@Override
public io.opentelemetry.api.trace.Span recordException(Throwable exception) {
return otelSpan.recordException(exception);
}

@Override
public io.opentelemetry.api.trace.Span recordException(
Throwable exception, Attributes additionalAttributes) {
return otelSpan.recordException(exception, additionalAttributes);
}

@Override
public io.opentelemetry.api.trace.Span updateName(String name) {
return otelSpan.updateName(name);
DelegatingSpan.super.end();
}

@Override
public SpanContext getSpanContext() {
return otelSpan.getSpanContext();
return DelegatingSpan.super.getSpanContext();
}

@Override
Expand Down
Loading