Example #1
0
        public async Task Invoke(HttpContext context, ITracer tracer)
        {
            if (!this.options.Enabled ||
                tracer == null ||
                context.Request.Path.Value.EqualsPatternAny(this.options.PathBlackListPatterns))
            {
                await this.next.Invoke(context).AnyContext();
            }
            else
            {
                var    uri        = context.Request.GetUri();
                object action     = null;
                object controller = null;
                context.GetRouteData()?.Values.TryGetValue("Action", out action);
                context.GetRouteData()?.Values.TryGetValue("Controller", out controller);

                // dehydrate the span infos
                var parentSpan = new Span(
                    context.Request.Headers.GetValue("x-traceid").EmptyToNull() ?? ActivityTraceId.CreateRandom().ToString() /*context.GetCorrelationId()*/,         // dehydrate the span infos
                    context.Request.Headers.GetValue("x-spanid"));
                parentSpan.SetSampled(context.Request.Headers.GetValue("x-tracesampled").To <bool>());

                using (var scope = tracer.BuildSpan(
                           $"{LogTraceNames.Http} {action ?? context.Request.Method.ToLowerInvariant()} {uri.AbsolutePath}{(controller != null ? $" ({controller.ToString().Singularize()})" : string.Empty)}",
                           LogKeys.InboundRequest,
                           SpanKind.Server,
                           parentSpan)

                                   // TODO: get service name as operationname (servicedescriptor?)
                                   .IgnoreParentSpan()
                                   //.SetSpanId(context.GetRequestId())
                                   .WithTag(SpanTagKey.HttpMethod, context.Request.Method.ToLowerInvariant())
                                   .WithTag(SpanTagKey.HttpUrl, context.Request.GetDisplayUrl())
                                   .WithTag(SpanTagKey.HttpHost, uri.Port > 0 ? $"{uri.Host}:{uri.Port}" : uri.Host)
                                   .WithTag(SpanTagKey.HttpPath, uri.AbsolutePath)
                                   // TODO: request size? SpanTagKey.HttpRequestSize
                                   .WithTag(SpanTagKey.HttpRequestId, context.GetRequestId()).Activate(this.logger))
                {
                    try
                    {
                        if (scope.Span.IsSampled == false)
                        {
                            this.logger.LogDebug($"{{LogKey:l}} span not sampled (id={scope.Span.SpanId}, sampler={scope.Span.Tags.GetValueOrDefault(SpanTagKey.SamplerType)})", LogKeys.Tracing);
                        }
                        else
                        {
                            this.logger.LogDebug($"{{LogKey:l}} span sampled (id={scope.Span.SpanId}, sampler={scope.Span.Tags.GetValueOrDefault(SpanTagKey.SamplerType)})", LogKeys.Tracing);
                        }

                        await this.next.Invoke(context).AnyContext();

                        scope.Span.WithTag("http.status_code", context.Response.StatusCode);
                        // TODO: response size?

                        if (context.Response.StatusCode > 399)
                        {
                            scope.Span.SetStatus(SpanStatus.Failed, $"{context.Response.StatusCode} ({ReasonPhrases.GetReasonPhrase(context.Response.StatusCode)})");
                        }
                        else
                        {
                            scope.Span.SetStatus(SpanStatus.Succeeded, $"{context.Response.StatusCode} ({ReasonPhrases.GetReasonPhrase(context.Response.StatusCode)})");
                        }
                    }
                    catch (Exception ex)
                    {
                        tracer.Fail(exception: ex);
                        throw;
                    }
                }
            }
        }