public async ValueTask <int> TrackAsync(IEnumerable <TelemetryItem> telemetryItems, bool async, CancellationToken cancellationToken) { // Prevent Azure Monitor's HTTP operations from being instrumented. using var scope = SuppressInstrumentationScope.Begin(); if (cancellationToken.IsCancellationRequested) { return(0); } Azure.Response <TrackResponse> response = null; try { if (async) { response = await this.applicationInsightsRestClient.InternalTrackAsync(telemetryItems, cancellationToken).ConfigureAwait(false); } else { response = this.applicationInsightsRestClient.InternalTrackAsync(telemetryItems, cancellationToken).Result; } } catch (Exception ex) { // TODO: Log the exception to new event source. If we get a common logger we could just log exception to it. AzureMonitorTraceExporterEventSource.Log.FailedExport(ex); } return(response == null ? 0 : response.Value.ItemsAccepted.GetValueOrDefault()); }
public void TracerSdkSetsActivityDataRequestedToFalseWhenSuppressInstrumentationIsTrueForLegacyActivity() { using TestActivityProcessor testActivityProcessor = new TestActivityProcessor(); bool startCalled = false; bool endCalled = false; testActivityProcessor.StartAction = (a) => { startCalled = true; }; testActivityProcessor.EndAction = (a) => { endCalled = true; }; using var openTelemetry = Sdk.CreateTracerProviderBuilder() .AddLegacySource("random") .AddProcessor(testActivityProcessor) .SetSampler(new AlwaysOnSampler()) .Build(); using (SuppressInstrumentationScope.Begin(true)) { using var activity = new Activity("random").Start(); Assert.False(activity.IsAllDataRequested); } Assert.False(startCalled); Assert.False(endCalled); }
public override void OnStartActivity(Activity activity, object payload) { var uri = this.uriFetcher.Fetch(payload); if (uri == null) { ElasticsearchInstrumentationEventSource.Log.NullPayload(nameof(ElasticsearchRequestPipelineDiagnosticListener), nameof(this.OnStartActivity)); return; } var method = this.methodFetcher.Fetch(payload); activity.DisplayName = this.GetDisplayName(activity, method); this.activitySource.Start(activity, ActivityKind.Client); if (this.options.SuppressDownstreamInstrumentation) { SuppressInstrumentationScope.Enter(); } if (!activity.IsAllDataRequested) { return; } var elasticIndex = this.GetElasticIndex(uri); activity.DisplayName = this.GetDisplayName(activity, method, elasticIndex); activity.SetTag(Constants.AttributeDbSystem, "elasticsearch"); if (elasticIndex != null) { activity.SetTag(Constants.AttributeDbName, elasticIndex); } var uriHostNameType = Uri.CheckHostName(uri.Host); if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6) { activity.SetTag(Constants.AttributeNetPeerIp, uri.Host); } else { activity.SetTag(Constants.AttributeNetPeerName, uri.Host); } if (uri.Port > 0) { activity.SetTag(Constants.AttributeNetPeerPort, uri.Port); } if (method != null) { activity.SetTag(Constants.AttributeDbMethod, method.ToString()); } activity.SetTag(Constants.AttributeDbUrl, uri.OriginalString); }
private void Application_BeginRequest(object sender, EventArgs e) { var context = ((HttpApplication)sender).Context; if (context.Request.QueryString["suppress"] == "true") { this.suppressionScope = SuppressInstrumentationScope.Begin(); } }
public override void OnStartActivity(Activity activity, object payload) { if (!this.startRequestFetcher.TryFetch(payload, out HttpRequestMessage request) || request == null) { GrpcInstrumentationEventSource.Log.NullPayload(nameof(GrpcClientDiagnosticListener), nameof(this.OnStartActivity)); return; } if (this.options.SuppressDownstreamInstrumentation) { SuppressInstrumentationScope.Enter(); } var grpcMethod = GrpcTagHelper.GetGrpcMethodFromActivity(activity); activity.DisplayName = grpcMethod?.Trim('/'); this.activitySource.Start(activity, ActivityKind.Client); if (activity.IsAllDataRequested) { try { this.options.Enrich?.Invoke(activity, "OnStartActivity", request); } catch (Exception ex) { GrpcInstrumentationEventSource.Log.EnrichmentException(ex); } activity.SetTag(SemanticConventions.AttributeRpcSystem, GrpcTagHelper.RpcSystemGrpc); if (GrpcTagHelper.TryParseRpcServiceAndRpcMethod(grpcMethod, out var rpcService, out var rpcMethod)) { activity.SetTag(SemanticConventions.AttributeRpcService, rpcService); activity.SetTag(SemanticConventions.AttributeRpcMethod, rpcMethod); // Remove the grpc.method tag added by the gRPC .NET library activity.SetTag(GrpcTagHelper.GrpcMethodTagName, null); } var uriHostNameType = Uri.CheckHostName(request.RequestUri.Host); if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6) { activity.SetTag(SemanticConventions.AttributeNetPeerIp, request.RequestUri.Host); } else { activity.SetTag(SemanticConventions.AttributeNetPeerName, request.RequestUri.Host); } activity.SetTag(SemanticConventions.AttributeNetPeerPort, request.RequestUri.Port); } }
public void DecrementIfTriggeredOnlyWorksInReferenceCountingMode() { // Instrumentation is not suppressed, DecrementIfTriggered is a no op Assert.False(OpenTelemetrySdk.SuppressInstrumentation); SuppressInstrumentationScope.DecrementIfTriggered(); Assert.False(OpenTelemetrySdk.SuppressInstrumentation); // Instrumentation is suppressed in reference counting mode, DecrementIfTriggered should work SuppressInstrumentationScope.Enter(); Assert.True(OpenTelemetrySdk.SuppressInstrumentation); SuppressInstrumentationScope.DecrementIfTriggered(); Assert.False(OpenTelemetrySdk.SuppressInstrumentation); // Instrumentation is not suppressed anymore }
public async void SuppressInstrumentationScopeEnterIsLocalToAsyncFlow() { Assert.False(OpenTelemetrySdk.SuppressInstrumentation); // SuppressInstrumentationScope.Enter called inside the task is only applicable to this async flow await Task.Factory.StartNew(() => { Assert.False(OpenTelemetrySdk.SuppressInstrumentation); SuppressInstrumentationScope.Enter(); Assert.True(OpenTelemetrySdk.SuppressInstrumentation); }); Assert.False(OpenTelemetrySdk.SuppressInstrumentation); // Changes made by SuppressInstrumentationScope.Enter in the task above are not reflected here as it's not part of the same async flow }
public void SuppressInstrumentationBeginTest(bool?shouldBegin) { Assert.False(OpenTelemetrySdk.SuppressInstrumentation); using var scope = shouldBegin.HasValue ? SuppressInstrumentationScope.Begin(shouldBegin.Value) : SuppressInstrumentationScope.Begin(); if (shouldBegin.HasValue) { Assert.Equal(shouldBegin.Value, OpenTelemetrySdk.SuppressInstrumentation); } else { Assert.True(OpenTelemetrySdk.SuppressInstrumentation); // Default behavior is to pass true and suppress the instrumentation } }
public void OnNext(KeyValuePair <string, object> value) { if (!this.handler.SupportsNullActivity && Activity.Current == null) { if (!Sdk.SuppressInstrumentation) { InstrumentationEventSource.Log.NullActivity(value.Key); } return; } try { if (value.Key.EndsWith("Start", StringComparison.Ordinal)) { if (SuppressInstrumentationScope.IncrementIfTriggered() == 0) { this.handler.OnStartActivity(Activity.Current, value.Value); } } else if (value.Key.EndsWith("Stop", StringComparison.Ordinal)) { if (SuppressInstrumentationScope.DecrementIfTriggered() == 0) { this.handler.OnStopActivity(Activity.Current, value.Value); } } else if (value.Key.EndsWith("Exception", StringComparison.Ordinal)) { if (!Sdk.SuppressInstrumentation) { this.handler.OnException(Activity.Current, value.Value); } } else { if (!Sdk.SuppressInstrumentation) { this.handler.OnCustom(value.Key, Activity.Current, value.Value); } } } catch (Exception ex) { InstrumentationEventSource.Log.UnknownErrorProcessingEvent(this.handler?.SourceName, value.Key, ex); } }
public override Task <ExportResult> ExportAsync( IEnumerable <Activity> batch, CancellationToken cancellationToken) { // Exporter code which can generate further // telemetry should do so inside SuppressInstrumentation // scope. This suppresses telemetry from // exporter's own code to avoid live-loop situation. using var scope = SuppressInstrumentationScope.Begin(); foreach (var activity in batch) { Console.WriteLine($"{activity.DisplayName}"); } return(Task.FromResult(ExportResult.Success)); }
public void IncrementIfTriggeredOnlyWorksInReferenceCountingMode() { // Instrumentation is not suppressed, IncrementIfTriggered is a no op Assert.False(OpenTelemetrySdk.SuppressInstrumentation); SuppressInstrumentationScope.IncrementIfTriggered(); Assert.False(OpenTelemetrySdk.SuppressInstrumentation); // Instrumentation is suppressed in reference counting mode, IncrementIfTriggered should work SuppressInstrumentationScope.Enter(); SuppressInstrumentationScope.IncrementIfTriggered(); Assert.True(OpenTelemetrySdk.SuppressInstrumentation); SuppressInstrumentationScope.DecrementIfTriggered(); Assert.True(OpenTelemetrySdk.SuppressInstrumentation); // Instrumentation is still suppressed as IncrementIfTriggered incremented the slot count after Enter, need to decrement the slot count again to enable instrumentation SuppressInstrumentationScope.DecrementIfTriggered(); Assert.False(OpenTelemetrySdk.SuppressInstrumentation); // Instrumentation is not suppressed anymore }
public void TracerSdkSetsActivitySamplingResultToNoneWhenSuppressInstrumentationIsTrue() { using var scope = SuppressInstrumentationScope.Begin(); var testSampler = new TestSampler(); using var activitySource = new ActivitySource(ActivitySourceName); using var sdk = Sdk.CreateTracerProviderBuilder() .AddSource(ActivitySourceName) .SetSampler(testSampler) .Build(); using (var activity = activitySource.StartActivity("root")) { Assert.Null(activity); } }
public void ListenerHandlerIsNotInvokedWhenSuppressInstrumentationTrue(bool suppressInstrumentation) { using var scope = SuppressInstrumentationScope.Begin(suppressInstrumentation); var activity = new Activity("Main"); this.diagnosticSource.StartActivity(activity, null); this.diagnosticSource.StopActivity(activity, null); if (suppressInstrumentation) { Assert.Equal(0, this.testListenerHandler.OnStartInvokedCount); Assert.Equal(0, this.testListenerHandler.OnStopInvokedCount); } else { Assert.Equal(1, this.testListenerHandler.OnStartInvokedCount); Assert.Equal(1, this.testListenerHandler.OnStopInvokedCount); } }
public int Send(byte[] buffer, int offset, int count) { // Prevent Jaeger's HTTP operations from being instrumented. using var scope = SuppressInstrumentationScope.Begin(); using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "/api/traces"); request.Content = new ByteArrayContent(buffer, offset, count) { Headers = { ContentType = ContentTypeHeader }, }; #if NET5_0_OR_GREATER using HttpResponseMessage response = this.httpClient.Send(request); #else using HttpResponseMessage response = this.httpClient.SendAsync(request).GetAwaiter().GetResult(); #endif response.EnsureSuccessStatusCode(); return(count); }
public async Task ShouldMapMassTransitTagsWhenIntrumentationIsSuppressed() { var activityProcessor = new Mock <BaseProcessor <Activity> >(); using (Sdk.CreateTracerProviderBuilder() .AddProcessor(activityProcessor.Object) .AddMassTransitInstrumentation() .Build()) { var harness = new InMemoryTestHarness(); var consumerHarness = harness.Consumer <TestConsumer>(); var handlerHarness = harness.Handler <TestMessage>(); using var scope = SuppressInstrumentationScope.Begin(); await harness.Start(); try { await harness.InputQueueSendEndpoint.Send <TestMessage>(new { Text = "Hello, world!" }); Assert.True(await harness.Consumed.SelectAsync <TestMessage>().Any()); Assert.True(await consumerHarness.Consumed.SelectAsync <TestMessage>().Any()); Assert.True(await handlerHarness.Consumed.SelectAsync().Any()); } finally { await harness.Stop(); } var expectedMessageContext = harness.Sent.Select <TestMessage>().FirstOrDefault()?.Context; Assert.NotNull(expectedMessageContext); } // Since instrumentation is suppressed, activiy is not emitted Assert.Equal(3, activityProcessor.Invocations.Count); // SetParentProvider + OnShutdown + Dispose // Processor.OnStart and Processor.OnEnd are not called Assert.DoesNotContain(activityProcessor.Invocations, invo => invo.Method.Name == nameof(activityProcessor.Object.OnStart)); Assert.DoesNotContain(activityProcessor.Invocations, invo => invo.Method.Name == nameof(activityProcessor.Object.OnEnd)); }
public static void UsingSuppressInstrumentation() { Assert.False(Sdk.SuppressInstrumentation); using (var scope = SuppressInstrumentationScope.Begin()) { Assert.True(Sdk.SuppressInstrumentation); using (var innerScope = SuppressInstrumentationScope.Begin()) { innerScope.Dispose(); Assert.True(Sdk.SuppressInstrumentation); scope.Dispose(); } Assert.False(Sdk.SuppressInstrumentation); } Assert.False(Sdk.SuppressInstrumentation); }
private Activity ProcessBeginRequest(IExecutionContext executionContext) { Activity activity = null; var requestContext = executionContext.RequestContext; var service = this.GetAWSServiceName(requestContext); var operation = this.GetAWSOperationName(requestContext); activity = AWSSDKActivitySource.StartActivity(service + "." + operation, ActivityKind.Client); if (activity == null) { return(null); } if (this.options.SuppressDownstreamInstrumentation) { SuppressInstrumentationScope.Enter(); } if (activity.IsAllDataRequested) { activity.SetTag(AWSSemanticConventions.AttributeAWSServiceName, service); activity.SetTag(AWSSemanticConventions.AttributeAWSOperationName, operation); var client = executionContext.RequestContext.ClientConfig; if (client != null) { var region = client.RegionEndpoint?.SystemName; activity.SetTag(AWSSemanticConventions.AttributeAWSRegion, region ?? AWSSDKUtils.DetermineRegion(client.ServiceURL)); } this.AddRequestSpecificInformation(activity, requestContext, service); } AwsPropagator.Inject(new PropagationContext(activity.Context, Baggage.Current), requestContext.Request.Headers, Setter); return(activity); }
private IDisposable SuppressDownstreamInstrumentation() { return(WcfInstrumentationActivitySource.Options?.SuppressDownstreamInstrumentation ?? false ? SuppressInstrumentationScope.Begin() : null); }
public override void OnStartActivity(Activity activity, object payload) { // By this time, samplers have already run and // activity.IsAllDataRequested populated accordingly. if (Sdk.SuppressInstrumentation) { return; } if (activity.IsAllDataRequested) { var uri = this.uriFetcher.Fetch(payload); if (uri == null) { ElasticsearchInstrumentationEventSource.Log.NullPayload(nameof(ElasticsearchRequestPipelineDiagnosticListener), nameof(this.OnStartActivity)); return; } ActivityInstrumentationHelper.SetActivitySourceProperty(activity, ActivitySource); ActivityInstrumentationHelper.SetKindProperty(activity, ActivityKind.Client); var method = this.methodFetcher.Fetch(payload); if (this.options.SuppressDownstreamInstrumentation) { SuppressInstrumentationScope.Enter(); } var elasticIndex = this.GetElasticIndex(uri); activity.DisplayName = this.GetDisplayName(activity, method, elasticIndex); activity.SetTag(SemanticConventions.AttributeDbSystem, DatabaseSystemName); if (elasticIndex != null) { activity.SetTag(SemanticConventions.AttributeDbName, elasticIndex); } var uriHostNameType = Uri.CheckHostName(uri.Host); if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6) { activity.SetTag(SemanticConventions.AttributeNetPeerIp, uri.Host); } else { activity.SetTag(SemanticConventions.AttributeNetPeerName, uri.Host); } if (uri.Port > 0) { activity.SetTag(SemanticConventions.AttributeNetPeerPort, uri.Port); } if (method != null) { activity.SetTag(AttributeDbMethod, method.ToString()); } activity.SetTag(SemanticConventions.AttributeDbUrl, uri.OriginalString); try { this.options.Enrich?.Invoke(activity, "OnStartActivity", payload); } catch (Exception ex) { ElasticsearchInstrumentationEventSource.Log.EnrichmentException(ex); } } }
internal TracerProviderSdk( Resource resource, IEnumerable <string> sources, IEnumerable <TracerProviderBuilderBase.InstrumentationFactory> instrumentationFactories, Sampler sampler, List <BaseProcessor <Activity> > processors, Dictionary <string, bool> legacyActivityOperationNames) { this.Resource = resource; this.sampler = sampler; this.supportLegacyActivity = legacyActivityOperationNames.Count > 0; bool legacyActivityWildcardMode = false; Regex legacyActivityWildcardModeRegex = null; foreach (var legacyName in legacyActivityOperationNames) { if (legacyName.Key.Contains('*')) { legacyActivityWildcardMode = true; legacyActivityWildcardModeRegex = GetWildcardRegex(legacyActivityOperationNames.Keys); break; } } foreach (var processor in processors) { this.AddProcessor(processor); } if (instrumentationFactories.Any()) { foreach (var instrumentationFactory in instrumentationFactories) { this.instrumentations.Add(instrumentationFactory.Factory()); } } var listener = new ActivityListener(); if (this.supportLegacyActivity) { Func <Activity, bool> legacyActivityPredicate = null; if (legacyActivityWildcardMode) { legacyActivityPredicate = activity => legacyActivityWildcardModeRegex.IsMatch(activity.OperationName); } else { legacyActivityPredicate = activity => legacyActivityOperationNames.ContainsKey(activity.OperationName); } listener.ActivityStarted = activity => { OpenTelemetrySdkEventSource.Log.ActivityStarted(activity); if (string.IsNullOrEmpty(activity.Source.Name)) { if (legacyActivityPredicate(activity)) { // Legacy activity matches the user configured list. // Call sampler for the legacy activity // unless suppressed. if (!Sdk.SuppressInstrumentation) { this.getRequestedDataAction(activity); } else { activity.IsAllDataRequested = false; } } else { // Legacy activity doesn't match the user configured list. No need to proceed further. return; } } if (!activity.IsAllDataRequested) { return; } if (SuppressInstrumentationScope.IncrementIfTriggered() == 0) { this.processor?.OnStart(activity); } }; listener.ActivityStopped = activity => { OpenTelemetrySdkEventSource.Log.ActivityStopped(activity); if (string.IsNullOrEmpty(activity.Source.Name) && !legacyActivityPredicate(activity)) { // Legacy activity doesn't match the user configured list. No need to proceed further. return; } if (!activity.IsAllDataRequested) { return; } // Spec says IsRecording must be false once span ends. // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#isrecording // However, Activity has slightly different semantic // than Span and we don't have strong reason to do this // now, as Activity anyway allows read/write always. // Intentionally commenting the following line. // activity.IsAllDataRequested = false; if (SuppressInstrumentationScope.DecrementIfTriggered() == 0) { this.processor?.OnEnd(activity); } }; } else { listener.ActivityStarted = activity => { OpenTelemetrySdkEventSource.Log.ActivityStarted(activity); if (activity.IsAllDataRequested && SuppressInstrumentationScope.IncrementIfTriggered() == 0) { this.processor?.OnStart(activity); } }; listener.ActivityStopped = activity => { OpenTelemetrySdkEventSource.Log.ActivityStopped(activity); if (!activity.IsAllDataRequested) { return; } // Spec says IsRecording must be false once span ends. // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#isrecording // However, Activity has slightly different semantic // than Span and we don't have strong reason to do this // now, as Activity anyway allows read/write always. // Intentionally commenting the following line. // activity.IsAllDataRequested = false; if (SuppressInstrumentationScope.DecrementIfTriggered() == 0) { this.processor?.OnEnd(activity); } }; } if (sampler is AlwaysOnSampler) { listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ActivitySamplingResult.AllDataAndRecorded : ActivitySamplingResult.None; this.getRequestedDataAction = this.RunGetRequestedDataAlwaysOnSampler; } else if (sampler is AlwaysOffSampler) { listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent.TraceId) : ActivitySamplingResult.None; this.getRequestedDataAction = this.RunGetRequestedDataAlwaysOffSampler; } else { // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ComputeActivitySamplingResult(options, sampler) : ActivitySamplingResult.None; this.getRequestedDataAction = this.RunGetRequestedDataOtherSampler; } if (sources.Any()) { // Sources can be null. This happens when user // is only interested in InstrumentationLibraries // which do not depend on ActivitySources. var wildcardMode = false; // Validation of source name is already done in builder. foreach (var name in sources) { if (name.Contains('*')) { wildcardMode = true; break; } } if (wildcardMode) { var regex = GetWildcardRegex(sources); // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => this.supportLegacyActivity ? string.IsNullOrEmpty(activitySource.Name) || regex.IsMatch(activitySource.Name) : regex.IsMatch(activitySource.Name); } else { var activitySources = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (var name in sources) { activitySources.Add(name); } if (this.supportLegacyActivity) { activitySources.Add(string.Empty); } // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => activitySources.Contains(activitySource.Name); } } else { if (this.supportLegacyActivity) { listener.ShouldListenTo = (activitySource) => string.IsNullOrEmpty(activitySource.Name); } } ActivitySource.AddActivityListener(listener); this.listener = listener; Regex GetWildcardRegex(IEnumerable <string> collection) { var pattern = '^' + string.Join("|", from name in collection select "(?:" + Regex.Escape(name).Replace("\\*", ".*") + ')') + '$'; return(new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase)); } }
public override void OnStartActivity(Activity activity, object payload) { if (!this.startRequestFetcher.TryFetch(payload, out HttpRequestMessage request) || request == null) { GrpcInstrumentationEventSource.Log.NullPayload(nameof(GrpcClientDiagnosticListener), nameof(this.OnStartActivity)); return; } if (this.options.SuppressDownstreamInstrumentation) { SuppressInstrumentationScope.Enter(); // If we are suppressing downstream instrumentation then inject // context here. Grpc.Net.Client uses HttpClient, so // SuppressDownstreamInstrumentation means that the // OpenTelemetry instrumentation for HttpClient will not be // invoked. // Note that HttpClient natively generates its own activity and // propagates W3C trace context headers regardless of whether // OpenTelemetry HttpClient instrumentation is invoked. // Therefore, injecting here preserves more intuitive span // parenting - i.e., the entry point span of a downstream // service would be parented to the span generated by // Grpc.Net.Client rather than the span generated natively by // HttpClient. Injecting here also ensures that baggage is // propagated to downstream services. // Injecting context here also ensures that the configured // propagator is used, as HttpClient by itself will only // do TraceContext propagation. var textMapPropagator = Propagators.DefaultTextMapPropagator; textMapPropagator.Inject( new PropagationContext(activity.Context, Baggage.Current), request, HttpRequestMessageContextPropagation.HeaderValueSetter); } var grpcMethod = GrpcTagHelper.GetGrpcMethodFromActivity(activity); activity.DisplayName = grpcMethod?.Trim('/'); this.activitySource.Start(activity, ActivityKind.Client, ActivitySource); if (activity.IsAllDataRequested) { try { this.options.Enrich?.Invoke(activity, "OnStartActivity", request); } catch (Exception ex) { GrpcInstrumentationEventSource.Log.EnrichmentException(ex); } activity.SetTag(SemanticConventions.AttributeRpcSystem, GrpcTagHelper.RpcSystemGrpc); if (GrpcTagHelper.TryParseRpcServiceAndRpcMethod(grpcMethod, out var rpcService, out var rpcMethod)) { activity.SetTag(SemanticConventions.AttributeRpcService, rpcService); activity.SetTag(SemanticConventions.AttributeRpcMethod, rpcMethod); // Remove the grpc.method tag added by the gRPC .NET library activity.SetTag(GrpcTagHelper.GrpcMethodTagName, null); } var uriHostNameType = Uri.CheckHostName(request.RequestUri.Host); if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6) { activity.SetTag(SemanticConventions.AttributeNetPeerIp, request.RequestUri.Host); } else { activity.SetTag(SemanticConventions.AttributeNetPeerName, request.RequestUri.Host); } activity.SetTag(SemanticConventions.AttributeNetPeerPort, request.RequestUri.Port); } }
internal TracerProviderSdk( Resource resource, IEnumerable <string> sources, IEnumerable <TracerProviderBuilder.InstrumentationFactory> instrumentationFactories, Sampler sampler, List <ActivityProcessor> processors) { this.resource = resource; this.sampler = sampler; foreach (var processor in processors) { this.AddProcessor(processor); } if (instrumentationFactories.Any()) { this.adapter = new ActivitySourceAdapter(sampler, this.processor, resource); foreach (var instrumentationFactory in instrumentationFactories) { this.instrumentations.Add(instrumentationFactory.Factory(this.adapter)); } } var listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = (activity) => { if (!activity.IsAllDataRequested) { return; } if (SuppressInstrumentationScope.IncrementIfTriggered() == 0) { activity.SetResource(this.resource); this.processor?.OnStart(activity); } }, // Callback when Activity is stopped. ActivityStopped = (activity) => { if (!activity.IsAllDataRequested) { return; } if (SuppressInstrumentationScope.DecrementIfTriggered() == 0) { this.processor?.OnEnd(activity); } }, // Setting this to true means TraceId will be always // available in sampling callbacks and will be the actual // traceid used, if activity ends up getting created. AutoGenerateRootContextTraceId = true, }; if (sampler is AlwaysOnSampler) { listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ActivityDataRequest.AllDataAndRecorded : ActivityDataRequest.None; } else if (sampler is AlwaysOffSampler) { /*TODO: Change options.Parent.SpanId to options.Parent.TraceId * once AutoGenerateRootContextTraceId is removed.*/ listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent.SpanId) : ActivityDataRequest.None; } else { // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ComputeActivityDataRequest(options, sampler) : ActivityDataRequest.None; } if (sources.Any()) { // Sources can be null. This happens when user // is only interested in InstrumentationLibraries // which do not depend on ActivitySources. var wildcardMode = false; // Validation of source name is already done in builder. foreach (var name in sources) { if (name.Contains('*')) { wildcardMode = true; } } if (wildcardMode) { var pattern = "^(" + string.Join("|", from name in sources select '(' + Regex.Escape(name).Replace("\\*", ".*") + ')') + ")$"; var regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => regex.IsMatch(activitySource.Name); } else { var activitySources = new Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase); foreach (var name in sources) { activitySources[name] = true; } // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => activitySources.ContainsKey(activitySource.Name); } } ActivitySource.AddActivityListener(listener); this.listener = listener; }
internal TracerProviderSdk( Resource resource, IEnumerable <string> sources, IEnumerable <TracerProviderBuilderSdk.DiagnosticSourceInstrumentationFactory> diagnosticSourceInstrumentationFactories, IEnumerable <TracerProviderBuilderSdk.InstrumentationFactory> instrumentationFactories, Sampler sampler, List <BaseProcessor <Activity> > processors) { this.Resource = resource; this.sampler = sampler; foreach (var processor in processors) { this.AddProcessor(processor); } if (diagnosticSourceInstrumentationFactories.Any()) { this.adapter = new ActivitySourceAdapter(sampler, this.processor); foreach (var instrumentationFactory in diagnosticSourceInstrumentationFactories) { this.instrumentations.Add(instrumentationFactory.Factory(this.adapter)); } } if (instrumentationFactories.Any()) { foreach (var instrumentationFactory in instrumentationFactories) { this.instrumentations.Add(instrumentationFactory.Factory()); } } var listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = (activity) => { OpenTelemetrySdkEventSource.Log.ActivityStarted(activity); if (!activity.IsAllDataRequested) { return; } if (SuppressInstrumentationScope.IncrementIfTriggered() == 0) { this.processor?.OnStart(activity); } }, // Callback when Activity is stopped. ActivityStopped = (activity) => { OpenTelemetrySdkEventSource.Log.ActivityStopped(activity); if (!activity.IsAllDataRequested) { return; } // Spec says IsRecording must be false once span ends. // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#isrecording // However, Activity has slightly different semantic // than Span and we don't have strong reason to do this // now, as Activity anyway allows read/write always. // Intentionally commenting the following line. // activity.IsAllDataRequested = false; if (SuppressInstrumentationScope.DecrementIfTriggered() == 0) { this.processor?.OnEnd(activity); } }, }; if (sampler is AlwaysOnSampler) { listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ActivitySamplingResult.AllDataAndRecorded : ActivitySamplingResult.None; } else if (sampler is AlwaysOffSampler) { listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? PropagateOrIgnoreData(options.Parent.TraceId) : ActivitySamplingResult.None; } else { // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. listener.Sample = (ref ActivityCreationOptions <ActivityContext> options) => !Sdk.SuppressInstrumentation ? ComputeActivitySamplingResult(options, sampler) : ActivitySamplingResult.None; } if (sources.Any()) { // Sources can be null. This happens when user // is only interested in InstrumentationLibraries // which do not depend on ActivitySources. var wildcardMode = false; // Validation of source name is already done in builder. foreach (var name in sources) { if (name.Contains('*')) { wildcardMode = true; } } if (wildcardMode) { var pattern = "^(" + string.Join("|", from name in sources select '(' + Regex.Escape(name).Replace("\\*", ".*") + ')') + ")$"; var regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => regex.IsMatch(activitySource.Name); } else { var activitySources = new Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase); foreach (var name in sources) { activitySources[name] = true; } // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not. listener.ShouldListenTo = (activitySource) => activitySources.ContainsKey(activitySource.Name); } } ActivitySource.AddActivityListener(listener); this.listener = listener; }