opentelemetry-go-contrib icon indicating copy to clipboard operation
opentelemetry-go-contrib copied to clipboard

Filter or skip span status for some grpc codes

Open amanakin opened this issue 1 year ago • 1 comments

Problem Statement

Now grpc interceptor sets span error if handler returned one of codes Unknown, DeadlineExceeded, Unimplemented, etc. But on NotFound code span status won't be set, which is should be configurable. Or vice versa, you could avoid setting span error on certain codes.

Proposed Solution

Add custom CodeFromGRPCStatus function as ServerInterceptor option.

Something like that:

--- vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go        (index)
+++ vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go        (working tree)
@@ -42,6 +42,7 @@ type config struct {
        TracerProvider   trace.TracerProvider
        MeterProvider    metric.MeterProvider
        SpanStartOptions []trace.SpanStartOption
+       CodeFromGRPCStatus CodeFromGRPCStatus

        ReceivedEvent bool
        SentEvent     bool
@@ -61,6 +62,7 @@ func newConfig(opts []Option) *config {
                Propagators:    otel.GetTextMapPropagator(),
                TracerProvider: otel.GetTracerProvider(),
                MeterProvider:  otel.GetMeterProvider(),
+               CodeFromGRPCStatus: serverStatus,
        }
        for _, o := range opts {
                o.apply(c)
@@ -182,3 +184,14 @@ func (o spanStartOption) apply(c *config) {
 func WithSpanOptions(opts ...trace.SpanStartOption) Option {
        return spanStartOption{opts}
 }
+
+
+type codeFromGRPCOption struct { codeFromGRPC CodeFromGRPCStatus }
+
+func (o codeFromGRPCOption) apply(c *config) {
+       c.CodeFromGRPCStatus = o.codeFromGRPC
+}
+
+func WithCodeFromGRPCStatus(codeFromGRPC CodeFromGRPCStatus) Option {
+       return codeFromGRPCOption{codeFromGRPC: codeFromGRPC}
+}
--- vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/interceptor.go   (index)
+++ vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/interceptor.go   (working tree)
@@ -376,8 +376,8 @@ func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
                resp, err := handler(ctx, req)
                if err != nil {
                        s, _ := status.FromError(err)
-                       statusCode, msg := serverStatus(s)
-                       span.SetStatus(statusCode, msg)
+                       code, msg := cfg.CodeFromGRPCStatus(s)
+                       span.SetStatus(code, msg)
                        span.SetAttributes(statusCodeAttr(s.Code()))
                        if cfg.SentEvent {
                                messageSent.Event(ctx, 1, s.Proto())
@@ -487,8 +487,8 @@ func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
                err := handler(srv, wrapServerStream(ctx, ss, cfg))
                if err != nil {
                        s, _ := status.FromError(err)
-                       statusCode, msg := serverStatus(s)
-                       span.SetStatus(statusCode, msg)
+                       code, msg := cfg.CodeFromGRPCStatus(s)
+                       span.SetStatus(code, msg)
                        span.SetAttributes(statusCodeAttr(s.Code()))
                } else {
                        span.SetAttributes(statusCodeAttr(grpc_codes.OK))
@@ -553,6 +553,8 @@ func statusCodeAttr(c grpc_codes.Code) attribute.KeyValue {
        return GRPCStatusCodeKey.Int64(int64(c))
 }

+type CodeFromGRPCStatus func (grpcStatus *status.Status) (codes.Code, string)
+
 // serverStatus returns a span status code and message for a given gRPC
 // status code. It maps specific gRPC status codes to a corresponding span
 // status code and message. This function is intended for use on the server

amanakin avatar Jan 11 '24 15:01 amanakin

The gRPC status code mapping to span status is defined strongly in the spec: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/rpc/grpc.md#grpc-status. Unless changes to the spec doubt this instrumentation would change.

Changing this could create side effects with vendor backend implementations. I don't really recommend changing this mapping behavior but you could attempt to alter this by either using a custom fork of the library or play around with otel collector processors (e.g. transformprocessor)

scorpionknifes avatar Jan 12 '24 02:01 scorpionknifes