/// <summary> /// Invokes the next <see cref="RequestDelegate"/> and traces the time /// taken for the next delegate to run, reporting the results to the /// Google Cloud Trace API. /// </summary> /// <param name="httpContext">The current HTTP context.</param> /// <param name="traceContext">Trace information from the current request. Must not be null.</param> /// <param name="fallback">Predicate to be used if the trace context has no information about whether /// the request should be traced or not.</param> /// <param name="traceContextPropagator">Trace context propagator to be used to set the trace context /// on the <see cref="HttpResponse"/>. Must not be null.</param> public async Task Invoke( HttpContext httpContext, ITraceContext traceContext, TraceDecisionPredicate fallback, Action <HttpResponse, ITraceContext> traceContextPropagator) { GaxPreconditions.CheckNotNull(traceContext, nameof(traceContext)); GaxPreconditions.CheckNotNull(traceContextPropagator, nameof(traceContextPropagator)); // Applies the trace decision fallback, if needed. traceContext = WithShouldTraceFallback(traceContext, fallback.ShouldTrace(httpContext.Request)); // Create a tracer for the given request and set it on the context manager so // the tracer can be used in other places. var tracer = _tracerFactory(traceContext); ContextTracerManager.SetCurrentTracer(tracer); if (tracer.GetCurrentTraceId() == null) { await _next(httpContext).ConfigureAwait(false); } else { if (traceContext.TraceId != null) { // Set the current trace context on the response. var currentTraceContext = ContextTracerManager.GetCurrentTraceContext(); traceContextPropagator.Invoke(httpContext.Response, currentTraceContext); } // Trace the delegate and annotate it with information from the current // HTTP context. var traceName = await _nameProvider.GetTraceNameAsync(httpContext).ConfigureAwait(false); var span = tracer.StartSpan(traceName); try { await _next(httpContext).ConfigureAwait(false); } catch (Exception exception) { try { StackTrace stackTrace = new StackTrace(exception, true); tracer.SetStackTrace(stackTrace); } catch (Exception innerException) { throw new AggregateException(innerException, exception); } throw; } finally { tracer.AnnotateSpan(Labels.AgentLabel); tracer.AnnotateSpan(Labels.FromHttpContext(httpContext)); span.Dispose(); } } }
/// <summary> /// Invokes the next <see cref="RequestDelegate"/> and traces the time /// taken for the next delegate to run, reporting the results to the /// Stackdriver Trace API. /// </summary> /// <param name="httpContext">The current HTTP context.</param> /// <param name="traceHeaderContext">Information from the current request header. Must not be null.</param> public async Task Invoke(HttpContext httpContext, TraceHeaderContext traceHeaderContext) { GaxPreconditions.CheckNotNull(traceHeaderContext, nameof(traceHeaderContext)); // Create a tracer for the given request and set it on the context manager so // the tracer can be used in other places. var tracer = _tracerFactory(traceHeaderContext); ContextTracerManager.SetCurrentTracer(tracer); if (tracer.GetCurrentTraceId() == null) { await _next(httpContext).ConfigureAwait(false); } else { if (traceHeaderContext.TraceId != null) { // Set the trace updated trace header on the response. var updatedHeaderContext = TraceHeaderContext.Create( tracer.GetCurrentTraceId(), tracer.GetCurrentSpanId() ?? 0, true); httpContext.Response.Headers.Add( TraceHeaderContext.TraceHeader, updatedHeaderContext.ToString()); } // Trace the delegate and annotate it with information from the current // HTTP context. var traceName = await _nameProvider.GetTraceNameAsync(httpContext).ConfigureAwait(false); var span = tracer.StartSpan(traceName); try { await _next(httpContext).ConfigureAwait(false); } catch (Exception exception) { try { StackTrace stackTrace = new StackTrace(exception, true); tracer.SetStackTrace(stackTrace); } catch (Exception innerException) { throw new AggregateException(innerException, exception); } throw; } finally { tracer.AnnotateSpan(Labels.AgentLabel); tracer.AnnotateSpan(Labels.FromHttpContext(httpContext)); span.Dispose(); } } }