internal static Scope CreateScope(IHttpControllerContext controllerContext, out AspNetTags tags) { Scope scope = null; tags = null; try { if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationId)) { // integration disabled, don't create a scope, skip this trace return(null); } var tracer = Tracer.Instance; var request = controllerContext.Request; SpanContext propagatedContext = null; var tagsFromHeaders = Enumerable.Empty <KeyValuePair <string, string> >(); if (request != null && tracer.InternalActiveScope == null) { try { // extract propagated http headers var headers = request.Headers; var headersCollection = new HttpHeadersCollection(headers); propagatedContext = SpanContextPropagator.Instance.Extract(headersCollection); tagsFromHeaders = SpanContextPropagator.Instance.ExtractHeaderTags(headersCollection, tracer.Settings.HeaderTags, SpanContextPropagator.HttpRequestHeadersTagPrefix, request.Headers.UserAgent.ToString()); } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } tags = new AspNetTags(); scope = tracer.StartActiveInternal(OperationName, propagatedContext, tags: tags); UpdateSpan(controllerContext, scope.Span, tags, tagsFromHeaders); tags.SetAnalyticsSampleRate(IntegrationId, tracer.Settings, enabledWithGlobalSetting: true); tracer.TracerManager.Telemetry.IntegrationGeneratedSpan(IntegrationId); } catch (Exception ex) { Log.Error(ex, "Error creating scope."); } return(scope); }
internal static void UpdateSpan(IHttpControllerContext controllerContext, Span span, AspNetTags tags, IEnumerable <KeyValuePair <string, string> > headerTags) { try { var newResourceNamesEnabled = Tracer.Instance.Settings.RouteTemplateResourceNamesEnabled; var request = controllerContext.Request; Uri requestUri = request.RequestUri; string host = request.Headers.Host ?? string.Empty; string rawUrl = requestUri?.ToString().ToLowerInvariant() ?? string.Empty; string method = request.Method.Method?.ToUpperInvariant() ?? "GET"; string route = null; try { route = controllerContext.RouteData.Route.RouteTemplate; } catch { } string resourceName; if (route != null) { resourceName = $"{method} {(newResourceNamesEnabled ? "/" : string.Empty)}{route.ToLowerInvariant()}"; } else if (requestUri != null) { var cleanUri = UriHelpers.GetCleanUriPath(requestUri); resourceName = $"{method} {cleanUri.ToLowerInvariant()}"; } else { resourceName = $"{method}"; } string controller = string.Empty; string action = string.Empty; string area = string.Empty; try { var routeValues = controllerContext.RouteData.Values; if (routeValues != null) { controller = (routeValues.GetValueOrDefault("controller") as string)?.ToLowerInvariant(); action = (routeValues.GetValueOrDefault("action") as string)?.ToLowerInvariant(); area = (routeValues.GetValueOrDefault("area") as string)?.ToLowerInvariant(); } } catch { } // Replace well-known routing tokens resourceName = resourceName .Replace("{area}", area) .Replace("{controller}", controller) .Replace("{action}", action); span.DecorateWebServerSpan( resourceName: resourceName, method: method, host: host, httpUrl: rawUrl, tags, headerTags); tags.AspNetAction = action; tags.AspNetController = controller; tags.AspNetArea = area; tags.AspNetRoute = route; if (newResourceNamesEnabled) { // set the resource name in the HttpContext so TracingHttpModule can update root span var httpContext = System.Web.HttpContext.Current; if (httpContext is not null) { httpContext.Items[SharedConstants.HttpContextPropagatedResourceNameKey] = resourceName; } } } catch (Exception ex) { Log.Error(ex, "Error populating scope data."); } }
internal static void UpdateSpan(IHttpControllerContext controllerContext, Span span, AspNetTags tags, IEnumerable <KeyValuePair <string, string> > headerTags) { try { var newResourceNamesEnabled = Tracer.Instance.Settings.RouteTemplateResourceNamesEnabled; var request = controllerContext.Request; Uri requestUri = request.RequestUri; string host = request.Headers.Host ?? string.Empty; string rawUrl = requestUri?.ToString().ToLowerInvariant() ?? string.Empty; string method = request.Method.Method?.ToUpperInvariant() ?? "GET"; string route = null; try { route = controllerContext.RouteData.Route.RouteTemplate; } catch { } IDictionary <string, object> routeValues = null; try { routeValues = controllerContext.RouteData.Values; } catch { } string resourceName; string controller = string.Empty; string action = string.Empty; string area = string.Empty; if (route is not null && routeValues is not null) { resourceName = AspNetResourceNameHelper.CalculateResourceName( httpMethod: method, routeTemplate: route, routeValues, defaults: null, out area, out controller, out action, addSlashPrefix: newResourceNamesEnabled, expandRouteTemplates: newResourceNamesEnabled && Tracer.Instance.Settings.ExpandRouteTemplatesEnabled); } else if (requestUri != null) { var cleanUri = UriHelpers.GetCleanUriPath(requestUri); resourceName = $"{method} {cleanUri}"; } else { resourceName = $"{method}"; } if (route is null && routeValues is not null) { // we weren't able to get the route template (somehow) but _were_ able to // get the route values. Not sure how this is possible, but is preexisting behaviour try { controller = (routeValues.GetValueOrDefault("controller") as string)?.ToLowerInvariant(); action = (routeValues.GetValueOrDefault("action") as string)?.ToLowerInvariant(); area = (routeValues.GetValueOrDefault("area") as string)?.ToLowerInvariant(); } catch { } } span.DecorateWebServerSpan( resourceName: resourceName, method: method, host: host, httpUrl: rawUrl, tags, headerTags); if (tags is not null) { tags.AspNetAction = action; tags.AspNetController = controller; tags.AspNetArea = area; tags.AspNetRoute = route; } if (newResourceNamesEnabled) { // set the resource name in the HttpContext so TracingHttpModule can update root span var httpContext = System.Web.HttpContext.Current; if (httpContext is not null) { httpContext.Items[SharedItems.HttpContextPropagatedResourceNameKey] = resourceName; } } }