public override async ValueTask Invoke(StreamingHubContext context, Func <StreamingHubContext, ValueTask> next)
        {
            // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/rpc.md#grpc

            using var activity = source.StartActivity($"{context.ServiceContext.MethodType}:/{context.Path}", ActivityKind.Server);

            // activity may be null if "no one is listening" or "all listener returns ActivitySamplingResult.None in Sample or SampleUsingParentId callback".
            if (activity == null)
            {
                await next(context);

                return;
            }

            // add trace context to service context. it allows user to add their span directly to this hub
            context.SetTraceContext(activity.Context);

            try
            {
                // request
                activity.SetTag("grpc.method", context.ServiceContext.MethodType.ToString());
                activity.SetTag("rpc.system", "grpc");
                activity.SetTag("rpc.service", context.ServiceContext.ServiceType.Name);
                activity.SetTag("rpc.method", $"/{context.Path}");
                activity.SetTag("net.peer.ip", context.ServiceContext.CallContext.Peer);
                activity.SetTag("http.host", context.ServiceContext.CallContext.Host);
                activity.SetTag("http.useragent", context.ServiceContext.CallContext.RequestHeaders.GetValue("user-agent"));
                activity.SetTag("message.type", "RECIEVED");
                activity.SetTag("message.id", context.ServiceContext.ContextId.ToString());
                activity.SetTag("message.uncompressed_size", context.Request.Length.ToString());

                activity.SetTag("magiconion.peer.ip", context.ServiceContext.CallContext.Peer);
                activity.SetTag("magiconion.auth.enabled", (!string.IsNullOrEmpty(context.ServiceContext.CallContext.AuthContext.PeerIdentityPropertyName)).ToString());
                activity.SetTag("magiconion.auth.peer.authenticated", context.ServiceContext.CallContext.AuthContext.IsPeerAuthenticated.ToString());

                await next(context);

                // response
                activity.SetTag("grpc.status_code", ((long)context.ServiceContext.CallContext.Status.StatusCode).ToString());
                activity.SetStatus(OpenTelemetryHelper.GrpcToOpenTelemetryStatus(context.ServiceContext.CallContext.Status.StatusCode));
            }
            catch (Exception ex)
            {
                activity.SetTag("exception", ex.ToString());
                activity.SetTag("grpc.status_code", ((long)context.ServiceContext.CallContext.Status.StatusCode).ToString());
                activity.SetTag("grpc.status_detail", context.ServiceContext.CallContext.Status.Detail);
                activity.SetStatus(OpenTelemetryHelper.GrpcToOpenTelemetryStatus(context.ServiceContext.CallContext.Status.StatusCode));
                throw;
            }
        }
Example #2
0
        public override async ValueTask Invoke(StreamingHubContext context, Func <StreamingHubContext, ValueTask> next)
        {
            // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/rpc.md#grpc

            using var activity = source.StartActivity($"{context.ServiceContext.MethodType}:/{context.Path}", ActivityKind.Server);

            // add trace context to service context. it allows user to add their span directly to this hub
            context.SetTraceContext(activity.Context);

            try
            {
                activity.SetTag("grpc.method", context.ServiceContext.MethodType.ToString());
                activity.SetTag("rpc.system", "grpc");
                activity.SetTag("rpc.service", context.ServiceContext.ServiceType.Name);
                activity.SetTag("rpc.method", $"/{context.Path}");
                // todo: context.CallContext.Peer/Host format is https://github.com/grpc/grpc/blob/master/doc/naming.md and not uri standard.
                activity.SetTag("net.peer.ip", context.ServiceContext.CallContext.Peer);
                activity.SetTag("net.host.name", context.ServiceContext.CallContext.Host);
                activity.SetTag("message.type", "RECIEVED");
                activity.SetTag("message.id", context.ServiceContext.ContextId.ToString());
                activity.SetTag("message.uncompressed_size", context.Request.Length.ToString());

                // todo: net.peer.name not report on tracer. use custom tag
                activity.SetTag("magiconion.peer.ip", context.ServiceContext.CallContext.Peer);
                activity.SetTag("magiconion.auth.enabled", (!string.IsNullOrEmpty(context.ServiceContext.CallContext.AuthContext.PeerIdentityPropertyName)).ToString());
                activity.SetTag("magiconion.auth.peer.authenticated", context.ServiceContext.CallContext.AuthContext.IsPeerAuthenticated.ToString());

                await next(context);

                activity.SetTag("grpc.status_code", ((long)context.ServiceContext.CallContext.Status.StatusCode).ToString());
                activity.SetStatus(OpenTelemetrygRpcStatusHelper.ConvertStatus(context.ServiceContext.CallContext.Status.StatusCode));
            }
            catch (Exception ex)
            {
                activity.SetTag("exception", ex.ToString());
                activity.SetTag("grpc.status_code", ((long)context.ServiceContext.CallContext.Status.StatusCode).ToString());
                activity.SetTag("grpc.status_detail", context.ServiceContext.CallContext.Status.Detail);
                activity.SetStatus(OpenTelemetrygRpcStatusHelper.ConvertStatus(context.ServiceContext.CallContext.Status.StatusCode));
                throw;
            }
        }