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

Add asynchronous tracing to Spring Boot Autoconfigure WithSpanAspect #2618

Merged
merged 2 commits into from
Mar 29, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Refactor MethodSpanStrategies to instrumentation-api, update Spring a…
…spect
  • Loading branch information
HaloFour committed Mar 29, 2021
commit a4abac8fd977ca73d69cf9e94585a5582a40537b
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.otelannotations.async;
package io.opentelemetry.instrumentation.api.tracer.async;

import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.otelannotations.async;
package io.opentelemetry.instrumentation.api.tracer.async;

import java.util.List;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.otelannotations.async;
package io.opentelemetry.instrumentation.api.tracer.async;

import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.otelannotations.async;
package io.opentelemetry.instrumentation.api.tracer.async;

import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
* Provides implementations of strategies for tracing methods that return asynchronous and reactive
* values so that the span can be ended when the asynchronous operation completes.
*/
package io.opentelemetry.javaagent.instrumentation.otelannotations.async;
package io.opentelemetry.instrumentation.api.tracer.async;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe .async -> .future or .promise

.async feels a bit general

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably gravitate to reactive but that's probably as general as async is. Of your suggestions I think future probably fits better in the Java ecosystem.

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.tracer.async

import io.opentelemetry.context.Context
import io.opentelemetry.instrumentation.api.tracer.BaseTracer
import spock.lang.Specification

import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionException

class Jdk8MethodStrategyTest extends Specification {
BaseTracer tracer

Context context

def underTest = Jdk8MethodStrategy.INSTANCE

void setup() {
tracer = Mock()
context = Mock()
}

def "ends span on completed future"() {
when:
underTest.end(tracer, context, CompletableFuture.completedFuture("completed"))

then:
1 * tracer.end(context)
}

def "ends span exceptionally on failed future"() {
given:
def exception = new CompletionException()
def future = new CompletableFuture<String>()
future.completeExceptionally(exception)

when:
underTest.end(tracer, context, future)

then:
1 * tracer.endExceptionally(context, exception)
}

def "ends span on future when complete"() {
def future = new CompletableFuture<String>()

when:
underTest.end(tracer, context, future)

then:
0 * tracer._

when:
future.complete("completed")

then:
1 * tracer.end(context)
}

def "ends span exceptionally on future when completed exceptionally"() {
def future = new CompletableFuture<String>()
def exception = new Exception()

when:
underTest.end(tracer, context, future)

then:
0 * tracer._

when:
future.completeExceptionally(exception)

then:
1 * tracer.endExceptionally(context, exception)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.tracer.async

import io.opentelemetry.context.Context
import io.opentelemetry.instrumentation.api.tracer.BaseTracer
import spock.lang.Specification

class SynchronousMethodSpanStrategyTest extends Specification {
BaseTracer tracer

Context context

def underTest = SynchronousMethodSpanStrategy.INSTANCE

void setup() {
tracer = Mock()
context = Mock()
}

def "ends span on any result"() {
when:
underTest.end(tracer, context, "any result")

then:
1 * tracer.end(context)
}

def "ends span on null result"() {
when:
underTest.end(tracer, context, null)

then:
1 * tracer.end(context)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import io.opentelemetry.javaagent.instrumentation.otelannotations.async.MethodSpanStrategies;
import io.opentelemetry.instrumentation.api.tracer.async.MethodSpanStrategies;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ public Object traceMethod(ProceedingJoinPoint pjp) throws Throwable {
Context context = tracer.startSpan(parentContext, withSpan, method);
try (Scope ignored = context.makeCurrent()) {
Object result = pjp.proceed();
tracer.end(context);
return result;
return tracer.end(context, method.getReturnType(), result);
} catch (Throwable t) {
tracer.endExceptionally(context, t);
throw t;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
import io.opentelemetry.context.Context;
import io.opentelemetry.extension.annotations.WithSpan;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import io.opentelemetry.instrumentation.api.tracer.async.MethodSpanStrategies;
import java.lang.reflect.Method;

class WithSpanAspectTracer extends BaseTracer {

private final MethodSpanStrategies methodSpanStrategies = MethodSpanStrategies.getInstance();

WithSpanAspectTracer(OpenTelemetry openTelemetry) {
super(openTelemetry);
}
Expand Down Expand Up @@ -42,4 +46,23 @@ private String spanName(WithSpan annotation, Method method) {
}
return spanName;
}

/**
* Denotes the end of the invocation of the traced method with a successful result which will end
* the span stored in the passed {@code context}. If the method returned a value representing an
* asynchronous operation then the span will not be finished until the asynchronous operation has
* completed.
*
* @param returnType Return type of the traced method.
* @param returnValue Return value from the traced method.
* @return Either {@code returnValue} or a value composing over {@code returnValue} for
* notification of completion.
*/
public Object end(Context context, Class<?> returnType, Object returnValue) {
if (!returnType.isInstance(returnValue)) {
end(context);
return returnValue;
}
return methodSpanStrategies.resolveStrategy(returnType).end(this, context, returnValue);
}
}
Loading