private void OnBeginRequest(object sender, EventArgs eventArgs) { Scope scope = null; try { var tracer = Tracer.Instance; if (!tracer.Settings.IsIntegrationEnabled(IntegrationName)) { // integration disabled return; } var httpContext = (sender as HttpApplication)?.Context; if (httpContext == null) { return; } HttpRequest httpRequest = httpContext.Request; SpanContext propagatedContext = null; if (tracer.ActiveScope == null) { try { // extract propagated http headers var headers = httpRequest.Headers.Wrap(); propagatedContext = SpanContextPropagator.Instance.Extract(headers); } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } string host = httpRequest.Headers.Get("Host"); string httpMethod = httpRequest.HttpMethod.ToUpperInvariant(); string url = httpRequest.RawUrl.ToLowerInvariant(); string path = UriHelpers.GetRelativeUrl(httpRequest.Url, tryRemoveIds: true); string resourceName = $"{httpMethod} {path.ToLowerInvariant()}"; scope = tracer.StartActive(_requestOperationName, propagatedContext); scope.Span.DecorateWebServerSpan(resourceName, httpMethod, host, url); // set analytics sample rate if enabled var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate); httpContext.Items[_httpContextScopeKey] = scope; } catch (Exception ex) { // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case... scope?.Dispose(); Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error"); } }
private static void GetTagValues( object actionDescriptor, object request, out string httpMethod, out string host, out string resourceName, out string url, out string controllerName, out string actionName) { controllerName = actionDescriptor.GetProperty <string>("ControllerName").GetValueOrDefault()?.ToLowerInvariant(); actionName = actionDescriptor.GetProperty <string>("ActionName").GetValueOrDefault()?.ToLowerInvariant(); host = request.GetProperty("Host").GetProperty <string>("Value").GetValueOrDefault(); httpMethod = request.GetProperty <string>("Method").GetValueOrDefault()?.ToUpperInvariant() ?? "UNKNOWN"; string pathBase = request.GetProperty("PathBase").GetProperty <string>("Value").GetValueOrDefault(); string path = request.GetProperty("Path").GetProperty <string>("Value").GetValueOrDefault(); string queryString = request.GetProperty("QueryString").GetProperty <string>("Value").GetValueOrDefault(); url = $"{pathBase}{path}{queryString}"; string resourceUrl = actionDescriptor.GetProperty("AttributeRouteInfo").GetProperty <string>("Template").GetValueOrDefault() ?? UriHelpers.GetRelativeUrl(new Uri($"https://{host}{url}"), tryRemoveIds: true).ToLowerInvariant(); resourceName = $"{httpMethod} {resourceUrl}"; }
private static void GetTagValues( object request, out string url, out string httpMethod, out string host, out string resourceName) { host = request.GetProperty("Host").GetProperty <string>("Value").GetValueOrDefault(); httpMethod = request.GetProperty <string>("Method").GetValueOrDefault()?.ToUpperInvariant() ?? "UNKNOWN"; string pathBase = request.GetProperty("PathBase").GetProperty <string>("Value").GetValueOrDefault(); string path = request.GetProperty("Path").GetProperty <string>("Value").GetValueOrDefault(); string queryString = request.GetProperty("QueryString").GetProperty <string>("Value").GetValueOrDefault(); string scheme = request.GetProperty <string>("Scheme").GetValueOrDefault()?.ToUpperInvariant() ?? "http"; url = $"{pathBase}{path}{queryString}"; string resourceUrl = UriHelpers.GetRelativeUrl(new Uri($"{scheme}://{host}{url}"), tryRemoveIds: true).ToLowerInvariant(); resourceName = $"{httpMethod} {resourceUrl}"; }
public override bool TryGetResourceName(out string resourceName) { // TODO: This will need to be moved out into a strategy to support extending to other integrations... var httpMethod = (GetHttpMethod() ?? Scope?.Span?.GetHttpMethod() ?? "GET").ToUpperInvariant(); string suffix = _httpContext.Request?.Url == null ? string.Empty : UriHelpers.GetRelativeUrl(_httpContext.Request.Url, tryRemoveIds: true); resourceName = $"{httpMethod} {suffix.ToLowerInvariant()}"; return(true); }
private void OnHostingHttpRequestInStart(object arg) { var httpContext = HttpRequestInStartHttpContextFetcher.Fetch <HttpContext>(arg); if (ShouldIgnore(httpContext)) { if (_isLogLevelDebugEnabled) { Log.Debug("Ignoring request"); } } else { HttpRequest request = httpContext.Request; string host = request.Host.Value; string httpMethod = request.Method?.ToUpperInvariant() ?? "UNKNOWN"; string url = GetUrl(request); string absolutePath = request.Path.Value; if (request.PathBase.HasValue) { absolutePath = request.PathBase.Value + absolutePath; } string resourceUrl = UriHelpers.GetRelativeUrl(absolutePath, tryRemoveIds: true) .ToLowerInvariant(); string resourceName = $"{httpMethod} {resourceUrl}"; SpanContext propagatedContext = ExtractPropagatedContext(request); var tagsFromHeaders = ExtractHeaderTags(request, _tracer); Span span = _tracer.StartSpan(HttpRequestInOperationName, propagatedContext) .SetTag(Tags.InstrumentationName, ComponentName); span.DecorateWebServerSpan(resourceName, httpMethod, host, url, tagsFromHeaders); // set analytics sample rate if enabled var analyticsSampleRate = _tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); span.SetMetric(Tags.Analytics, analyticsSampleRate); Scope scope = _tracer.ActivateSpan(span); _options.OnRequest?.Invoke(scope.Span, httpContext); } }
private void OnHostingHttpRequestInStart(object arg) { var tracer = _tracer ?? Tracer.Instance; if (!tracer.Settings.IsIntegrationEnabled(IntegrationName)) { return; } var httpContext = HttpRequestInStartHttpContextFetcher.Fetch <HttpContext>(arg); HttpRequest request = httpContext.Request; string host = request.Host.Value; string httpMethod = request.Method?.ToUpperInvariant() ?? "UNKNOWN"; string url = GetUrl(request); string absolutePath = request.Path.Value; if (request.PathBase.HasValue) { absolutePath = request.PathBase.Value + absolutePath; } string resourceUrl = UriHelpers.GetRelativeUrl(absolutePath, tryRemoveIds: true) .ToLowerInvariant(); string resourceName = $"{httpMethod} {resourceUrl}"; SpanContext propagatedContext = ExtractPropagatedContext(request); var tagsFromHeaders = ExtractHeaderTags(request, tracer); var tags = new AspNetCoreTags(); var scope = tracer.StartActiveWithTags(HttpRequestInOperationName, propagatedContext, tags: tags); tags.InstrumentationName = ComponentName; scope.Span.DecorateWebServerSpan(resourceName, httpMethod, host, url, tags, tagsFromHeaders); // set analytics sample rate if enabled var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); if (analyticsSampleRate != null) { tags.AnalyticsSampleRate = analyticsSampleRate; } }
private void OnHostingHttpRequestInStart(object arg) { var httpContext = (HttpContext)HttpRequestInStartHttpContextFetcher.Fetch(arg); if (ShouldIgnore(httpContext)) { if (_isLogLevelDebugEnabled) { Log.Debug("Ignoring request"); } } else { HttpRequest request = httpContext.Request; string host = request.Host.Value; string httpMethod = request.Method?.ToUpperInvariant() ?? "UNKNOWN"; string url = GetUrl(request); string resourceUrl = UriHelpers.GetRelativeUrl(new Uri(url), tryRemoveIds: true) .ToLowerInvariant(); var propagator = _tracer.Propagator; SpanContext propagatedContext = ExtractPropagatedContext(propagator, request); Span span = _tracer.StartSpan(HttpRequestInOperationName, propagatedContext) .SetTag(Tags.InstrumentationName, ComponentName); IPAddress remoteIp = null; if (Tracing.Tracer.Instance.Settings.AddClientIpToServerSpans) { remoteIp = httpContext?.Connection?.RemoteIpAddress; } span.DecorateWebServerSpan(resourceUrl, httpMethod, host, url, remoteIp); span.SetTag(Tags.InstrumentationName, IntegrationName); // set analytics sample rate if enabled var analyticsSampleRate = _tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); span.SetMetric(Tags.Analytics, analyticsSampleRate); Scope scope = _tracer.ActivateSpan(span); _options.OnRequest?.Invoke(scope.Span, httpContext); } }
private static void UpdateSpan(object controllerContext, Span span, AspNetTags tags, IEnumerable <KeyValuePair <string, string> > headerTags) { try { object request = controllerContext.GetProperty <object>("Request").GetValueOrDefault(); Uri requestUri = request.GetProperty <Uri>("RequestUri").GetValueOrDefault(); string host = request.GetProperty <object>("Headers").GetProperty <string>("Host").GetValueOrDefault() ?? string.Empty; string rawUrl = requestUri?.ToString().ToLowerInvariant() ?? string.Empty; string absoluteUri = requestUri?.AbsoluteUri?.ToLowerInvariant() ?? string.Empty; string method = request.GetProperty <object>("Method").GetProperty <string>("Method").GetValueOrDefault()?.ToUpperInvariant() ?? "GET"; string route = null; try { route = controllerContext.GetProperty <object>("RouteData").GetProperty <object>("Route").GetProperty <string>("RouteTemplate").GetValueOrDefault(); } catch { } string resourceName = $"{method} {absoluteUri.ToLowerInvariant()}"; if (route != null) { resourceName = $"{method} {route.ToLowerInvariant()}"; } else if (requestUri != null) { var cleanUri = UriHelpers.GetRelativeUrl(requestUri, tryRemoveIds: true); resourceName = $"{method} {cleanUri.ToLowerInvariant()}"; } string controller = string.Empty; string action = string.Empty; try { var routeValues = controllerContext.GetProperty <object>("RouteData").GetProperty <IDictionary <string, object> >("Values").GetValueOrDefault(); if (routeValues != null) { controller = (routeValues.GetValueOrDefault("controller") as string)?.ToLowerInvariant(); action = (routeValues.GetValueOrDefault("action") as string)?.ToLowerInvariant(); } } catch { } // Fail safe to catch templates in routing values resourceName = resourceName .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.AspNetRoute = route; } catch (Exception ex) { Log.Error(ex, "Error populating scope data."); } }
/// <summary> /// Creates a scope used to instrument an MVC action and populates some common details. /// </summary> /// <param name="controllerContext">The System.Web.Mvc.ControllerContext that was passed as an argument to the instrumented method.</param> /// <returns>A new scope used to instrument an MVC action.</returns> public static Scope CreateScope(object controllerContext) { Scope scope = null; try { if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName)) { // integration disabled, don't create a scope, skip this trace return(null); } if (controllerContext == null || controllerContext.GetType().FullName != ControllerContextTypeName) { return(null); } var httpContext = controllerContext.GetProperty <HttpContextBase>("HttpContext").GetValueOrDefault(); if (httpContext == null) { return(null); } string host = httpContext.Request.Headers.Get("Host"); string httpMethod = httpContext.Request.HttpMethod.ToUpperInvariant(); string url = httpContext.Request.RawUrl.ToLowerInvariant(); string resourceName = null; RouteData routeData = controllerContext.GetProperty <RouteData>("RouteData").GetValueOrDefault(); Route route = routeData?.Route as Route; RouteValueDictionary routeValues = routeData?.Values; if (route == null && routeData?.Route.GetType().FullName == RouteCollectionRouteTypeName) { var routeMatches = routeValues?.GetValueOrDefault("MS_DirectRouteMatches") as List <RouteData>; if (routeMatches?.Count > 0) { // route was defined using attribute routing i.e. [Route("/path/{id}")] // get route and routeValues from the RouteData in routeMatches route = routeMatches[0].Route as Route; routeValues = routeMatches[0].Values; if (route != null) { var resourceUrl = route.Url?.ToLowerInvariant() ?? string.Empty; if (resourceUrl.FirstOrDefault() != '/') { resourceUrl = string.Concat("/", resourceUrl); } resourceName = $"{httpMethod} {resourceUrl}"; } } } if (string.IsNullOrEmpty(resourceName) && httpContext.Request.Url != null) { var cleanUri = UriHelpers.GetRelativeUrl(httpContext.Request.Url, tryRemoveIds: true); resourceName = $"{httpMethod} {cleanUri.ToLowerInvariant()}"; } string controllerName = (routeValues?.GetValueOrDefault("controller") as string)?.ToLowerInvariant(); string actionName = (routeValues?.GetValueOrDefault("action") as string)?.ToLowerInvariant(); if (string.IsNullOrEmpty(resourceName)) { // Keep the legacy resource name, just to have something resourceName = $"{httpMethod} {controllerName}.{actionName}"; } SpanContext propagatedContext = null; var tracer = Tracer.Instance; var tagsFromHeaders = Enumerable.Empty <KeyValuePair <string, string> >(); if (tracer.ActiveScope == null) { try { // extract propagated http headers var headers = httpContext.Request.Headers.Wrap(); propagatedContext = SpanContextPropagator.Instance.Extract(headers); tagsFromHeaders = SpanContextPropagator.Instance.ExtractHeaderTags(headers, tracer.Settings.HeaderTags); } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } scope = Tracer.Instance.StartActive(OperationName, propagatedContext); Span span = scope.Span; // Fail safe to catch templates in routing values resourceName = resourceName .Replace("{controller}", controllerName) .Replace("{action}", actionName); span.DecorateWebServerSpan( resourceName: resourceName, method: httpMethod, host: host, httpUrl: url, tags: tagsFromHeaders); span.SetTag(Tags.AspNetRoute, route?.Url); span.SetTag(Tags.AspNetController, controllerName); span.SetTag(Tags.AspNetAction, actionName); // set analytics sample rate if enabled var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); span.SetMetric(Tags.Analytics, analyticsSampleRate); } catch (Exception ex) { Log.Error(ex, "Error creating or populating scope."); } return(scope); }
private static void UpdateSpan(dynamic controllerContext, Span span) { try { var req = controllerContext?.Request as HttpRequestMessage; string host = req?.Headers?.Host ?? string.Empty; string rawUrl = req?.RequestUri?.ToString().ToLowerInvariant() ?? string.Empty; string absoluteUri = req?.RequestUri?.AbsoluteUri?.ToLowerInvariant() ?? string.Empty; string method = controllerContext?.Request?.Method?.Method?.ToUpperInvariant() ?? "GET"; string route = null; try { route = controllerContext?.RouteData?.Route?.RouteTemplate; } catch { } string resourceName = $"{method} {absoluteUri.ToLowerInvariant()}"; if (route != null) { resourceName = $"{method} {route.ToLowerInvariant()}"; } else if (req?.RequestUri != null) { var cleanUri = UriHelpers.GetRelativeUrl(req?.RequestUri, tryRemoveIds: true); resourceName = $"{method} {cleanUri.ToLowerInvariant()}"; } string controller = string.Empty; string action = string.Empty; try { if (controllerContext?.RouteData?.Values is IDictionary <string, object> routeValues) { controller = (routeValues.GetValueOrDefault("controller") as string)?.ToLowerInvariant(); action = (routeValues.GetValueOrDefault("action") as string)?.ToLowerInvariant(); } } catch { } // Fail safe to catch templates in routing values resourceName = resourceName .Replace("{controller}", controller) .Replace("{action}", action); IPAddress remoteIp = null; if (req != null && Tracer.Instance.Settings.AddClientIpToServerSpans) { var httpContextWrapper = req.Properties.GetValueOrDefault("MS_HttpContext") as HttpContextWrapper; if (httpContextWrapper != null) { IPAddress.TryParse(httpContextWrapper.Request.UserHostAddress, out remoteIp); } else { var remoteEndpoint = req.Properties.GetValueOrDefault(RemoteEndpointMessageProperty.Name) as RemoteEndpointMessageProperty; if (remoteEndpoint != null) { IPAddress.TryParse(remoteEndpoint.Address, out remoteIp); } } } span.DecorateWebServerSpan( resourceName: resourceName, method: method, host: host, httpUrl: rawUrl, remoteIp: remoteIp); span.SetTag(Tags.AspNetAction, action); span.SetTag(Tags.AspNetController, controller); span.SetTag(Tags.AspNetRoute, route); } catch (Exception ex) { Log.Error(ex, "Error populating scope data."); } }
private void OnBeginRequest(object sender, EventArgs eventArgs) { Scope scope = null; try { var tracer = Tracer.Instance; if (!tracer.Settings.IsIntegrationEnabled(IntegrationId)) { // integration disabled return; } var httpContext = (sender as HttpApplication)?.Context; if (httpContext == null) { return; } HttpRequest httpRequest = httpContext.Request; SpanContext propagatedContext = null; var tagsFromHeaders = Enumerable.Empty <KeyValuePair <string, string> >(); if (tracer.ActiveScope == null) { try { // extract propagated http headers var headers = httpRequest.Headers.Wrap(); propagatedContext = SpanContextPropagator.Instance.Extract(headers); tagsFromHeaders = SpanContextPropagator.Instance.ExtractHeaderTags(headers, tracer.Settings.HeaderTags); } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } string host = httpRequest.Headers.Get("Host"); string httpMethod = httpRequest.HttpMethod.ToUpperInvariant(); string url = httpRequest.RawUrl.ToLowerInvariant(); string path = UriHelpers.GetRelativeUrl(httpRequest.Url, tryRemoveIds: true); string resourceName = $"{httpMethod} {path.ToLowerInvariant()}"; var tags = new WebTags(); scope = tracer.StartActiveWithTags(_requestOperationName, propagatedContext, tags: tags); scope.Span.DecorateWebServerSpan(resourceName, httpMethod, host, url, tags, tagsFromHeaders); tags.SetAnalyticsSampleRate(IntegrationId, tracer.Settings, enabledWithGlobalSetting: true); httpContext.Items[_httpContextScopeKey] = scope; // Decorate the incoming HTTP Request with distributed tracing headers // in case the next processor cannot access the stored Scope // (e.g. WCF being hosted in IIS) SpanContextPropagator.Instance.Inject(scope.Span.Context, httpRequest.Headers.Wrap()); } catch (Exception ex) { // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case... scope?.Dispose(); Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error"); } }
private static void UpdateSpan(dynamic controllerContext, Span span, IEnumerable <KeyValuePair <string, string> > headerTags) { try { var req = controllerContext?.Request; string host = req?.Headers?.Host ?? string.Empty; string rawUrl = req?.RequestUri?.ToString().ToLowerInvariant() ?? string.Empty; string absoluteUri = req?.RequestUri?.AbsoluteUri?.ToLowerInvariant() ?? string.Empty; string method = controllerContext?.Request?.Method?.Method?.ToUpperInvariant() ?? "GET"; string route = null; try { route = controllerContext?.RouteData?.Route?.RouteTemplate; } catch { } string resourceName = $"{method} {absoluteUri.ToLowerInvariant()}"; if (route != null) { resourceName = $"{method} {route.ToLowerInvariant()}"; } else if (req?.RequestUri != null) { var cleanUri = UriHelpers.GetRelativeUrl(req?.RequestUri, tryRemoveIds: true); resourceName = $"{method} {cleanUri.ToLowerInvariant()}"; } string controller = string.Empty; string action = string.Empty; try { if (controllerContext?.RouteData?.Values is IDictionary <string, object> routeValues) { controller = (routeValues.GetValueOrDefault("controller") as string)?.ToLowerInvariant(); action = (routeValues.GetValueOrDefault("action") as string)?.ToLowerInvariant(); } } catch { } // Fail safe to catch templates in routing values resourceName = resourceName .Replace("{controller}", controller) .Replace("{action}", action); span.DecorateWebServerSpan( resourceName: resourceName, method: method, host: host, httpUrl: rawUrl, tags: headerTags); span.SetTag(Tags.AspNetAction, action); span.SetTag(Tags.AspNetController, controller); span.SetTag(Tags.AspNetRoute, route); } catch (Exception ex) { Log.Error(ex, "Error populating scope data."); } }