/// <summary> /// Creates a span context for outbound http requests, or get the active one. /// Used to propagate headers without changing the active span. /// </summary> /// <param name="tracer">The tracer instance to use to create the span.</param> /// <param name="httpMethod">The HTTP method used by the request.</param> /// <param name="requestUri">The URI requested by the request.</param> /// <param name="integrationName">The name of the integration creating this scope.</param> /// <returns>A span context to use to populate headers</returns> public static SpanContext CreateHttpSpanContext( Tracer tracer, string httpMethod, Uri requestUri, string integrationName) { if (!tracer.Settings.IsIntegrationEnabled(integrationName)) { // integration disabled, skip this trace return(null); } try { var activeScope = GetActiveHttpScope(tracer, httpMethod, requestUri); if (activeScope != null) { // This HTTP request was already instrumented return the active HTTP context. return(activeScope.Span.Context); } return(tracer.CreateSpanContext(out bool _)); } catch (Exception ex) { Log.Error(ex, "Error creating or populating span context."); } return(null); }
public static object ExecuteAsyncGeneric( object wireProtocol, object connection, object cancellationTokenSource, int opCode, int mdToken, long moduleVersionPtr) { // The generic type for this method comes from the declaring type of wireProtocol if (wireProtocol == null) { throw new ArgumentNullException(nameof(wireProtocol)); } var tokenSource = cancellationTokenSource as CancellationTokenSource; var cancellationToken = tokenSource?.Token ?? CancellationToken.None; var wireProtocolType = wireProtocol.GetType(); var wireProtocolGenericArgs = GetGenericsFromWireProtocol(wireProtocolType); const string methodName = nameof(ExecuteAsync); Func <object, object, CancellationToken, object> executeAsync; try { executeAsync = MethodBuilder <Func <object, object, CancellationToken, object> > .Start(moduleVersionPtr, mdToken, opCode, methodName) .WithConcreteType(wireProtocolType) .WithDeclaringTypeGenerics(wireProtocolGenericArgs) .WithParameters(connection, cancellationToken) .WithNamespaceAndNameFilters(ClrNames.GenericTask, "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken) .Build(); } catch (Exception ex) { // profiled app will not continue working as expected without this method Log.Error(ex, $"Error resolving {wireProtocolType.Name}.{methodName}(IConnection connection, CancellationToken cancellationToken)"); throw; } return(AsyncHelper.InvokeGenericTaskDelegate( wireProtocolType, wireProtocolGenericArgs[0], nameof(ExecuteAsyncInternalGeneric), typeof(MongoDbIntegration), wireProtocol, connection, cancellationToken, executeAsync)); }
private static SpanContext ExtractPropagatedContext(IPropagator propagator, HttpRequest request) { try { // extract propagation details from http headers var requestHeaders = request.Headers; if (requestHeaders != null) { var headersCollection = new DictionaryHeadersCollection(); foreach (var header in requestHeaders) { string key = header.Key; string[] values = header.Value.ToArray(); if (key != null && values.Length > 0) { headersCollection.Add(key, values); } } return(propagator.Extract(headersCollection)); } } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } return(null); }
/// <summary> /// Gets a <see cref="ConcurrentDictionary{TKey, TValue}"/> containing all of the values. /// </summary> /// <remarks> /// Example JSON where `globalTags` is the configuration key. /// { /// "globalTags": { /// "name1": "value1", /// "name2": "value2" /// } /// } /// </remarks> /// <param name="key">The key that identifies the setting.</param> /// <returns><see cref="IDictionary{TKey, TValue}"/> containing all of the key-value pairs.</returns> /// <exception cref="JsonReaderException">Thrown if the configuration value is not a valid JSON string.</exception>" public IDictionary <string, string> GetDictionary(string key) { var token = _configuration.SelectToken(key, errorWhenNoMatch: false); if (token == null) { return(null); } if (token.Type == JTokenType.Object) { try { var dictionary = token ?.ToObject <ConcurrentDictionary <string, string> >(); return(dictionary); } catch (Exception e) { Log.Error(e, "Unable to parse configuration value for {0} as key-value pairs of strings.", key); return(null); } } return(StringConfigurationSource.ParseCustomKeyValues(token.ToString())); }
private async Task FlushTracesTaskLoopAsync() { while (true) { try { await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(1)), _processExit.Task) .ConfigureAwait(false); if (_processExit.Task.IsCompleted) { await FlushTracesAsync().ConfigureAwait(false); return; } else { await FlushTracesAsync().ConfigureAwait(false); } } catch (Exception ex) { Log.Error(ex, "An unhandled error occurred during the flushing task"); } } }
public async Task SendTracesAsync(Span[][] traces) { // retry up to 5 times with exponential back-off var retryLimit = 5; var retryCount = 1; var sleepDuration = 100; // in milliseconds while (true) { HttpResponseMessage responseMessage; try { // re-create content on every retry because some versions of HttpClient always dispose of it, so we can't reuse. using (var content = new ZipkinContent(traces, _settings)) { responseMessage = await _client.PostAsync(_settings.EndpointUrl, content).ConfigureAwait(false); responseMessage.EnsureSuccessStatusCode(); return; } } catch (Exception ex) { if (ex.InnerException is InvalidOperationException ioe) { Log.Error("A fatal error occurred while sending traces to {Endpoint}\n{Exception}", _settings.EndpointUrl, ex.Message); return; } if (retryCount >= retryLimit) { // stop retrying Log.Error("No more retries to send traces to {Endpoint}\n{Exception}", _settings.EndpointUrl, ex.Message); return; } Log.Debug("Error sending traces to {Endpoint}\n{Exception}", _settings.EndpointUrl, ex.Message); // retry await Task.Delay(sleepDuration).ConfigureAwait(false); retryCount++; sleepDuration *= 2; } } }
private 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); } var tracer = Tracer.Instance; var request = controllerContext.GetProperty <HttpRequestMessage>("Request").GetValueOrDefault(); SpanContext propagatedContext = null; if (request != null && tracer.ActiveScope == null) { try { // extract propagated http headers var headers = request.Headers.Wrap(); propagatedContext = B3SpanContextPropagator.Instance.Extract(headers); } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } scope = tracer.StartActive(OperationName, propagatedContext); UpdateSpan(controllerContext, scope.Span); // set analytics sample rate if enabled var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate); } catch (Exception ex) { Log.Error(ex, "Error creating scope."); } return(scope); }
void IObserver <KeyValuePair <string, object> > .OnNext(KeyValuePair <string, object> value) { try { OnNext(value.Key, value.Value); } catch (Exception ex) { Log.Error(ex, "Event Exception: {0}", value.Key); } }
public static int ExecuteNonQuery( object command, int opCode, int mdToken, long moduleVersionPtr) { Func <DbCommand, int> instrumentedMethod; try { instrumentedMethod = MethodBuilder <Func <DbCommand, int> > .Start(moduleVersionPtr, mdToken, opCode, AdoNetConstants.MethodNames.ExecuteNonQuery) .WithConcreteType(typeof(DbCommand)) .WithNamespaceAndNameFilters(ClrNames.Int32) .Build(); } catch (Exception ex) { Log.Error(ex, $"Error resolving {DbCommandTypeName}.{AdoNetConstants.MethodNames.ExecuteNonQuery}(...)"); throw; } var dbCommand = command as DbCommand; using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) { try { return(instrumentedMethod(dbCommand)); } catch (Exception ex) { scope?.Span.SetException(ex); throw; } } }
public static Module Get(Guid moduleVersionId) { // First attempt at cached values with no blocking if (_modules.TryGetValue(moduleVersionId, out Module value)) { return(value); } // Block if a population event is happening _populationResetEvent.Wait(); // See if the previous population event populated what we need if (_modules.TryGetValue(moduleVersionId, out value)) { return(value); } if (_failures >= MaxFailures) { // For some unforeseeable reason we have failed on a lot of AppDomain lookups if (!_shortCircuitLogicHasLogged) { Log.Warning("Datadog is unable to continue attempting module lookups for this AppDomain. Falling back to legacy method lookups."); } return(null); } // Block threads on this event _populationResetEvent.Reset(); try { PopulateModules(); } catch (Exception ex) { _failures++; Log.Error(ex, "Error when populating modules."); } finally { // Continue threads blocked on this event _populationResetEvent.Set(); } _modules.TryGetValue(moduleVersionId, out value); return(value); }
/// <summary> /// Gets an "application name" for the executing application by looking at /// the hosted app name (.NET Framework on IIS only), assembly name, and process name. /// </summary> /// <returns>The default service name.</returns> private static string GetApplicationName() { try { #if !NETSTANDARD2_0 // System.Web.dll is only available on .NET Framework if (System.Web.Hosting.HostingEnvironment.IsHosted) { // if this app is an ASP.NET application, return "SiteName/ApplicationVirtualPath". // note that ApplicationVirtualPath includes a leading slash. return((System.Web.Hosting.HostingEnvironment.SiteName + System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath).TrimEnd('/')); } #endif return(Assembly.GetEntryAssembly()?.GetName().Name ?? Process.GetCurrentProcess().ProcessName); } catch (Exception ex) { Log.Error(ex, "Error creating default service name."); return(null); } }
private string CompileResourceId() { string resourceId = null; try { var success = true; if (SubscriptionId == null) { success = false; Log.Warning("Could not successfully retrieve the subscription ID from variable: {0}", WebsiteOwnerNameKey); } if (SiteName == null) { success = false; Log.Warning("Could not successfully retrieve the deployment ID from variable: {0}", SiteNameKey); } if (ResourceGroup == null) { success = false; Log.Warning("Could not successfully retrieve the resource group name from variable: {0}", ResourceGroupKey); } if (success) { resourceId = $"/subscriptions/{SubscriptionId}/resourcegroups/{ResourceGroup}/providers/microsoft.web/sites/{SiteName}".ToLowerInvariant(); } } catch (Exception ex) { Log.Error(ex, "Could not successfully setup the resource id for azure app services."); } return(resourceId); }
internal static Scope CreateScope(Tracer tracer, string integrationName, string componentName, string host, string port, string rawCommand) { if (!Tracer.Instance.Settings.IsIntegrationEnabled(integrationName)) { // integration disabled, don't create a scope, skip this trace return(null); } Scope scope = null; try { int separatorIndex = rawCommand.IndexOf(' '); string command; if (separatorIndex >= 0) { command = rawCommand.Substring(0, separatorIndex); } else { command = rawCommand; } scope = tracer.StartActive(command ?? OperationName, serviceName: tracer.DefaultServiceName); var span = scope.Span; span.SetTag(Tags.InstrumentationName, componentName); span.SetTag(Tags.DbType, SpanTypes.Redis); span.SetTag(Tags.SpanKind, SpanKinds.Client); if (Tracer.Instance.Settings.TagRedisCommands) { span.SetTag(Tags.DbStatement, rawCommand); } span.SetTag(Tags.OutHost, host); span.SetTag(Tags.OutPort, port); // set analytics sample rate if enabled var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false); span.SetMetric(Tags.Analytics, analyticsSampleRate); } catch (Exception ex) { Log.Error(ex, "Error creating or populating scope."); } return(scope); }
public static Scope CreateScope(Tracer tracer, string integrationName, object pipeline, object requestData) { if (!tracer.Settings.IsIntegrationEnabled(integrationName)) { // integration disabled, don't create a scope, skip this trace return(null); } string requestName = pipeline.GetProperty("RequestParameters") .GetValueOrDefault() ?.GetType() .Name .Replace("RequestParameters", string.Empty); var pathAndQuery = requestData.GetProperty <string>("PathAndQuery").GetValueOrDefault() ?? requestData.GetProperty <string>("Path").GetValueOrDefault(); string method = requestData.GetProperty("Method").GetValueOrDefault()?.ToString(); var url = requestData.GetProperty("Uri").GetValueOrDefault()?.ToString(); Scope scope = null; try { var operationName = requestName ?? OperationName; scope = tracer.StartActive(operationName, serviceName: tracer.DefaultServiceName); var span = scope.Span; span.SetTag(Tags.InstrumentationName, ComponentValue); span.SetTag(Tags.DbType, SpanType); span.SetTag(Tags.SpanKind, SpanKinds.Client); span.SetTag(ElasticsearchMethodKey, method); span.SetTag(ElasticsearchUrlKey, url); // set analytics sample rate if enabled var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false); span.SetMetric(Tags.Analytics, analyticsSampleRate); } catch (Exception ex) { Log.Error(ex, "Error creating or populating scope."); } return(scope); }
public static void ErrorRetrievingMethod( this SignalFx.Tracing.Vendors.Serilog.ILogger logger, Exception exception, long moduleVersionPointer, int mdToken, int opCode, string instrumentedType, string methodName, string instanceType = null, string[] relevantArguments = null) { var instrumentedMethod = $"{instrumentedType}.{methodName}(...)"; if (instanceType != null) { instrumentedMethod = $"{instrumentedMethod} on {instanceType}"; } if (relevantArguments != null) { instrumentedMethod = $"{instrumentedMethod} with {string.Join(", ", relevantArguments)}"; } var moduleVersionId = PointerHelpers.GetGuidFromNativePointer(moduleVersionPointer); logger.Error( exception, $"Error (MVID: {moduleVersionId}, mdToken: {mdToken}, opCode: {opCode}) could not retrieve: {instrumentedMethod}"); var statsd = Tracer.Instance.Statsd; if (statsd != null) { string[] tags = { $"instrumented-method:{instrumentedMethod}" }; statsd.AppendException(exception, source: instrumentedType, message: "Error retrieving instrumented method", tags); statsd.Send(); } }
public static object Validate( object documentValidator, object originalQuery, object schema, object document, object rules, object userContext, object inputs, int opCode, int mdToken, long moduleVersionPtr) { if (documentValidator == null) { throw new ArgumentNullException(nameof(documentValidator)); } const string methodName = nameof(Validate); // At runtime, get a Type object for GraphQL.ExecutionResult var documentValidatorInstanceType = documentValidator.GetType(); try { var graphQLAssembly = AppDomain.CurrentDomain .GetAssemblies() .Single(a => a.GetName().Name.Equals(GraphQLAssemblyName)); } catch (Exception ex) { // This shouldn't happen because the GraphQL assembly should have been loaded to construct various other types // profiled app will not continue working as expected without this method Log.Error(ex, $"Error finding types in the GraphQL assembly."); throw; } Func <object, object, object, object, object, object, object, object> instrumentedMethod; try { instrumentedMethod = MethodBuilder <Func <object, object, object, object, object, object, object, object> > .Start(moduleVersionPtr, mdToken, opCode, methodName) .WithConcreteType(documentValidatorInstanceType) .WithParameters(originalQuery, schema, document, rules, userContext, inputs) .WithNamespaceAndNameFilters( GraphQLValidationResultInterfaceName, ClrNames.String, "GraphQL.Types.ISchema", "GraphQL.Language.AST.Document", "System.Collections.Generic.IEnumerable`1", ClrNames.Ignore, "GraphQL.Inputs") .Build(); } catch (Exception ex) { Log.ErrorRetrievingMethod( exception: ex, moduleVersionPointer: moduleVersionPtr, mdToken: mdToken, opCode: opCode, instrumentedType: GraphQLDocumentValidatorInterfaceName, methodName: methodName, instanceType: documentValidator.GetType().AssemblyQualifiedName); throw; } using (var scope = CreateScopeFromValidate(document)) { try { var validationResult = instrumentedMethod(documentValidator, originalQuery, schema, document, rules, userContext, inputs); RecordExecutionErrorsIfPresent(scope.Span, "GraphQL.Validation.ValidationError", validationResult.GetProperty("Errors").GetValueOrDefault()); return(validationResult); } catch (Exception ex) { scope?.Span.SetException(ex); throw; } } }
private static Scope CreateScope(RequestContext requestContext) { var requestMessage = requestContext?.RequestMessage; if (requestMessage == null) { return(null); } var tracer = Tracer.Instance; if (!tracer.Settings.IsIntegrationEnabled(IntegrationName)) { // integration disabled, don't create a scope, skip this trace return(null); } Scope scope = null; try { SpanContext propagatedContext = null; string host = null; string httpMethod = null; if (requestMessage.Properties.TryGetValue("httpRequest", out var httpRequestProperty) && httpRequestProperty is HttpRequestMessageProperty httpRequestMessageProperty) { // we're using an http transport host = httpRequestMessageProperty.Headers[HttpRequestHeader.Host]; httpMethod = httpRequestMessageProperty.Method?.ToUpperInvariant(); // try to extract propagated context values from http headers if (tracer.ActiveScope == null) { try { var headers = httpRequestMessageProperty.Headers.Wrap(); propagatedContext = B3SpanContextPropagator.Instance.Extract(headers); } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } } var operationNameSuffix = requestMessage.Headers.Action ?? requestMessage.Headers.To?.LocalPath; var operationName = !string.IsNullOrEmpty(operationNameSuffix) ? "wcf.request " + operationNameSuffix : "wcf.request"; scope = tracer.StartActive(operationName, propagatedContext); var span = scope.Span; span.DecorateWebServerSpan( resourceName: null, httpMethod, host, httpUrl: requestMessage.Headers.To?.AbsoluteUri); // 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."); } // always returns the scope, even if it's null return(scope); }
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 = B3SpanContextPropagator.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); IPAddress remoteIp = null; if (Tracer.Instance.Settings.AddClientIpToServerSpans) { IPAddress.TryParse(httpRequest.UserHostAddress, out remoteIp); } scope.Span.DecorateWebServerSpan(resourceName, httpMethod, host, url, remoteIp); // 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"); } }
/// <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; if (tracer.ActiveScope == null) { try { // extract propagated http headers var headers = httpContext.Request.Headers.Wrap(); propagatedContext = tracer.Propagator.Extract(headers); } 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); IPAddress remoteIp = null; if (Tracer.Instance.Settings.AddClientIpToServerSpans) { IPAddress.TryParse(httpContext.Request.UserHostAddress, out remoteIp); } span.DecorateWebServerSpan( resourceName: resourceName, method: httpMethod, host: host, httpUrl: url, remoteIp: remoteIp); 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 AspNetAmbientContext(string integrationName, object httpContext) { try { Tracer = Tracer.Instance; _httpContext = httpContext; var request = _httpContext.GetProperty("Request").GetValueOrDefault(); var response = _httpContext.GetProperty("Response").GetValueOrDefault(); GetTagValues( request, out string absoluteUri, out string httpMethod, out string host, out string resourceName); if (httpMethod == StartupDiagnosticMethod) { // An initial diagnostic HttpContext is created on the start of many web applications AbortRegistration = true; return; } RegisterForDisposalWithPipeline(response, this); SpanContext propagatedContext = null; if (Tracer.ActiveScope == null) { try { // extract propagated http headers var requestHeaders = request.GetProperty <IEnumerable>("Headers").GetValueOrDefault(); if (requestHeaders != null) { var headersCollection = new DictionaryHeadersCollection(); foreach (object header in requestHeaders) { var key = header.GetProperty <string>("Key").GetValueOrDefault(); var values = header.GetProperty <IList <string> >("Value").GetValueOrDefault(); if (key != null && values != null) { headersCollection.Add(key, values); } } propagatedContext = B3SpanContextPropagator.Instance.Extract(headersCollection); } } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } _rootScope = Tracer.StartActive(TopLevelOperationName, propagatedContext); RegisterForDisposal(_rootScope); var span = _rootScope.Span; IPAddress remoteIp = null; if (Tracer.Instance.Settings.AddClientIpToServerSpans) { var userHostAddress = request.GetProperty <string>("UserHostAddress").GetValueOrDefault(); IPAddress.TryParse(userHostAddress, out remoteIp); } span.DecorateWebServerSpan( resourceName: resourceName, method: httpMethod, host: host, httpUrl: absoluteUri, remoteIp: remoteIp); var statusCode = response.GetProperty <int>("StatusCode"); if (statusCode.HasValue) { span.SetTag(Tags.HttpStatusCode, statusCode.Value.ToString()); } var analyticSampleRate = Tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: true); span.SetMetric(Tags.Analytics, analyticSampleRate); } catch (Exception ex) { // Don't crash client apps Log.Error(ex, $"Exception when initializing {nameof(AspNetAmbientContext)}."); } }