private SentryTraceHeader?TryGetSentryTraceHeader(HttpContext context) { var value = context.Request.Headers.GetValueOrDefault(SentryTraceHeader.HttpHeaderName); if (string.IsNullOrWhiteSpace(value)) { return(null); } _options.LogDebug("Received Sentry trace header '{0}'.", value); try { return(SentryTraceHeader.Parse(value)); } catch (Exception ex) { _options.LogError("Invalid Sentry trace header '{0}'.", ex, value); return(null); } }
/// <summary> /// Populates the scope with the HTTP data /// </summary> /// <remarks> /// NOTE: The scope is applied to the event BEFORE running the event processors/exception processors. /// The main Sentry SDK has processors which run right before any additional processors to the Event /// </remarks> public static void Populate(this Scope scope, HttpContext context, SentryAspNetCoreOptions options) { // Not to throw on code that ignores nullability warnings. // ReSharper disable ConditionIsAlwaysTrueOrFalse if (scope is null || context is null || options is null) { return; } // ReSharper restore ConditionIsAlwaysTrueOrFalse // With the logger integration, a BeginScope call is made with RequestId. That ends up adding // two tags with the same value: RequestId and TraceIdentifier if (!scope.Tags.TryGetValue("RequestId", out var requestId) || requestId != context.TraceIdentifier) { scope.SetTag(nameof(context.TraceIdentifier), context.TraceIdentifier); } if (options.SendDefaultPii && !scope.HasUser()) { var userFactory = context.RequestServices.GetService <IUserFactory>(); var user = userFactory?.Create(context); if (user != null) { scope.User = user; } } try { SetBody(scope, context, options); } catch (Exception e) { options.LogError("Failed to extract body.", e); } SetEnv(scope, context, options); // Extract the route data try { var routeData = context.GetRouteData(); var controller = routeData.Values["controller"]?.ToString(); var action = routeData.Values["action"]?.ToString(); var area = routeData.Values["area"]?.ToString(); if (controller != null) { scope.SetTag("route.controller", controller); } if (action != null) { scope.SetTag("route.action", action); } if (area != null) { scope.SetTag("route.area", area); } // Transaction Name may only be available afterward the creation of the Transaction. // In this case, the event will update the transaction name if captured during the // pipeline execution, allowing it to match the correct transaction name as the current // active transaction. if (string.IsNullOrEmpty(scope.TransactionName)) { scope.TransactionName = context.TryGetTransactionName(); } } catch (Exception e) { // Suppress the error here; we expect an ArgumentNullException if httpContext.Request.RouteValues is null from GetRouteData() // TODO: Consider adding a bool to the Sentry options to make route data extraction optional in case they don't use a routing middleware? options.LogDebug("Failed to extract route data.", e); } // TODO: Get context stuff into scope //context.Session //context.Response //context.Items }