Split out gRPC library instrumentation. (#1329)

* Split out gRPC library instrumentation.

* Simpler status
This commit is contained in:
Anuraag Agrawal 2020-10-07 17:57:28 +09:00 committed by GitHub
parent 9523f9ffe6
commit 525b3f729d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 448 additions and 358 deletions

View File

@ -5,4 +5,12 @@
package io.opentelemetry.instrumentation.api.tracer;
public abstract class RpcClientTracer extends BaseTracer {}
import io.opentelemetry.trace.Tracer;
public abstract class RpcClientTracer extends BaseTracer {
protected RpcClientTracer() {}
protected RpcClientTracer(Tracer tracer) {
super(tracer);
}
}

View File

@ -9,9 +9,16 @@ import static io.opentelemetry.OpenTelemetry.getPropagators;
import io.grpc.Context;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.trace.Tracer;
public abstract class RpcServerTracer<REQUEST> extends BaseTracer {
protected RpcServerTracer() {}
protected RpcServerTracer(Tracer tracer) {
super(tracer);
}
protected abstract TextMapPropagator.Getter<REQUEST> getGetter();
protected <C> Context extract(C carrier, TextMapPropagator.Getter<C> getter) {

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed 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.
*/
apply from: "$rootDir/gradle/instrumentation.gradle"
muzzle {
pass {
group = "io.grpc"
module = "grpc-core"
versions = "[1.5.0,)"
}
}
def grpcVersion = '1.5.0'
dependencies {
implementation project(':instrumentation:grpc-1.5:library')
library group: 'io.grpc', name: 'grpc-core', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-netty', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-stub', version: grpcVersion
testImplementation project(':instrumentation:grpc-1.5:testing')
}

View File

@ -0,0 +1,32 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.v1_5;
import io.opentelemetry.javaagent.tooling.Instrumenter;
abstract class AbstractGrpcInstrumentation extends Instrumenter.Default {
public AbstractGrpcInstrumentation() {
super("grpc");
}
@Override
public final String[] helperClassNames() {
return new String[] {
"io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper",
"io.opentelemetry.instrumentation.grpc.v1_5.client.GrpcClientTracer",
"io.opentelemetry.instrumentation.grpc.v1_5.client.GrpcInjectAdapter",
"io.opentelemetry.instrumentation.grpc.v1_5.client.TracingClientInterceptor",
"io.opentelemetry.instrumentation.grpc.v1_5.client.TracingClientInterceptor$TracingClientCall",
"io.opentelemetry.instrumentation.grpc.v1_5.client.TracingClientInterceptor$TracingClientCallListener",
"io.opentelemetry.instrumentation.grpc.v1_5.server.GrpcExtractAdapter",
"io.opentelemetry.instrumentation.grpc.v1_5.server.GrpcServerTracer",
"io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor",
"io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor$TracingServerCall",
"io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor$TracingServerCallListener",
};
}
}

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.client;
package io.opentelemetry.instrumentation.auto.grpc.v1_5;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static java.util.Collections.singletonMap;
@ -13,11 +13,8 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.grpc.ClientInterceptor;
import io.grpc.ManagedChannelBuilder;
import io.opentelemetry.instrumentation.auto.api.ContextStore;
import io.opentelemetry.instrumentation.auto.api.InstrumentationContext;
import io.opentelemetry.instrumentation.grpc.v1_5.client.TracingClientInterceptor;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import net.bytebuddy.asm.Advice;
@ -26,7 +23,7 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class)
public class GrpcClientBuilderBuildInstrumentation extends AbstractGrpcClientInstrumentation {
public class GrpcClientBuilderBuildInstrumentation extends AbstractGrpcInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
@ -45,7 +42,6 @@ public class GrpcClientBuilderBuildInstrumentation extends AbstractGrpcClientIns
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void addInterceptor(
@Advice.This ManagedChannelBuilder thiz,
@Advice.FieldValue("interceptors") List<ClientInterceptor> interceptors) {
boolean shouldRegister = true;
for (ClientInterceptor interceptor : interceptors) {
@ -55,10 +51,7 @@ public class GrpcClientBuilderBuildInstrumentation extends AbstractGrpcClientIns
}
}
if (shouldRegister) {
ContextStore<ManagedChannelBuilder, InetSocketAddress> contextStore =
InstrumentationContext.get(ManagedChannelBuilder.class, InetSocketAddress.class);
InetSocketAddress sockAddr = contextStore.get(thiz);
interceptors.add(0, new TracingClientInterceptor(sockAddr));
interceptors.add(0, TracingClientInterceptor.newInterceptor());
}
}
}

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.server;
package io.opentelemetry.instrumentation.auto.grpc.v1_5;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@ -11,6 +11,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.grpc.ServerInterceptor;
import io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.util.List;
import java.util.Map;
@ -20,29 +21,13 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@AutoService(Instrumenter.class)
public class GrpcServerBuilderInstrumentation extends Instrumenter.Default {
public GrpcServerBuilderInstrumentation() {
super("grpc", "grpc-server");
}
public class GrpcServerBuilderInstrumentation extends AbstractGrpcInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("io.grpc.internal.AbstractServerImplBuilder");
}
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".GrpcServerTracer",
packageName + ".GrpcExtractAdapter",
packageName + ".TracingServerInterceptor",
packageName + ".TracingServerInterceptor$TracingServerCall",
packageName + ".TracingServerInterceptor$TracingServerCallListener",
"io.opentelemetry.instrumentation.auto.grpc.common.GrpcHelper",
};
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
@ -63,7 +48,7 @@ public class GrpcServerBuilderInstrumentation extends Instrumenter.Default {
}
}
if (shouldRegister) {
interceptors.add(0, TracingServerInterceptor.INSTANCE);
interceptors.add(0, TracingServerInterceptor.newInterceptor());
}
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.v1_5
import io.grpc.ManagedChannelBuilder
import io.grpc.ServerBuilder
import io.opentelemetry.auto.test.AgentTestTrait
import io.opentelemetry.instrumentation.grpc.v1_5.AbstractGrpcStreamingTest
class GrpcStreamingTest extends AbstractGrpcStreamingTest implements AgentTestTrait {
@Override
ServerBuilder configureServer(ServerBuilder server) {
return server
}
@Override
ManagedChannelBuilder configureClient(ManagedChannelBuilder client) {
return client
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.v1_5
import io.grpc.ManagedChannelBuilder
import io.grpc.ServerBuilder
import io.opentelemetry.auto.test.AgentTestTrait
import io.opentelemetry.instrumentation.grpc.v1_5.AbstractGrpcTest
class GrpcTest extends AbstractGrpcTest implements AgentTestTrait {
@Override
ServerBuilder configureServer(ServerBuilder server) {
return server
}
@Override
ManagedChannelBuilder configureClient(ManagedChannelBuilder client) {
return client
}
}

View File

@ -1,54 +0,0 @@
apply from: "$rootDir/gradle/instrumentation.gradle"
apply plugin: 'com.google.protobuf'
apply plugin: 'idea'
muzzle {
pass {
group = "io.grpc"
module = "grpc-core"
versions = "[1.5.0,)"
}
}
buildscript {
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12'
}
}
def grpcVersion = '1.5.0'
protobuf {
protoc {
// Download compiler rather than using locally installed version:
artifact = 'com.google.protobuf:protoc:3.3.0'
}
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
}
generateProtoTasks {
all()*.plugins { grpc {} }
}
}
dependencies {
library group: 'io.grpc', name: 'grpc-core', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-netty', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-stub', version: grpcVersion
testImplementation group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
// this instrumentation needs to be able to be able to reference the OpenTelemetry API's gRPC Context
// that is shaded in the bootstrap class loader (for sending telemetry to the agent),
// separately from the gRPC Context that is brought by gRPC
compileOnly project(path: ':opentelemetry-api-beta-shaded-for-instrumenting', configuration: 'shadow')
testImplementation project(path: ':opentelemetry-api-beta-shaded-for-instrumenting', configuration: 'shadow')
}

