/// <summary> /// Handles the <see cref="HttpContext"/>. /// </summary> public async Task InvokeAsync(HttpContext context) { var hub = _getHub(); if (!hub.IsEnabled) { await _next(context).ConfigureAwait(false); return; } await hub.ConfigureScopeAsync(async scope => { // Attempt to start a transaction from the trace header if it exists var traceHeader = TryGetSentryTraceHeader(context); // Defer setting name until other middlewares have finished var transaction = traceHeader is not null ? hub.StartTransaction( "Unknown Route", "http.server", traceHeader ) : hub.StartTransaction( "Unknown Route", "http.server" ); _options.DiagnosticLogger?.LogInfo( "Started transaction: Span ID: {0}, Trace ID: {1}", transaction.SpanId, transaction.TraceId ); // Put the transaction on the scope scope.Transaction = transaction; try { await _next(context).ConfigureAwait(false); } finally { // Try to resolve the route if (context.TryGetTransactionName() is { } transactionName) { transaction.Name = transactionName; } transaction.Finish( SpanStatusConverter.FromHttpStatusCode(context.Response.StatusCode) ); } }).ConfigureAwait(false); }
/// <summary> /// Handles the <see cref="HttpContext"/>. /// </summary> public async Task InvokeAsync(HttpContext context) { var hub = _getHub(); if (!hub.IsEnabled) { await _next(context).ConfigureAwait(false); return; } var transaction = TryStartTransaction(context); // Expose the transaction on the scope so that the user // can retrieve it and start child spans off of it. hub.ConfigureScope(scope => { scope.Transaction = transaction; scope.OnEvaluating += (_, _) => scope.Populate(context, _options); }); try { await _next(context).ConfigureAwait(false); } finally { if (transaction is not null) { // The routing middleware may have ran after ours, so // try to get the transaction name again. if (context.TryGetTransactionName() is { } transactionName) { if (!string.Equals(transaction.Name, transactionName, StringComparison.Ordinal)) { _options.DiagnosticLogger?.LogDebug( "Changed transaction name from '{0}' to '{1}' after request pipeline executed.", transaction.Name, transactionName ); } transaction.Name = transactionName; } transaction.Finish( SpanStatusConverter.FromHttpStatusCode(context.Response.StatusCode) ); } } }
/// <summary> /// Finishes an active Sentry transaction that encompasses the currently executing HTTP request (if present). /// </summary> public static void FinishSentryTransaction(this HttpContext httpContext) { if (!httpContext.Items.Contains(HttpContextTransactionItemName)) { return; } if (httpContext.Items[HttpContextTransactionItemName] is not ISpan transaction) { return; } var status = SpanStatusConverter.FromHttpStatusCode(httpContext.Response.StatusCode); transaction.Finish(status); }
/// <summary> /// Handles the <see cref="HttpContext"/>. /// </summary> public async Task InvokeAsync(HttpContext context) { var hub = _getHub(); if (!hub.IsEnabled) { await _next(context).ConfigureAwait(false); return; } var transaction = TryStartTransaction(context); var initialName = transaction?.Name; // Expose the transaction on the scope so that the user // can retrieve it and start child spans off of it. hub.ConfigureScope(scope => { scope.Transaction = transaction; }); Exception?exception = null; try { await _next(context).ConfigureAwait(false); } catch (Exception e) { exception = e; } finally { if (transaction is not null) { // The Transaction name was altered during the pipeline execution, // That could be done by user interference or by some Event Capture // That triggers ScopeExtensions.Populate. if (transaction.Name != initialName) { _options.LogDebug( "transaction name set from '{0}' to '{1}' during request pipeline execution.", initialName, transaction.Name); } // try to get the transaction name. else if (context.TryGetTransactionName() is { } transactionName&& !string.IsNullOrEmpty(transactionName)) { _options.LogDebug( "Changed transaction '{0}', name set to '{1}' after request pipeline executed.", transaction.SpanId, transactionName); transaction.Name = transactionName; } var status = SpanStatusConverter.FromHttpStatusCode(context.Response.StatusCode); // If no Name was found for Transaction, fallback to UnknownRoute name. if (transaction.Name == string.Empty) { transaction.Name = UnknownRouteTransactionName; } if (exception is null) { transaction.Finish(status); } // Status code not yet changed to 500 but an exception does exist // so lets avoid passing the misleading 200 down and close only with // the exception instance that will be inferred as errored. else if (status == SpanStatus.Ok) { transaction.Finish(exception); } else { transaction.Finish(exception, status); } } if (exception is not null) { ExceptionDispatchInfo.Capture(exception).Throw(); } } }
/// <summary> /// Handles the <see cref="HttpContext"/>. /// </summary> public async Task InvokeAsync(HttpContext context) { var hub = _getHub(); if (!hub.IsEnabled) { await _next(context).ConfigureAwait(false); return; } var transaction = TryStartTransaction(context); // Expose the transaction on the scope so that the user // can retrieve it and start child spans off of it. hub.ConfigureScope(scope => { scope.Transaction = transaction; scope.OnEvaluating += (_, _) => scope.Populate(context, _options); }); Exception?exception = null; try { await _next(context).ConfigureAwait(false); } catch (Exception e) { exception = e; } finally { if (transaction is not null) { // The routing middleware may have ran after ours, so // try to get the transaction name again. if (context.TryGetTransactionName() is { } transactionName) { if (!string.Equals(transaction.Name, transactionName, StringComparison.Ordinal)) { _options.DiagnosticLogger?.LogDebug( "Changed transaction name from '{0}' to '{1}' after request pipeline executed.", transaction.Name, transactionName ); } transaction.Name = transactionName; } var status = SpanStatusConverter.FromHttpStatusCode(context.Response.StatusCode); if (exception is null) { transaction.Finish(status); } // Status code not yet changed to 500 but an exception does exist // so lets avoid passing the misleading 200 down and close only with // the exception instance that will be inferred as errored. else if (status == SpanStatus.Ok) { transaction.Finish(exception); } else { transaction.Finish(exception, status); } } if (exception is not null) { ExceptionDispatchInfo.Capture(exception).Throw(); } } }