Example #1
0
        /// <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 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);
        }
Example #3
0
 /// <summary>
 /// Configures sampler.
 /// </summary>
 /// <param name="sampler">Sampler instance.</param>
 /// <returns>Returns <see cref="OpenTelemetryBuilder"/> for chaining.</returns>
 public OpenTelemetryBuilder SetSampler(ActivitySampler sampler)
 {
     this.Sampler = sampler ?? throw new ArgumentNullException(nameof(sampler));
     return(this);
 }
        /// <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);
        }