/// <summary> /// Enables the outgoing requests automatic data collection for GrpcClient. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddGrpcClientDependencyInstrumentation( this OpenTelemetryBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.AddInstrumentation((activitySource) => new GrpcClientInstrumentation(activitySource)); return(builder); }
/// <summary> /// Enables instrumentation for Azure clients. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddAzureClientsDependencyInstrumentation( this OpenTelemetryBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.AddActivitySource(AzureSdkDiagnosticListener.ActivitySourceName); builder.AddInstrumentation(() => new AzureClientsInstrumentation()); return(builder); }
/// <summary> /// Enables OpenTelemetry. /// </summary> /// <param name="configureOpenTelemetryBuilder">Function that configures OpenTelemetryBuilder.</param> /// <returns><see cref="OpenTelemetrySdk"/> instance which can be disposed on application shutdown.</returns> /// <remarks> /// Basic implementation only. Most logic from TracerBuilder will be ported here. /// </remarks> public static OpenTelemetrySdk EnableOpenTelemetry(Action <OpenTelemetryBuilder> configureOpenTelemetryBuilder) { var openTelemetryBuilder = new OpenTelemetryBuilder(); configureOpenTelemetryBuilder(openTelemetryBuilder); var openTelemetrySDK = new OpenTelemetrySdk(); ActivitySampler sampler = openTelemetryBuilder.Sampler ?? new AlwaysOnActivitySampler(); ActivityProcessor activityProcessor; if (openTelemetryBuilder.ProcessingPipeline == null) { // if there are no pipelines are configured, use noop processor activityProcessor = new NoopActivityProcessor(); } else { activityProcessor = openTelemetryBuilder.ProcessingPipeline.Build(); } if (openTelemetryBuilder.InstrumentationFactories != null) { foreach (var instrumentation in openTelemetryBuilder.InstrumentationFactories) { openTelemetrySDK.instrumentations.Add(instrumentation.Factory()); } } // This is what subscribes to Activities. // Think of this as the replacement for DiagnosticListener.AllListeners.Subscribe(onNext => diagnosticListener.Subscribe(..)); openTelemetrySDK.listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = activityProcessor.OnStart, // Callback when Activity is started. ActivityStopped = activityProcessor.OnEnd, // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not ShouldListenTo = (activitySource) => openTelemetryBuilder.ActivitySourceNames?.Contains(activitySource.Name.ToUpperInvariant()) ?? false, // The following parameter is not used now. GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> options) => ActivityDataRequest.AllData, // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => ComputeActivityDataRequest(options, sampler), }; ActivitySource.AddActivityListener(openTelemetrySDK.listener); return(openTelemetrySDK); }
/// <summary> /// Enables the outgoing requests automatic data collection for all supported activity sources. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddDependencyInstrumentation(this OpenTelemetryBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.AddHttpClientDependencyInstrumentation(); builder.AddSqlClientDependencyInstrumentation(); #if NETFRAMEWORK builder.AddHttpWebRequestDependencyInstrumentation(); #endif return(builder); }
/// <summary> /// Enables the incoming requests automatic data collection for Asp.Net Core. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <param name="configureAspNetCoreInstrumentationOptions">ASP.NET Core Request configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddRequestInstrumentation( this OpenTelemetryBuilder builder, Action <AspNetCoreInstrumentationOptions> configureAspNetCoreInstrumentationOptions = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } var aspnetCoreOptions = new AspNetCoreInstrumentationOptions(); configureAspNetCoreInstrumentationOptions?.Invoke(aspnetCoreOptions); builder.AddInstrumentation((activitySource) => new AspNetCoreInstrumentation(activitySource, aspnetCoreOptions)); return(builder); }
/// <summary> /// Enables the outgoing requests automatic data collection for HttpClient. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <param name="configureHttpClientInstrumentationOptions">HttpClient configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddHttpClientDependencyInstrumentation( this OpenTelemetryBuilder builder, Action <HttpClientInstrumentationOptions> configureHttpClientInstrumentationOptions = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } var httpClientOptions = new HttpClientInstrumentationOptions(); configureHttpClientInstrumentationOptions?.Invoke(httpClientOptions); builder.AddInstrumentation((activitySource) => new HttpClientInstrumentation(activitySource, httpClientOptions)); return(builder); }
/// <summary> /// Enables the OpenTelemetry Protocol (OTLP) exporter. /// </summary> /// <param name="builder">Open Telemetry builder to use.</param> /// <param name="configure">Exporter configuration options.</param> /// <param name="processorConfigure">Activity processor configuration.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder UseOtlpExporter(this OpenTelemetryBuilder builder, Action <OtlpExporterOptions> configure = null, Action <ActivityProcessorPipelineBuilder> processorConfigure = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } return(builder.AddProcessorPipeline(pipeline => { var exporterOptions = new OtlpExporterOptions(); configure?.Invoke(exporterOptions); var activityExporter = new OtlpExporter(exporterOptions); processorConfigure?.Invoke(pipeline); pipeline.SetExporter(activityExporter); })); }
/// <summary> /// Enables the outgoing requests automatic data collection for Redis. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <param name="connection"><see cref="ConnectionMultiplexer"/> to instrument.</param> /// <param name="configureOptions">Redis configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddRedisInstrumentation( this OpenTelemetryBuilder builder, ConnectionMultiplexer connection, Action <StackExchangeRedisCallsInstrumentationOptions> configureOptions = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } StackExchangeRedisCallsInstrumentationOptions options = new StackExchangeRedisCallsInstrumentationOptions(); configureOptions?.Invoke(options); return(builder .AddInstrumentation((activitySourceAdapter) => new StackExchangeRedisCallsInstrumentation(connection, options)) .AddActivitySource(StackExchangeRedisCallsInstrumentation.ActivitySourceName)); }
/// <summary> /// Enables the outgoing requests automatic data collection for SqlClient. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <param name="configureSqlClientInstrumentationOptions">SqlClient configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddSqlClientDependencyInstrumentation( this OpenTelemetryBuilder builder, Action <SqlClientInstrumentationOptions> configureSqlClientInstrumentationOptions = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } var sqlOptions = new SqlClientInstrumentationOptions(); configureSqlClientInstrumentationOptions?.Invoke(sqlOptions); builder.AddInstrumentation((activitySource) => new SqlClientInstrumentation(sqlOptions)); builder.AddActivitySource(SqlClientDiagnosticListener.ActivitySourceName); return(builder); }
/// <summary> /// Enables the outgoing requests automatic data collection for all supported activity sources. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <param name="configureHttpClientInstrumentationOptions">HttpClient configuration options.</param> /// <param name="configureSqlClientInstrumentationOptions">SqlClient configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddDependencyInstrumentation( this OpenTelemetryBuilder builder, Action <HttpClientInstrumentationOptions> configureHttpClientInstrumentationOptions = null, Action <SqlClientInstrumentationOptions> configureSqlClientInstrumentationOptions = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.AddHttpClientDependencyInstrumentation(configureHttpClientInstrumentationOptions); builder.AddSqlClientDependencyInstrumentation(configureSqlClientInstrumentationOptions); builder.AddGrpcClientDependencyInstrumentation(); #if NETFRAMEWORK builder.AddHttpWebRequestDependencyInstrumentation(); #endif return(builder); }
/// <summary> /// Enables the outgoing requests automatic data collection for HttpClient. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <param name="configureHttpClientInstrumentationOptions">HttpClient configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddHttpClientDependencyInstrumentation( this OpenTelemetryBuilder builder, Action <HttpClientInstrumentationOptions> configureHttpClientInstrumentationOptions) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } // HttpClient is not instrumented with ActivitySource, hence // it'll have a default ActivitySource with name string.Empty. builder.AddActivitySource(string.Empty); var httpClientOptions = new HttpClientInstrumentationOptions(); configureHttpClientInstrumentationOptions?.Invoke(httpClientOptions); builder.AddInstrumentation(() => new HttpClientInstrumentation(httpClientOptions)); return(builder); }
/// <summary> /// Enables the outgoing requests automatic data collection for .NET Framework HttpWebRequest activity source. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <param name="configureOptions">HttpWebRequest configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddHttpWebRequestDependencyInstrumentation( this OpenTelemetryBuilder builder, Action <HttpWebRequestInstrumentationOptions> configureOptions = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } HttpWebRequestInstrumentationOptions options = new HttpWebRequestInstrumentationOptions(); configureOptions?.Invoke(options); HttpWebRequestActivitySource.Options = options; builder.AddActivitySource(HttpWebRequestActivitySource.ActivitySourceName); return(builder); }
/// <summary> /// Enables the incoming requests automatic data collection for Asp.Net. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <param name="configureAspNetInstrumentationOptions">ASP.NET Request configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddRequestInstrumentation( this OpenTelemetryBuilder builder, Action <AspNetInstrumentationOptions> configureAspNetInstrumentationOptions = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } // Asp.Net is not instrumented with ActivitySource, hence // it'll have a default ActivitySource with name string.Empty. builder.AddActivitySource(string.Empty); var aspnetOptions = new AspNetInstrumentationOptions(); configureAspNetInstrumentationOptions?.Invoke(aspnetOptions); builder.AddInstrumentation(() => new AspNetInstrumentation(aspnetOptions)); return(builder); }
/// <summary> /// Registers a Jaeger exporter that will receive <see cref="System.Diagnostics.Activity"/> instances. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> builder to use.</param> /// <param name="configure">Exporter configuration options.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder UseJaegerActivityExporter(this OpenTelemetryBuilder builder, Action <JaegerExporterOptions> configure) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (configure == null) { throw new ArgumentNullException(nameof(configure)); } return(builder.AddProcessorPipeline(pipeline => { var exporterOptions = new JaegerExporterOptions(); configure(exporterOptions); var activityExporter = new JaegerActivityExporter(exporterOptions); pipeline.SetExporter(activityExporter); })); }
/// <summary> /// Enables OpenTelemetry. /// </summary> /// <param name="configureOpenTelemetryBuilder">Function that configures OpenTelemetryBuilder.</param> /// <remarks> /// Basic implementation only. Most logic from TracerBuilder will be ported here. /// </remarks> public static void EnableOpenTelemetry(Action <OpenTelemetryBuilder> configureOpenTelemetryBuilder) { var openTelemetryBuilder = new OpenTelemetryBuilder(); configureOpenTelemetryBuilder(openTelemetryBuilder); ActivityProcessor activityProcessor; if (openTelemetryBuilder.ProcessingPipeline == null) { // if there are no pipelines are configured, use noop processor activityProcessor = new NoopActivityProcessor(); } else { activityProcessor = openTelemetryBuilder.ProcessingPipeline.Build(); } // This is what subscribes to Activities. // Think of this as the replacement for DiagnosticListener.AllListeners.Subscribe(onNext => diagnosticListener.Subscribe(..)); ActivityListener listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = activityProcessor.OnStart, // Callback when Activity is started. ActivityStopped = activityProcessor.OnEnd, // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not ShouldListenTo = (activitySource) => openTelemetryBuilder.ActivitySourceNames.Contains(activitySource.Name.ToUpperInvariant()), // The following parameters are not used now. GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> options) => ActivityDataRequest.AllData, GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => ActivityDataRequest.AllData, }; ActivitySource.AddActivityListener(listener); }
/// <summary> /// Enables OpenTelemetry. /// </summary> /// <param name="configureOpenTelemetryBuilder">Function that configures OpenTelemetryBuilder.</param> /// <remarks> /// Basic implementation only. Most logic from TracerBuilder will be ported here. /// </remarks> public static void EnableOpenTelemetry(Action <OpenTelemetryBuilder> configureOpenTelemetryBuilder) { var openTelemetryBuilder = new OpenTelemetryBuilder(); configureOpenTelemetryBuilder(openTelemetryBuilder); ActivitySampler sampler = openTelemetryBuilder.Sampler ?? new AlwaysOnActivitySampler(); ActivityProcessor activityProcessor; if (openTelemetryBuilder.ProcessingPipeline == null) { // if there are no pipelines are configured, use noop processor activityProcessor = new NoopActivityProcessor(); } else { activityProcessor = openTelemetryBuilder.ProcessingPipeline.Build(); } // This is what subscribes to Activities. // Think of this as the replacement for DiagnosticListener.AllListeners.Subscribe(onNext => diagnosticListener.Subscribe(..)); ActivityListener listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = activityProcessor.OnStart, // Callback when Activity is started. ActivityStopped = activityProcessor.OnEnd, // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not ShouldListenTo = (activitySource) => openTelemetryBuilder.ActivitySourceNames.Contains(activitySource.Name.ToUpperInvariant()), // The following parameter is not used now. GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> options) => ActivityDataRequest.AllData, // This delegate informs ActivitySource about sampling decision. // Following simple behavior is enabled now: // If Sampler returns IsSampled as true, returns ActivityDataRequest.AllDataAndRecorded // This creates Activity and sets its IsAllDataRequested to true. // Library authors can check activity.IsAllDataRequested and avoid // doing any additional telemetry population. // Activity.IsAllDataRequested is the equivalent of Span.IsRecording // // If Sampler returns IsSampled as false, returns ActivityDataRequest.None // This prevents Activity from being created at all. GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => { var shouldSample = sampler.ShouldSample( options.Parent, options.Parent.TraceId, default(ActivitySpanId), // Passing default SpanId here. The actual SpanId is not known before actual Activity creation options.Name, options.Kind, options.Tags, options.Links); if (shouldSample.IsSampled) { return(ActivityDataRequest.AllDataAndRecorded); } else { return(ActivityDataRequest.None); } // TODO: Improve this to properly use ActivityDataRequest.AllData, PropagationData as well. }, }; ActivitySource.AddActivityListener(listener); }
/// <summary> /// Enables the outgoing requests automatic data collection for .NET Framework HttpWebRequest activity source. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddHttpWebRequestDependencyInstrumentation(this OpenTelemetryBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } GC.KeepAlive(HttpWebRequestActivitySource.Instance); builder.AddActivitySource(HttpWebRequestActivitySource.ActivitySourceName); return(builder); }
/// <summary> /// Enables OpenTelemetry. /// </summary> /// <param name="configureOpenTelemetryBuilder">Function that configures OpenTelemetryBuilder.</param> /// <returns><see cref="OpenTelemetrySdk"/> instance which can be disposed on application shutdown.</returns> /// <remarks> /// Basic implementation only. Most logic from TracerBuilder will be ported here. /// </remarks> public static OpenTelemetrySdk EnableOpenTelemetry(Action <OpenTelemetryBuilder> configureOpenTelemetryBuilder) { var openTelemetryBuilder = new OpenTelemetryBuilder(); configureOpenTelemetryBuilder(openTelemetryBuilder); var openTelemetrySDK = new OpenTelemetrySdk(); ActivitySampler sampler = openTelemetryBuilder.Sampler ?? new AlwaysOnActivitySampler(); ActivityProcessor activityProcessor; if (openTelemetryBuilder.ProcessingPipelines == null || !openTelemetryBuilder.ProcessingPipelines.Any()) { // if there are no pipelines are configured, use noop processor activityProcessor = new NoopActivityProcessor(); } else if (openTelemetryBuilder.ProcessingPipelines.Count == 1) { // if there is only one pipeline - use it's outer processor as a // single processor on the tracerSdk. var processorFactory = openTelemetryBuilder.ProcessingPipelines[0]; activityProcessor = processorFactory.Build(); } else { // if there are more pipelines, use processor that will broadcast to all pipelines var processors = new ActivityProcessor[openTelemetryBuilder.ProcessingPipelines.Count]; for (int i = 0; i < openTelemetryBuilder.ProcessingPipelines.Count; i++) { processors[i] = openTelemetryBuilder.ProcessingPipelines[i].Build(); } activityProcessor = new BroadcastActivityProcessor(processors); } openTelemetrySDK.resource = openTelemetryBuilder.Resource; var activitySource = new ActivitySourceAdapter(sampler, activityProcessor, openTelemetrySDK.resource); if (openTelemetryBuilder.InstrumentationFactories != null) { foreach (var instrumentation in openTelemetryBuilder.InstrumentationFactories) { openTelemetrySDK.instrumentations.Add(instrumentation.Factory(activitySource)); } } // This is what subscribes to Activities. // Think of this as the replacement for DiagnosticListener.AllListeners.Subscribe(onNext => diagnosticListener.Subscribe(..)); openTelemetrySDK.listener = new ActivityListener { // Callback when Activity is started. ActivityStarted = (activity) => { if (activity.IsAllDataRequested) { activity.SetResource(openTelemetrySDK.resource); } activityProcessor.OnStart(activity); }, // Callback when Activity is started. ActivityStopped = activityProcessor.OnEnd, // Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to // or not ShouldListenTo = (activitySource) => openTelemetryBuilder.ActivitySourceNames?.Contains(activitySource.Name.ToUpperInvariant()) ?? false, // The following parameter is not used now. GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> options) => ActivityDataRequest.AllData, // This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext. GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => ComputeActivityDataRequest(options, sampler), }; ActivitySource.AddActivityListener(openTelemetrySDK.listener); openTelemetrySDK.activityProcessor = activityProcessor; return(openTelemetrySDK); }
/// <summary> /// Enables the outgoing requests automatic data collection for HttpClient. /// </summary> /// <param name="builder"><see cref="OpenTelemetryBuilder"/> being configured.</param> /// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns> public static OpenTelemetryBuilder AddHttpClientDependencyInstrumentation( this OpenTelemetryBuilder builder) { return(builder.AddHttpClientDependencyInstrumentation(null)); }