Map gRPC status to OTel status.
MODIFY
instrumentation/grpc-1.5/src/main/java/io/opentelemetry/auto/instrumentation/grpc/client/GrpcClientDecorator.java
instrumentation/grpc-1.5/src/main/java/io/opentelemetry/auto/instrumentation/grpc/client/GrpcClientDecorator.java
@@ -18,8 +18,8 @@ package io.opentelemetry.auto.instrumentation.grpc.client;
import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.auto.bootstrap.instrumentation.decorator.ClientDecorator;
+import io.opentelemetry.auto.instrumentation.grpc.common.GrpcHelper;
import io.opentelemetry.trace.Span;
-import io.opentelemetry.trace.Status;
import io.opentelemetry.trace.Tracer;
public class GrpcClientDecorator extends ClientDecorator {
@@ -33,9 +33,7 @@ public class GrpcClientDecorator extends ClientDecorator {
span.setAttribute("status.description", status.getDescription());
onError(span, status.getCause());
- if (!status.isOk()) {
- span.setStatus(Status.UNKNOWN);
- }
+ span.setStatus(GrpcHelper.statusFromGrpcStatus(status));
return span;
}
}

MODIFY
instrumentation/grpc-1.5/src/main/java/io/opentelemetry/auto/instrumentation/grpc/common/GrpcHelper.java
instrumentation/grpc-1.5/src/main/java/io/opentelemetry/auto/instrumentation/grpc/common/GrpcHelper.java
package io.opentelemetry.auto.instrumentation.grpc.common;
+import io.grpc.Status.Code;
import io.opentelemetry.auto.instrumentation.api.MoreTags;
import io.opentelemetry.trace.Span;
+import io.opentelemetry.trace.Status;
+import io.opentelemetry.trace.Status.CanonicalCode;
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, CanonicalCode> CODE_MAP;
+
+ static {
+ EnumMap<Code, CanonicalCode> codeMap = new EnumMap<>(Code.class);
+ codeMap.put(Code.OK, CanonicalCode.OK);
+ codeMap.put(Code.CANCELLED, CanonicalCode.CANCELLED);
+ codeMap.put(Code.INVALID_ARGUMENT, CanonicalCode.INVALID_ARGUMENT);
+ codeMap.put(Code.DEADLINE_EXCEEDED, CanonicalCode.DEADLINE_EXCEEDED);
+ codeMap.put(Code.NOT_FOUND, CanonicalCode.NOT_FOUND);
+ codeMap.put(Code.ALREADY_EXISTS, CanonicalCode.ALREADY_EXISTS);
+ codeMap.put(Code.PERMISSION_DENIED, CanonicalCode.PERMISSION_DENIED);
+ codeMap.put(Code.RESOURCE_EXHAUSTED, CanonicalCode.RESOURCE_EXHAUSTED);
+ codeMap.put(Code.FAILED_PRECONDITION, CanonicalCode.FAILED_PRECONDITION);
+ codeMap.put(Code.ABORTED, CanonicalCode.ABORTED);
+ codeMap.put(Code.OUT_OF_RANGE, CanonicalCode.OUT_OF_RANGE);
+ codeMap.put(Code.UNIMPLEMENTED, CanonicalCode.UNIMPLEMENTED);
+ codeMap.put(Code.INTERNAL, CanonicalCode.INTERNAL);
+ codeMap.put(Code.UNAVAILABLE, CanonicalCode.UNAVAILABLE);
+ codeMap.put(Code.DATA_LOSS, CanonicalCode.DATA_LOSS);
+ codeMap.put(Code.UNAUTHENTICATED, CanonicalCode.UNAUTHENTICATED);
+ codeMap.put(Code.UNKNOWN, CanonicalCode.UNKNOWN);
+ CODE_MAP = Collections.unmodifiableMap(codeMap);
+ }
-public class GrpcHelper {
public static void prepareSpan(
final Span span,
final String methodName,
@@ -51,4 +81,19 @@ public class GrpcHelper {
span.setAttribute(MoreTags.NET_PEER_NAME, "(unknown)");
}
}
+
+ public static Status statusFromGrpcStatus(io.grpc.Status grpcStatus) {
+ Status status = codeFromGrpcCode(grpcStatus.getCode()).toStatus();
+ if (grpcStatus.getDescription() != null) {
+ status = status.withDescription(grpcStatus.getDescription());
+ }
+ return status;
+ }
+
+ private static CanonicalCode codeFromGrpcCode(Code grpcCode) {
+ CanonicalCode code = CODE_MAP.get(grpcCode);
+ return code != null ? code : CanonicalCode.UNKNOWN;
+ }
+
+ private GrpcHelper() {}
}

MODIFY
instrumentation/grpc-1.5/src/main/java/io/opentelemetry/auto/instrumentation/grpc/server/GrpcServerDecorator.java
instrumentation/grpc-1.5/src/main/java/io/opentelemetry/auto/instrumentation/grpc/server/GrpcServerDecorator.java
@@ -19,6 +19,7 @@ package io.opentelemetry.auto.instrumentation.grpc.server;
import io.grpc.Status;
import io.opentelemetry.OpenTelemetry;
import io.opentelemetry.auto.bootstrap.instrumentation.decorator.ServerDecorator;
+import io.opentelemetry.auto.instrumentation.grpc.common.GrpcHelper;
import io.opentelemetry.trace.Span;
import io.opentelemetry.trace.Tracer;
@@ -32,9 +33,7 @@ public class GrpcServerDecorator extends ServerDecorator {
span.setAttribute("status.code", status.getCode().name());
span.setAttribute("status.description", status.getDescription());
onError(span, status.getCause());
- if (!status.isOk()) {
- span.setStatus(io.opentelemetry.trace.Status.UNKNOWN);
- }
+ span.setStatus(GrpcHelper.statusFromGrpcStatus(status));
return span;
}
}

ADD
instrumentation/grpc-1.5/src/test/groovy/io/opentelemetry/auto/instrumentation/grpc/common/GrpcHelperTest.groovy
+/*
+ * 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.
+ */
+
+package io.opentelemetry.auto.instrumentation.grpc.common
+
+import io.grpc.Status
+import spock.lang.Specification
+
+class GrpcHelperTest extends Specification {
+
+ def "test status from #grpcStatus.code"() {
+ when:
+ def status = GrpcHelper.statusFromGrpcStatus(grpcStatus)
+
+ then:
+ status.canonicalCode.name() == grpcStatus.code.name()
+ status.description == null
+
+ // Considering history of status, if we compare all values of the gRPC status by name, we will
+ // probably find any new mismatches with the OpenTelemetry spec.
+ where:
+ grpcStatus << Status.Code.values().collect { Status.fromCode(it) }
+ }
+
+ def "test status has grpc description"() {
+ when:
+ def status = GrpcHelper.statusFromGrpcStatus(Status.INVALID_ARGUMENT.withDescription("bad argument"))
+
+ then:
+ status.canonicalCode == io.opentelemetry.trace.Status.CanonicalCode.INVALID_ARGUMENT
+ status.description == "bad argument"
+ }
+}

Map gRPC status to OTel status.  (#609)