View File

@ -0,0 +1,13 @@
apply from: "$rootDir/gradle/instrumentation-library.gradle"
def grpcVersion = '1.5.0'
dependencies {
library group: 'io.grpc', name: 'grpc-core', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-netty', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion
testLibrary group: 'io.grpc', name: 'grpc-stub', version: grpcVersion
testImplementation project(':instrumentation:grpc-1.5:testing')
}

View File

@ -3,19 +3,25 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.client;
package io.opentelemetry.instrumentation.grpc.v1_5.client;
import static io.opentelemetry.trace.Span.Kind.CLIENT;
import io.grpc.Status;
import io.opentelemetry.instrumentation.api.tracer.RpcClientTracer;
import io.opentelemetry.instrumentation.auto.grpc.common.GrpcHelper;
import io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Span.Builder;
import io.opentelemetry.trace.Tracer;
import io.opentelemetry.trace.attributes.SemanticAttributes;
public class GrpcClientTracer extends RpcClientTracer {
public static final GrpcClientTracer TRACER = new GrpcClientTracer();
protected GrpcClientTracer() {}
protected GrpcClientTracer(Tracer tracer) {
super(tracer);
}
public Span startSpan(String name) {
Builder spanBuilder = tracer.spanBuilder(name).setSpanKind(CLIENT);

View File

@ -3,14 +3,14 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.client;
package io.opentelemetry.instrumentation.grpc.v1_5.client;
import io.grpc.Metadata;
import io.opentelemetry.context.propagation.TextMapPropagator;
public final class GrpcInjectAdapter implements TextMapPropagator.Setter<Metadata> {
final class GrpcInjectAdapter implements TextMapPropagator.Setter<Metadata> {
public static final GrpcInjectAdapter SETTER = new GrpcInjectAdapter();
static final GrpcInjectAdapter SETTER = new GrpcInjectAdapter();
@Override
public void set(Metadata carrier, String key, String value) {

View File

@ -3,84 +3,106 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.client;
package io.opentelemetry.instrumentation.grpc.v1_5.client;
import static io.opentelemetry.context.ContextUtils.withScopedContext;
import static io.opentelemetry.instrumentation.auto.grpc.client.GrpcClientTracer.TRACER;
import static io.opentelemetry.instrumentation.auto.grpc.client.GrpcInjectAdapter.SETTER;
import static io.opentelemetry.trace.TracingContextUtils.getSpan;
import static io.opentelemetry.instrumentation.grpc.v1_5.client.GrpcInjectAdapter.SETTER;
import static io.opentelemetry.trace.TracingContextUtils.withSpan;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientCall.Listener;
import io.grpc.ClientInterceptor;
import io.grpc.Context;
import io.grpc.ForwardingClientCall;
import io.grpc.ForwardingClientCallListener;
import io.grpc.Grpc;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.Status;
import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.common.Attributes;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.auto.grpc.common.GrpcHelper;
import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils;
import io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Tracer;
import io.opentelemetry.trace.attributes.SemanticAttributes;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.atomic.AtomicLong;
public class TracingClientInterceptor implements ClientInterceptor {
private final InetSocketAddress peerAddress;
public TracingClientInterceptor(InetSocketAddress peerAddress) {
this.peerAddress = peerAddress;
public static ClientInterceptor newInterceptor() {
return newInterceptor(new GrpcClientTracer());
}
public static ClientInterceptor newInterceptor(Tracer tracer) {
return newInterceptor(new GrpcClientTracer(tracer));
}
public static ClientInterceptor newInterceptor(GrpcClientTracer tracer) {
return new TracingClientInterceptor(tracer);
}
private final GrpcClientTracer tracer;
private TracingClientInterceptor(GrpcClientTracer tracer) {
this.tracer = tracer;
}
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
String methodName = method.getFullMethodName();
Span span = TRACER.startSpan(methodName);
Span span = tracer.startSpan(methodName);
GrpcHelper.prepareSpan(span, methodName);
Context context = withSpan(span, Context.current());
final ClientCall<ReqT, RespT> result;
try (Scope ignored = withScopedContext(context)) {
GrpcHelper.prepareSpan(span, methodName, peerAddress, false);
ClientCall<ReqT, RespT> result;
try {
// call other interceptors
result = next.newCall(method, callOptions);
} catch (Throwable e) {
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
return new TracingClientCall<>(context, result);
}
SocketAddress address = result.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
if (address instanceof InetSocketAddress) {
InetSocketAddress inetSocketAddress = (InetSocketAddress) address;
NetPeerUtils.setNetPeer(span, inetSocketAddress);
}
return new TracingClientCall<>(result, span, context, tracer);
}
static final class TracingClientCall<ReqT, RespT>
extends ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT> {
final Context context;
TracingClientCall(Context context, ClientCall<ReqT, RespT> delegate) {
private final Span span;
private final Context context;
private final GrpcClientTracer tracer;
TracingClientCall(
ClientCall<ReqT, RespT> delegate, Span span, Context context, GrpcClientTracer tracer) {
super(delegate);
this.span = span;
this.context = context;
this.tracer = tracer;
}
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
// this reference to io.grpc.Context will be shaded during the build
// see instrumentation.gradle: "relocate OpenTelemetry API dependency usage"
// (luckily the grpc instrumentation doesn't need to reference unshaded grpc Context, so we
// don't need to worry about distinguishing them like in the opentelemetry-api
// instrumentation)
OpenTelemetry.getPropagators().getTextMapPropagator().inject(context, headers, SETTER);
try (Scope ignored = withScopedContext(context)) {
super.start(new TracingClientCallListener<>(context, responseListener), headers);
super.start(
new TracingClientCallListener<>(responseListener, span, context, tracer), headers);
} catch (Throwable e) {
Span span = getSpan(context);
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
}
@ -90,8 +112,7 @@ public class TracingClientInterceptor implements ClientInterceptor {
try (Scope ignored = withScopedContext(context)) {
super.sendMessage(message);
} catch (Throwable e) {
Span span = getSpan(context);
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
}
@ -99,17 +120,22 @@ public class TracingClientInterceptor implements ClientInterceptor {
static final class TracingClientCallListener<RespT>
extends ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT> {
private final Span span;
private final Context context;
private final GrpcClientTracer tracer;
private final AtomicLong messageId = new AtomicLong();
TracingClientCallListener(Context context, ClientCall.Listener<RespT> delegate) {
TracingClientCallListener(
Listener<RespT> delegate, Span span, Context context, GrpcClientTracer tracer) {
super(delegate);
this.span = span;
this.context = context;
this.tracer = tracer;
}
@Override
public void onMessage(RespT message) {
Span span = getSpan(context);
Attributes attributes =
Attributes.of(
SemanticAttributes.GRPC_MESSAGE_TYPE,
@ -119,19 +145,20 @@ public class TracingClientInterceptor implements ClientInterceptor {
span.addEvent("message", attributes);
try (Scope ignored = withScopedContext(context)) {
delegate().onMessage(message);
} catch (Throwable e) {
tracer.addThrowable(span, e);
}
}
@Override
public void onClose(Status status, Metadata trailers) {
Span span = getSpan(context);
try (Scope ignored = withScopedContext(context)) {
delegate().onClose(status, trailers);
} catch (Throwable e) {
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
TRACER.endSpan(span, status);
tracer.endSpan(span, status);
}
@Override
@ -139,8 +166,7 @@ public class TracingClientInterceptor implements ClientInterceptor {
try (Scope ignored = withScopedContext(context)) {
delegate().onReady();
} catch (Throwable e) {
Span span = getSpan(context);
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.grpc.v1_5.common;
import io.grpc.Status.Code;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.StatusCanonicalCode;
import io.opentelemetry.trace.attributes.SemanticAttributes;
public final class GrpcHelper {
public static void prepareSpan(Span span, String fullMethodName) {
int slash = fullMethodName.indexOf('/');
String serviceName = slash == -1 ? fullMethodName : fullMethodName.substring(0, slash);
String methodName = slash == -1 ? null : fullMethodName.substring(slash + 1);
span.setAttribute(SemanticAttributes.RPC_SERVICE, serviceName);
span.setAttribute(SemanticAttributes.RPC_METHOD, methodName);
}
public static StatusCanonicalCode statusFromGrpcStatus(io.grpc.Status grpcStatus) {
return codeFromGrpcCode(grpcStatus.getCode());
}
private static StatusCanonicalCode codeFromGrpcCode(Code grpcCode) {
return grpcCode.equals(Code.OK) ? StatusCanonicalCode.UNSET : StatusCanonicalCode.ERROR;
}
private GrpcHelper() {}
}

View File

@ -3,14 +3,14 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.server;
package io.opentelemetry.instrumentation.grpc.v1_5.server;
import io.grpc.Metadata;
import io.opentelemetry.context.propagation.TextMapPropagator;
public final class GrpcExtractAdapter implements TextMapPropagator.Getter<Metadata> {
final class GrpcExtractAdapter implements TextMapPropagator.Getter<Metadata> {
public static final GrpcExtractAdapter GETTER = new GrpcExtractAdapter();
static final GrpcExtractAdapter GETTER = new GrpcExtractAdapter();
@Override
public String get(Metadata carrier, String key) {

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.server;
package io.opentelemetry.instrumentation.grpc.v1_5.server;
import static io.opentelemetry.trace.Span.Kind.SERVER;
@ -11,13 +11,19 @@ import io.grpc.Metadata;
import io.grpc.Status;
import io.opentelemetry.context.propagation.TextMapPropagator.Getter;
import io.opentelemetry.instrumentation.api.tracer.RpcServerTracer;
import io.opentelemetry.instrumentation.auto.grpc.common.GrpcHelper;
import io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Span.Builder;
import io.opentelemetry.trace.Tracer;
import io.opentelemetry.trace.attributes.SemanticAttributes;
public class GrpcServerTracer extends RpcServerTracer<Metadata> {
public static final GrpcServerTracer TRACER = new GrpcServerTracer();
GrpcServerTracer() {}
GrpcServerTracer(Tracer tracer) {
super(tracer);
}
public Span startSpan(String name, Metadata headers) {
Builder spanBuilder =

View File

@ -3,9 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.server;
package io.opentelemetry.instrumentation.grpc.v1_5.server;
import static io.opentelemetry.instrumentation.auto.grpc.server.GrpcServerTracer.TRACER;
import static io.opentelemetry.trace.TracingContextUtils.currentContextWith;
import io.grpc.ForwardingServerCall;
@ -13,13 +12,15 @@ import io.grpc.ForwardingServerCallListener;
import io.grpc.Grpc;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCall.Listener;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import io.grpc.Status;
import io.opentelemetry.common.Attributes;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.auto.grpc.common.GrpcHelper;
import io.opentelemetry.instrumentation.grpc.v1_5.common.GrpcHelper;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Tracer;
import io.opentelemetry.trace.attributes.SemanticAttributes;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
@ -27,20 +28,39 @@ import java.util.concurrent.atomic.AtomicLong;
public class TracingServerInterceptor implements ServerInterceptor {
public static final TracingServerInterceptor INSTANCE = new TracingServerInterceptor();
public static ServerInterceptor newInterceptor() {
return newInterceptor(new GrpcServerTracer());
}
private TracingServerInterceptor() {}
public static ServerInterceptor newInterceptor(Tracer tracer) {
return newInterceptor(new GrpcServerTracer(tracer));
}
public static ServerInterceptor newInterceptor(GrpcServerTracer tracer) {
return new TracingServerInterceptor(tracer);
}
private final GrpcServerTracer tracer;
private TracingServerInterceptor(GrpcServerTracer tracer) {
this.tracer = tracer;
}
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
String methodName = call.getMethodDescriptor().getFullMethodName();
Span span = TRACER.startSpan(methodName, headers);
Span span = tracer.startSpan(methodName, headers);
SocketAddress addr = call.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
InetSocketAddress iAddr = addr instanceof InetSocketAddress ? (InetSocketAddress) addr : null;
GrpcHelper.prepareSpan(span, methodName, iAddr, true);
SocketAddress address = call.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
if (address instanceof InetSocketAddress) {
InetSocketAddress inetSocketAddress = (InetSocketAddress) address;
span.setAttribute(SemanticAttributes.NET_PEER_PORT, inetSocketAddress.getPort());
span.setAttribute(
SemanticAttributes.NET_PEER_IP, inetSocketAddress.getAddress().getHostAddress());
}
GrpcHelper.prepareSpan(span, methodName);
ServerCall.Listener<ReqT> result;
try (Scope ignored = currentContextWith(span)) {
@ -48,36 +68,39 @@ public class TracingServerInterceptor implements ServerInterceptor {
try {
// Wrap the server call so that we can decorate the span
// with the resulting status
TracingServerCall<ReqT, RespT> tracingServerCall = new TracingServerCall<>(span, call);
TracingServerCall<ReqT, RespT> tracingServerCall =
new TracingServerCall<>(call, span, tracer);
// call other interceptors
result = next.startCall(tracingServerCall, headers);
} catch (Throwable e) {
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
}
// This ensures the server implementation can see the span in scope
return new TracingServerCallListener<>(span, result);
return new TracingServerCallListener<>(result, span, tracer);
}
static final class TracingServerCall<ReqT, RespT>
extends ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT> {
final Span span;
private final Span span;
private final GrpcServerTracer tracer;
TracingServerCall(Span span, ServerCall<ReqT, RespT> delegate) {
TracingServerCall(ServerCall<ReqT, RespT> delegate, Span span, GrpcServerTracer tracer) {
super(delegate);
this.span = span;
this.tracer = tracer;
}
@Override
public void close(Status status, Metadata trailers) {
TRACER.setStatus(span, status);
tracer.setStatus(span, status);
try (Scope ignored = currentContextWith(span)) {
delegate().close(status, trailers);
} catch (Throwable e) {
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
}
@ -86,11 +109,14 @@ public class TracingServerInterceptor implements ServerInterceptor {
static final class TracingServerCallListener<ReqT>
extends ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT> {
private final Span span;
private final GrpcServerTracer tracer;
private final AtomicLong messageId = new AtomicLong();
TracingServerCallListener(Span span, ServerCall.Listener<ReqT> delegate) {
TracingServerCallListener(Listener<ReqT> delegate, Span span, GrpcServerTracer tracer) {
super(delegate);
this.span = span;
this.tracer = tracer;
}
@Override
@ -112,7 +138,7 @@ public class TracingServerInterceptor implements ServerInterceptor {
try (Scope ignored = currentContextWith(span)) {
delegate().onHalfClose();
} catch (Throwable e) {
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
}
@ -123,10 +149,10 @@ public class TracingServerInterceptor implements ServerInterceptor {
delegate().onCancel();
span.setAttribute("canceled", true);
} catch (Throwable e) {
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
TRACER.end(span);
tracer.end(span);
}
@Override
@ -134,10 +160,10 @@ public class TracingServerInterceptor implements ServerInterceptor {
try (Scope ignored = currentContextWith(span)) {
delegate().onComplete();
} catch (Throwable e) {
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
TRACER.end(span);
tracer.end(span);
}
@Override
@ -145,7 +171,7 @@ public class TracingServerInterceptor implements ServerInterceptor {
try (Scope ignored = currentContextWith(span)) {
delegate().onReady();
} catch (Throwable e) {
TRACER.endExceptionally(span, e);
tracer.endExceptionally(span, e);
throw e;
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.grpc.v1_5
import io.grpc.ManagedChannelBuilder
import io.grpc.ServerBuilder
import io.opentelemetry.auto.test.InstrumentationTestTrait
import io.opentelemetry.instrumentation.grpc.v1_5.client.TracingClientInterceptor
import io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor
class GrpcStreamingTest extends AbstractGrpcStreamingTest implements InstrumentationTestTrait {
@Override
ServerBuilder configureServer(ServerBuilder server) {
return server.intercept(TracingServerInterceptor.newInterceptor())
}
@Override
ManagedChannelBuilder configureClient(ManagedChannelBuilder client) {
return client.intercept(TracingClientInterceptor.newInterceptor())
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.grpc.v1_5
import io.grpc.ManagedChannelBuilder
import io.grpc.ServerBuilder
import io.opentelemetry.auto.test.InstrumentationTestTrait
import io.opentelemetry.instrumentation.grpc.v1_5.client.TracingClientInterceptor
import io.opentelemetry.instrumentation.grpc.v1_5.server.TracingServerInterceptor
class GrpcTest extends AbstractGrpcTest implements InstrumentationTestTrait {
@Override
ServerBuilder configureServer(ServerBuilder server) {
return server.intercept(TracingServerInterceptor.newInterceptor())
}
@Override
ManagedChannelBuilder configureClient(ManagedChannelBuilder client) {
return client.intercept(TracingClientInterceptor.newInterceptor())
}
}

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.common
package io.opentelemetry.instrumentation.grpc.v1_5.common
import io.grpc.Status
import io.opentelemetry.trace.StatusCanonicalCode

View File

@ -1,36 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.client;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.Map;
abstract class AbstractGrpcClientInstrumentation extends Instrumenter.Default {
public AbstractGrpcClientInstrumentation() {
super("grpc", "grpc-client");
}
@Override
public String[] helperClassNames() {
return new String[] {
packageName + ".GrpcClientTracer",
packageName + ".GrpcInjectAdapter",
packageName + ".TracingClientInterceptor",
packageName + ".TracingClientInterceptor$TracingClientCall",
packageName + ".TracingClientInterceptor$TracingClientCallListener",
"io.opentelemetry.instrumentation.auto.grpc.common.GrpcHelper",
};
}
@Override
public Map<String, String> contextStore() {
return Collections.singletonMap(
"io.grpc.ManagedChannelBuilder", InetSocketAddress.class.getName());
}
}

View File

@ -1,52 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.client;
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
import io.grpc.ManagedChannelBuilder;
import io.opentelemetry.instrumentation.auto.api.ContextStore;
import io.opentelemetry.instrumentation.auto.api.InstrumentationContext;
import io.opentelemetry.javaagent.tooling.Instrumenter;
import java.net.InetSocketAddress;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
@AutoService(Instrumenter.class)
public class GrpcClientBuilderForAddressInstrumentation extends AbstractGrpcClientInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return extendsClass(named("io.grpc.ManagedChannelBuilder"));
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
isMethod().and(named("forAddress").and(ElementMatchers.takesArguments(2))),
GrpcClientBuilderForAddressInstrumentation.class.getName() + "$ForAddressAdvice");
}
public static class ForAddressAdvice {
@Advice.OnMethodExit(suppress = Throwable.class)
public static final void forAddress(
@Advice.Argument(0) String address,
@Advice.Argument(1) int port,
@Advice.Return ManagedChannelBuilder builder) {
ContextStore<ManagedChannelBuilder, InetSocketAddress> contextStore =
InstrumentationContext.get(ManagedChannelBuilder.class, InetSocketAddress.class);
contextStore.put(builder, InetSocketAddress.createUnresolved(address, port));
}
}
}

View File

@ -1,80 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.auto.grpc.common;
import io.grpc.Status.Code;
import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.StatusCanonicalCode;
import io.opentelemetry.trace.attributes.SemanticAttributes;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
public final class GrpcHelper {
private static final Map<Code, StatusCanonicalCode> CODE_MAP;
static {
EnumMap<Code, StatusCanonicalCode> codeMap = new EnumMap<>(Code.class);
codeMap.put(Code.CANCELLED, StatusCanonicalCode.ERROR);
codeMap.put(Code.INVALID_ARGUMENT, StatusCanonicalCode.ERROR);
codeMap.put(Code.DEADLINE_EXCEEDED, StatusCanonicalCode.ERROR);
codeMap.put(Code.NOT_FOUND, StatusCanonicalCode.ERROR);
codeMap.put(Code.ALREADY_EXISTS, StatusCanonicalCode.ERROR);
codeMap.put(Code.PERMISSION_DENIED, StatusCanonicalCode.ERROR);
codeMap.put(Code.RESOURCE_EXHAUSTED, StatusCanonicalCode.ERROR);
codeMap.put(Code.FAILED_PRECONDITION, StatusCanonicalCode.ERROR);
codeMap.put(Code.ABORTED, StatusCanonicalCode.ERROR);
codeMap.put(Code.OUT_OF_RANGE, StatusCanonicalCode.ERROR);
codeMap.put(Code.UNIMPLEMENTED, StatusCanonicalCode.ERROR);
codeMap.put(Code.INTERNAL, StatusCanonicalCode.ERROR);
codeMap.put(Code.UNAVAILABLE, StatusCanonicalCode.ERROR);
codeMap.put(Code.DATA_LOSS, StatusCanonicalCode.ERROR);
codeMap.put(Code.UNAUTHENTICATED, StatusCanonicalCode.ERROR);
codeMap.put(Code.UNKNOWN, StatusCanonicalCode.ERROR);
CODE_MAP = Collections.unmodifiableMap(codeMap);
}
public static void prepareSpan(
Span span, String fullMethodName, InetSocketAddress peerAddress, boolean server) {
int slash = fullMethodName.indexOf('/');
String serviceName = slash == -1 ? fullMethodName : fullMethodName.substring(0, slash);
String methodName = slash == -1 ? null : fullMethodName.substring(slash + 1);
span.setAttribute(SemanticAttributes.RPC_SERVICE, serviceName);
if (methodName != null) {
span.setAttribute(SemanticAttributes.RPC_METHOD, methodName);
}
if (peerAddress != null) {
span.setAttribute(SemanticAttributes.NET_PEER_PORT, (long) peerAddress.getPort());
if (server) {
span.setAttribute(
SemanticAttributes.NET_PEER_IP, peerAddress.getAddress().getHostAddress());
} else {
NetPeerUtils.setNetPeer(span, peerAddress.getHostName(), null);
}
} else {
// The spec says these fields must be populated, so put some values in even if we don't have
// an address recorded.
span.setAttribute(SemanticAttributes.NET_PEER_PORT, 0L);
NetPeerUtils.setNetPeer(span, "(unknown)", null);
}
}
public static StatusCanonicalCode statusFromGrpcStatus(io.grpc.Status grpcStatus) {
return codeFromGrpcCode(grpcStatus.getCode());
}
private static StatusCanonicalCode codeFromGrpcCode(Code grpcCode) {
StatusCanonicalCode code = CODE_MAP.get(grpcCode);
return code != null ? code : StatusCanonicalCode.UNSET;
}
private GrpcHelper() {}
}

View File

@ -0,0 +1,37 @@
plugins {
id "java-library"
id "com.google.protobuf" version "0.8.13"
}
apply from: "$rootDir/gradle/java.gradle"
def grpcVersion = '1.5.0'
protobuf {
protoc {
// Download compiler rather than using locally installed version:
artifact = 'com.google.protobuf:protoc:3.3.0'
}
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
}
generateProtoTasks {
all()*.plugins { grpc {} }
}
}
dependencies {
api project(':testing-common')
api group: 'io.grpc', name: 'grpc-core', version: grpcVersion
api group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion
api group: 'io.grpc', name: 'grpc-stub', version: grpcVersion
implementation group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
implementation deps.guava
implementation deps.groovy
implementation deps.opentelemetryApi
implementation deps.spock
}

View File

@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.grpc.v1_5
import static io.opentelemetry.trace.Span.Kind.CLIENT
import static io.opentelemetry.trace.Span.Kind.SERVER
@ -14,16 +16,22 @@ import io.grpc.ManagedChannelBuilder
import io.grpc.Server
import io.grpc.ServerBuilder
import io.grpc.stub.StreamObserver
import io.opentelemetry.auto.test.AgentTestRunner
import io.opentelemetry.auto.test.InstrumentationSpecification
import io.opentelemetry.auto.test.utils.PortUtils
import io.opentelemetry.trace.attributes.SemanticAttributes
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
import spock.lang.Unroll
class GrpcStreamingTest extends AgentTestRunner {
@Unroll
abstract class AbstractGrpcStreamingTest extends InstrumentationSpecification {
def "test conversation #name"() {
abstract ServerBuilder configureServer(ServerBuilder server)
abstract ManagedChannelBuilder configureClient(ManagedChannelBuilder client)
def "test conversation #paramName"() {
setup:
def msgCount = serverMessageCount
def serverReceived = new CopyOnWriteArrayList<>()
@ -58,8 +66,8 @@ class GrpcStreamingTest extends AgentTestRunner {
}
}
def port = PortUtils.randomOpenPort()
Server server = ServerBuilder.forPort(port).addService(greeter).build().start()
ManagedChannelBuilder channelBuilder = ManagedChannelBuilder.forAddress("localhost", port)
Server server = configureServer(ServerBuilder.forPort(port).addService(greeter)).build().start()
ManagedChannelBuilder channelBuilder = configureClient(ManagedChannelBuilder.forAddress("localhost", port))
// Depending on the version of gRPC usePlainText may or may not take an argument.
try {
@ -94,12 +102,6 @@ class GrpcStreamingTest extends AgentTestRunner {
observer.onCompleted()
then:
error.get() == null
TEST_WRITER.waitForTraces(1)
error.get() == null
serverReceived == clientRange.collect { "call $it" }
clientReceived == serverRange.collect { clientRange.collect { "call $it" } }.flatten().sort()
assertTraces(1) {
trace(0, 2) {
span(0) {
@ -111,8 +113,6 @@ class GrpcStreamingTest extends AgentTestRunner {
"${SemanticAttributes.RPC_SYSTEM.key()}" "grpc"
"${SemanticAttributes.RPC_SERVICE.key()}" "example.Greeter"
"${SemanticAttributes.RPC_METHOD.key()}" "Conversation"
"${SemanticAttributes.NET_PEER_NAME.key()}" "localhost"
"${SemanticAttributes.NET_PEER_PORT.key()}" port
}
(1..(clientMessageCount * serverMessageCount)).each {
def messageId = it
@ -150,6 +150,9 @@ class GrpcStreamingTest extends AgentTestRunner {
}
}
}
error.get() == null
serverReceived == clientRange.collect { "call $it" }
clientReceived == serverRange.collect { clientRange.collect { "call $it" } }.flatten().sort()
cleanup:
channel?.shutdownNow()?.awaitTermination(10, TimeUnit.SECONDS)

View File

@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.grpc.v1_5
import static io.opentelemetry.auto.test.utils.TraceUtils.basicSpan
import static io.opentelemetry.auto.test.utils.TraceUtils.runUnderTrace
import static io.opentelemetry.trace.Span.Kind.CLIENT
@ -18,15 +20,21 @@ import io.grpc.ServerBuilder
import io.grpc.Status
import io.grpc.StatusRuntimeException
import io.grpc.stub.StreamObserver
import io.opentelemetry.auto.test.AgentTestRunner
import io.opentelemetry.auto.test.InstrumentationSpecification
import io.opentelemetry.auto.test.utils.PortUtils
import io.opentelemetry.instrumentation.auto.grpc.common.GrpcHelper
import io.opentelemetry.trace.StatusCanonicalCode
import io.opentelemetry.trace.attributes.SemanticAttributes
import java.util.concurrent.TimeUnit
import spock.lang.Unroll
class GrpcTest extends AgentTestRunner {
@Unroll
abstract class AbstractGrpcTest extends InstrumentationSpecification {
def "test request-response"() {
abstract ServerBuilder configureServer(ServerBuilder server)
abstract ManagedChannelBuilder configureClient(ManagedChannelBuilder client)
def "test request-response #paramName"() {
setup:
BindableService greeter = new GreeterGrpc.GreeterImplBase() {
@Override
@ -38,8 +46,8 @@ class GrpcTest extends AgentTestRunner {
}
}
def port = PortUtils.randomOpenPort()
Server server = ServerBuilder.forPort(port).addService(greeter).build().start()
ManagedChannelBuilder channelBuilder = ManagedChannelBuilder.forAddress("localhost", port)
Server server = configureServer(ServerBuilder.forPort(port).addService(greeter)).build().start()
ManagedChannelBuilder channelBuilder = configureClient(ManagedChannelBuilder.forAddress("localhost", port))
// Depending on the version of gRPC usePlainText may or may not take an argument.
try {
@ -77,8 +85,6 @@ class GrpcTest extends AgentTestRunner {
"${SemanticAttributes.RPC_SYSTEM.key()}" "grpc"
"${SemanticAttributes.RPC_SERVICE.key()}" "example.Greeter"
"${SemanticAttributes.RPC_METHOD.key()}" "SayHello"
"${SemanticAttributes.NET_PEER_NAME.key()}" "localhost"
"${SemanticAttributes.NET_PEER_PORT.key()}" port
}
}
span(2) {
@ -112,7 +118,7 @@ class GrpcTest extends AgentTestRunner {
paramName << ["some name", "some other name"]
}
def "test error - #name"() {
def "test error - #paramName"() {
setup:
def error = grpcStatus.asException()
BindableService greeter = new GreeterGrpc.GreeterImplBase() {
@ -123,8 +129,8 @@ class GrpcTest extends AgentTestRunner {
}
}
def port = PortUtils.randomOpenPort()
Server server = ServerBuilder.forPort(port).addService(greeter).build().start()
ManagedChannelBuilder channelBuilder = ManagedChannelBuilder.forAddress("localhost", port)
Server server = configureServer(ServerBuilder.forPort(port).addService(greeter)).build().start()
ManagedChannelBuilder channelBuilder = configureClient(ManagedChannelBuilder.forAddress("localhost", port))
// Depending on the version of gRPC usePlainText may or may not take an argument.
try {
@ -148,13 +154,11 @@ class GrpcTest extends AgentTestRunner {
kind CLIENT
hasNoParent()
errored true
status(GrpcHelper.statusFromGrpcStatus(grpcStatus))
status(StatusCanonicalCode.ERROR)
attributes {
"${SemanticAttributes.RPC_SYSTEM.key()}" "grpc"
"${SemanticAttributes.RPC_SERVICE.key()}" "example.Greeter"
"${SemanticAttributes.RPC_METHOD.key()}" "SayHello"
"${SemanticAttributes.NET_PEER_NAME.key()}" "localhost"
"${SemanticAttributes.NET_PEER_PORT.key()}" port
}
}
span(1) {
@ -162,7 +166,7 @@ class GrpcTest extends AgentTestRunner {
kind SERVER
childOf span(0)
errored true
status(GrpcHelper.statusFromGrpcStatus(grpcStatus))
status(StatusCanonicalCode.ERROR)
event(0) {
eventName "message"
attributes {
@ -198,7 +202,7 @@ class GrpcTest extends AgentTestRunner {
"StatusRuntime - description" | Status.UNIMPLEMENTED.withDescription("some description")
}
def "test error thrown - #name"() {
def "test error thrown - #paramName"() {
setup:
def error = grpcStatus.asRuntimeException()
BindableService greeter = new GreeterGrpc.GreeterImplBase() {
@ -209,8 +213,8 @@ class GrpcTest extends AgentTestRunner {
}
}
def port = PortUtils.randomOpenPort()
Server server = ServerBuilder.forPort(port).addService(greeter).build().start()
ManagedChannelBuilder channelBuilder = ManagedChannelBuilder.forAddress("localhost", port)
Server server = configureServer(ServerBuilder.forPort(port).addService(greeter)).build().start()
ManagedChannelBuilder channelBuilder = configureClient(ManagedChannelBuilder.forAddress("localhost", port))
// Depending on the version of gRPC usePlainText may or may not take an argument.
try {
@ -240,8 +244,6 @@ class GrpcTest extends AgentTestRunner {
"${SemanticAttributes.RPC_SYSTEM.key()}" "grpc"
"${SemanticAttributes.RPC_SERVICE.key()}" "example.Greeter"
"${SemanticAttributes.RPC_METHOD.key()}" "SayHello"
"${SemanticAttributes.NET_PEER_NAME.key()}" "localhost"
"${SemanticAttributes.NET_PEER_PORT.key()}" Long
}
}
span(1) {
@ -249,7 +251,7 @@ class GrpcTest extends AgentTestRunner {
kind SERVER
childOf span(0)
errored true
status(GrpcHelper.statusFromGrpcStatus(grpcStatus))
status(StatusCanonicalCode.ERROR)
event(0) {
eventName "message"
attributes {

View File

@ -88,7 +88,9 @@ include ':instrumentation:geode-1.4'
include ':instrumentation:google-http-client-1.19'
include ':instrumentation:grizzly-2.0'
include ':instrumentation:grizzly-client-1.9'
include ':instrumentation:grpc-1.5'
include ':instrumentation:grpc-1.5:auto'
include ':instrumentation:grpc-1.5:library'
include ':instrumentation:grpc-1.5:testing'
include ':instrumentation:guava-10.0'
include ':instrumentation:hibernate:hibernate-3.3'
include ':instrumentation:hibernate:hibernate-4.0'