public static void Main(string[] args)
        {
            var listener = new ActivityListener
            {
                ShouldListenTo  = _ => true,
                ActivityStopped = activity =>
                {
                    foreach (var(key, value) in activity.Baggage)
                    {
                        activity.AddTag(key, value);
                    }
                }
            };

            ActivitySource.AddActivityListener(listener);



            var host = CreateHostBuilder(args).Build();

            SeedDb(host);

            host.Run();
        }
Example #2
0
        public void ProcessorDoesNotBlockOnExporter()
        {
            this.activityExporter = new TestActivityExporter(async _ => await Task.Delay(500));
            this.openTelemetry    = Sdk.CreateTracerProvider(b => b
                                                             .AddActivitySource("cijo")
                                                             .AddProcessorPipeline(p => p
                                                                                   .SetExporter(this.activityExporter)
                                                                                   .SetExportingProcessor(e => new SimpleActivityProcessor(e))));

            ActivitySource source   = new ActivitySource("cijo");
            var            activity = source.StartActivity("somename");

            // does not block
            var sw = Stopwatch.StartNew();

            activity.Stop();
            sw.Stop();

            Assert.InRange(sw.Elapsed, TimeSpan.Zero, TimeSpan.FromMilliseconds(100));

            var exported = this.WaitForSpans(this.activityExporter, 1, TimeSpan.FromMilliseconds(600));

            Assert.Single(exported);
        }
        public void ProcessorDoesNotBlockOnExporter()
        {
            var activityExporter = new TestActivityExporter(async _ => await Task.Delay(500));

            using var openTelemetry = Sdk.CreateTracerProviderBuilder()
                                      .AddSource("random")
                                      .AddProcessor(new SimpleActivityProcessor(activityExporter))
                                      .Build();

            ActivitySource source   = new ActivitySource("random");
            var            activity = source.StartActivity("somename");

            // does not block
            var sw = Stopwatch.StartNew();

            activity.Stop();
            sw.Stop();

            Assert.InRange(sw.Elapsed, TimeSpan.Zero, TimeSpan.FromMilliseconds(100));

            var exported = this.WaitForSpans(activityExporter, 1, TimeSpan.FromMilliseconds(600));

            Assert.Single(exported);
        }
Example #4
0
        public void TestActivitySourceAttachedObject()
        {
            RemoteExecutor.Invoke(() => {
                // All Activities created through the constructor should have same source.
                Assert.True(object.ReferenceEquals(new Activity("a1").Source, new Activity("a2").Source));
                Assert.Equal("", new Activity("a3").Source.Name);
                Assert.Equal(string.Empty, new Activity("a4").Source.Version);

                using ActivitySource aSource = new ActivitySource("SourceToTest", "1.2.3.4");

                // Ensure at least we have a listener to allow Activity creation
                using ActivityListener listener = new ActivityListener();
                listener.ActivityStarted        = activity => Assert.NotNull(activity);
                listener.ActivityStopped        = activity => Assert.NotNull(activity);
                listener.ShouldListenTo         = (activitySource) => object.ReferenceEquals(aSource, activitySource);
                listener.SampleUsingParentId    = (ref ActivityCreationOptions <string> activityOptions) => ActivitySamplingResult.AllData;
                listener.Sample = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivitySamplingResult.AllData;

                ActivitySource.AddActivityListener(listener);

                using Activity activity = aSource.StartActivity("ActivityToTest");
                Assert.True(object.ReferenceEquals(aSource, activity.Source));
            }).Dispose();
        }
        /// <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 #6
0
        public ClientSecretAuthenticationMiddleware(RequestDelegate next, IContainerResolve container, ClientSecretAuthenticationOption option)
        {
            _next = next ?? throw new ArgumentNullException(nameof(next));

            if (null == container)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (null == option)
            {
                throw new ArgumentNullException(nameof(option));
            }

            _logger = container.Resolve <ILogger <ClientSecretAuthenticationMiddleware> >();
            _option = option;

            if (null == option.Settings)
            {
                _logger.Technical().Warning("No settings have been provided.").Log();
                return;
            }

            if (option.Settings.Values.ContainsKey(TokenKeys.ProviderIdKey))
            {
                _hasProvider = container.TryResolve(option.Settings.Values[TokenKeys.ProviderIdKey], out _provider);
            }

            if (!_hasProvider)
            {
                _logger.Technical().Warning("No ClientSecret provider found. Skip ClientSecret capability.").Log();
                return;
            }

            _hasCertificate = null != option.Certificate &&
                              !String.IsNullOrWhiteSpace(option.Certificate.SecretKey) &&
                              !String.IsNullOrWhiteSpace(option.Certificate.Name);

            // check the certificate exists.
            if (_hasCertificate)
            {
                try
                {
                    var certificateInfo = new CertificateInfo
                    {
                        Name = option.Certificate.Name
                    };

                    if (Enum.TryParse(option.Certificate.FindType, out X509FindType x509FindType))
                    {
                        certificateInfo.FindType = x509FindType;
                    }
                    if (Enum.TryParse(option.Certificate.Location, out StoreLocation storeLocation_))
                    {
                        certificateInfo.Location = storeLocation_;
                    }
                    if (Enum.TryParse(option.Certificate.StoreName, out StoreName storeName_))
                    {
                        certificateInfo.StoreName = storeName_;
                    }

                    _certificate = Certificate.FindCertificate(
                        certificateInfo.Name,
                        certificateInfo.FindType,
                        certificateInfo.Location,
                        certificateInfo.StoreName);

                    _logger.Technical().System($"Authentication with certificate secret activated.").Log();
                }
                catch (KeyNotFoundException)
                {
                    _hasCertificate = false;
                    _logger.Technical().Error($"No certificate found with {option.Certificate.FindType} = {option.Certificate.Name} in location = {option.Certificate.Location}.").Log();
                }
                catch (Exception ex)
                {
                    _logger.Technical().Exception(ex).Log();
                }
            }
            else
            {
                _logger.Technical().System($"No authentication  with certificate secret.").Log();
            }

            _activitySource = container.Resolve <IActivitySourceFactory>()?.GetArc4u();
        }
        public static Activity CreateActivityWithKind(ActivitySource source)
        {
            var activity = source.StartActivity("name", ActivityKind.Client);

            return(activity);
        }
Example #8
0
        public async Task IncomingRequestInstrumentationTest(
            bool instrument,
            bool filter               = false,
            bool includeVersion       = false,
            bool enrich               = false,
            bool enrichmentExcecption = false)
        {
            List <Activity> stoppedActivities = new List <Activity>();

            using ActivityListener activityListener = new ActivityListener
                  {
                      ShouldListenTo  = activitySource => true,
                      ActivityStopped = activity => stoppedActivities.Add(activity),
                  };

            ActivitySource.AddActivityListener(activityListener);

            TracerProvider tracerProvider = null;

            if (instrument)
            {
                tracerProvider = Sdk.CreateTracerProviderBuilder()
                                 .AddWcfInstrumentation(options =>
                {
                    if (enrich)
                    {
                        if (!enrichmentExcecption)
                        {
                            options.Enrich = (activity, eventName, message) =>
                            {
                                switch (eventName)
                                {
                                case WcfEnrichEventNames.AfterReceiveRequest:
                                    activity.SetTag(
                                        "server.afterreceiverequest",
                                        WcfEnrichEventNames.AfterReceiveRequest);
                                    break;

                                case WcfEnrichEventNames.BeforeSendReply:
                                    activity.SetTag(
                                        "server.beforesendreply",
                                        WcfEnrichEventNames.BeforeSendReply);
                                    break;
                                }
                            };
                        }
                        else
                        {
                            options.Enrich = (activity, eventName, message) =>
                            {
                                throw new Exception("Failure whilst enriching activity");
                            };
                        }
                    }

                    options.IncomingRequestFilter = (Message m) =>
                    {
                        return(!filter);
                    };
                    options.SetSoapMessageVersion = includeVersion;
                })
                                 .Build();
            }

            ServiceClient client = new ServiceClient(
                new NetTcpBinding(),
                new EndpointAddress(new Uri(this.serviceBaseUri, "/Service")));

            try
            {
                var response = await client.ExecuteAsync(
                    new ServiceRequest
                {
                    Payload = "Hello Open Telemetry!",
                }).ConfigureAwait(false);
            }
            finally
            {
                if (client.State == CommunicationState.Faulted)
                {
                    client.Abort();
                }
                else
                {
                    client.Close();
                }

                tracerProvider?.Shutdown();
                tracerProvider?.Dispose();

                WcfInstrumentationActivitySource.Options = null;
            }

            if (instrument && !filter)
            {
                Assert.NotEmpty(stoppedActivities);
                Assert.Single(stoppedActivities);

                Activity activity = stoppedActivities[0];
                Assert.Equal(WcfInstrumentationActivitySource.IncomingRequestActivityName, activity.OperationName);
                Assert.Equal(WcfInstrumentationConstants.WcfSystemValue, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcSystemTag).Value);
                Assert.Equal("http://opentelemetry.io/Service", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcServiceTag).Value);
                Assert.Equal("Execute", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcMethodTag).Value);
                Assert.Equal(this.serviceBaseUri.Host, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.NetHostNameTag).Value);
                Assert.Equal(this.serviceBaseUri.Port, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.NetHostPortTag).Value);
                Assert.Equal("net.tcp", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.WcfChannelSchemeTag).Value);
                Assert.Equal("/Service", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.WcfChannelPathTag).Value);
                Assert.Equal("http://opentelemetry.io/Service/ExecuteResponse", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.SoapReplyActionTag).Value);
                if (includeVersion)
                {
                    Assert.Equal("Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.SoapMessageVersionTag).Value);
                }

                if (enrich && !enrichmentExcecption)
                {
                    Assert.Equal(WcfEnrichEventNames.AfterReceiveRequest, activity.TagObjects.Single(t => t.Key == "server.afterreceiverequest").Value);
                    Assert.Equal(WcfEnrichEventNames.BeforeSendReply, activity.TagObjects.Single(t => t.Key == "server.beforesendreply").Value);
                }
            }
            else
            {
                Assert.Empty(stoppedActivities);
            }
        }
Example #9
0
        public void BuildSamplingParametersHandlesCurrentActivity()
        {
            using var activitySource = new ActivitySource(nameof(this.BuildSamplingParametersHandlesCurrentActivity));

            var testSampler = new TestSampler {
                DesiredSamplingResult = new SamplingResult(true)
            };

            using var listener = new ActivityListener
                  {
                      ShouldListenTo = _ => true,
                      GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) =>
                                                     Sdk.ComputeActivityDataRequest(options, testSampler),
                  };

            ActivitySource.AddActivityListener(listener);

            using (var root = activitySource.StartActivity("root"))
            {
                Assert.Equal(default(ActivitySpanId), root.ParentSpanId);

                // This enforces the current behavior that the traceId passed to the sampler for the
                // root span/activity is not the traceId actually used.
                Assert.NotEqual(root.TraceId, testSampler.LatestSamplingParameters.TraceId);
            }

            using (var parent = activitySource.StartActivity("parent", ActivityKind.Client))
            {
                // This enforces the current behavior that the traceId passed to the sampler for the
                // root span/activity is not the traceId actually used.
                Assert.NotEqual(parent.TraceId, testSampler.LatestSamplingParameters.TraceId);
                using (var child = activitySource.StartActivity("child"))
                {
                    Assert.Equal(parent.TraceId, testSampler.LatestSamplingParameters.TraceId);
                    Assert.Equal(parent.TraceId, child.TraceId);
                    Assert.Equal(parent.SpanId, child.ParentSpanId);
                }
            }

            var customContext = new ActivityContext(
                ActivityTraceId.CreateRandom(),
                ActivitySpanId.CreateRandom(),
                ActivityTraceFlags.None);

            using (var fromCustomContext =
                       activitySource.StartActivity("customContext", ActivityKind.Client, customContext))
            {
                Assert.Equal(customContext.TraceId, fromCustomContext.TraceId);
                Assert.Equal(customContext.SpanId, fromCustomContext.ParentSpanId);
                Assert.NotEqual(customContext.SpanId, fromCustomContext.SpanId);
            }

            // Preserve traceId in case span is propagated but not recorded (sampled per OpenTelemetry parlance) and
            // no data is requested for children spans.
            testSampler.DesiredSamplingResult = new SamplingResult(false);
            using (var root = activitySource.StartActivity("root"))
            {
                Assert.Equal(default(ActivitySpanId), root.ParentSpanId);

                using (var child = activitySource.StartActivity("child"))
                {
                    Assert.Null(child);
                    Assert.Equal(root.TraceId, testSampler.LatestSamplingParameters.TraceId);
                    Assert.Same(Activity.Current, root);
                }
            }
        }
        public void TestExpectedListenersReturnValues()
        {
            RemoteExecutor.Invoke(() => {
                int activityStartCount = 0;
                int activityStopCount  = 0;

                ActivitySource source         = new ActivitySource("MultipleListenerSource");
                ActivityListener [] listeners = new ActivityListener[4];

                listeners[0] = new ActivityListener
                {
                    ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); },
                    ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); },
                    ShouldListenTo  = (activitySource) => true,
                    GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.None,
                    GetRequestedDataUsingContext  = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.None
                };
                ActivitySource.AddActivityListener(listeners[0]);

                Assert.Null(source.StartActivity("a1"));

                Assert.Equal(0, activityStartCount);
                Assert.Equal(0, activityStopCount);

                listeners[1] = new ActivityListener
                {
                    ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); },
                    ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); },
                    ShouldListenTo  = (activitySource) => true,
                    GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.PropagationData,
                    GetRequestedDataUsingContext  = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.PropagationData
                };
                ActivitySource.AddActivityListener(listeners[1]);

                using (Activity a2 = source.StartActivity("a2"))
                {
                    Assert.False(a2.IsAllDataRequested);
                    Assert.True((a2.ActivityTraceFlags & ActivityTraceFlags.Recorded) == 0);

                    Assert.Equal(2, activityStartCount);
                    Assert.Equal(0, activityStopCount);
                }

                Assert.Equal(activityStartCount, activityStopCount);
                Assert.Equal(2, activityStopCount);

                listeners[2] = new ActivityListener
                {
                    ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); },
                    ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); },
                    ShouldListenTo  = (activitySource) => true,
                    GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.AllData,
                    GetRequestedDataUsingContext  = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.AllData
                };
                ActivitySource.AddActivityListener(listeners[2]);

                using (Activity a3 = source.StartActivity("a3"))
                {
                    Assert.True(a3.IsAllDataRequested);
                    Assert.True((a3.ActivityTraceFlags & ActivityTraceFlags.Recorded) == 0);

                    Assert.Equal(5, activityStartCount);
                    Assert.Equal(2, activityStopCount);
                }

                Assert.Equal(activityStartCount, activityStopCount);
                Assert.Equal(5, activityStopCount);

                listeners[3] = new ActivityListener
                {
                    ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); },
                    ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); },
                    ShouldListenTo  = (activitySource) => true,
                    GetRequestedDataUsingParentId = (ref ActivityCreationOptions <string> activityOptions) => ActivityDataRequest.AllDataAndRecorded,
                    GetRequestedDataUsingContext  = (ref ActivityCreationOptions <ActivityContext> activityOptions) => ActivityDataRequest.AllDataAndRecorded
                };
                ActivitySource.AddActivityListener(listeners[3]);

                using (Activity a4 = source.StartActivity("a4"))
                {
                    Assert.True(a4.IsAllDataRequested);
                    Assert.True((a4.ActivityTraceFlags & ActivityTraceFlags.Recorded) != 0, $"a4.ActivityTraceFlags failed: {a4.ActivityTraceFlags}");

                    Assert.Equal(9, activityStartCount);
                    Assert.Equal(5, activityStopCount);
                }

                foreach (IDisposable listener in listeners)
                {
                    listener.Dispose();
                }

                Assert.Equal(activityStartCount, activityStopCount);
                Assert.Equal(9, activityStopCount);
                Assert.Null(source.StartActivity("a5"));
            }).Dispose();
        }
Example #11
0
        public void TracerProviderSdkInvokesSamplingWithCorrectParameters()
        {
            var testSampler = new TestSampler();

            using var activitySource = new ActivitySource(ActivitySourceName);
            using var sdk            = Sdk.CreateTracerProviderBuilder()
                                       .AddSource(ActivitySourceName)
                                       .SetSampler(testSampler)
                                       .Build();

            // OpenTelemetry Sdk is expected to set default to W3C.
            Assert.True(Activity.DefaultIdFormat == ActivityIdFormat.W3C);

            using (var rootActivity = activitySource.StartActivity("root"))
            {
                Assert.NotNull(rootActivity);
                Assert.True(rootActivity.ParentSpanId == default);

                // Validate that the TraceId seen by Sampler is same as the
                // Activity when it got created.
                Assert.Equal(rootActivity.TraceId, testSampler.LatestSamplingParameters.TraceId);
            }

            using (var parent = activitySource.StartActivity("parent", ActivityKind.Client))
            {
                Assert.Equal(parent.TraceId, testSampler.LatestSamplingParameters.TraceId);
                using (var child = activitySource.StartActivity("child"))
                {
                    Assert.Equal(child.TraceId, testSampler.LatestSamplingParameters.TraceId);
                    Assert.Equal(parent.TraceId, child.TraceId);
                    Assert.Equal(parent.SpanId, child.ParentSpanId);
                }
            }

            var customContext = new ActivityContext(
                ActivityTraceId.CreateRandom(),
                ActivitySpanId.CreateRandom(),
                ActivityTraceFlags.None);

            using (var fromCustomContext =
                       activitySource.StartActivity("customContext", ActivityKind.Client, customContext))
            {
                Assert.Equal(fromCustomContext.TraceId, testSampler.LatestSamplingParameters.TraceId);
                Assert.Equal(customContext.TraceId, fromCustomContext.TraceId);
                Assert.Equal(customContext.SpanId, fromCustomContext.ParentSpanId);
                Assert.NotEqual(customContext.SpanId, fromCustomContext.SpanId);
            }

            // Validate that when StartActivity is called using Parent as string,
            // Sampling is called correctly.
            var act = new Activity("anything").Start();

            act.Stop();
            var customContextAsString = act.Id;
            var expectedTraceId       = act.TraceId;
            var expectedParentSpanId  = act.SpanId;

            using (var fromCustomContextAsString =
                       activitySource.StartActivity("customContext", ActivityKind.Client, customContextAsString))
            {
                Assert.Equal(fromCustomContextAsString.TraceId, testSampler.LatestSamplingParameters.TraceId);
                Assert.Equal(expectedTraceId, fromCustomContextAsString.TraceId);
                Assert.Equal(expectedParentSpanId, fromCustomContextAsString.ParentSpanId);
            }

            using (var fromInvalidW3CIdParent =
                       activitySource.StartActivity("customContext", ActivityKind.Client, "InvalidW3CIdParent"))
            {
                // OpenTelemetry ActivityContext does not support
                // non W3C Ids. Starting activity with non W3C Ids
                // will result in no activity being created.
                Assert.Null(fromInvalidW3CIdParent);
            }
        }
Example #12
0
        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;
        }
Example #13
0
 internal static Activity?CreateStartedActivity(this ActivitySource source, string activityName, Dictionary <string, string>?tags = null)
 {
     if (!source.HasListeners())
     {
         return(default);
 /// <summary>
 /// Initializes a new instance of the <see cref="MessageMethodHandlingDecorator"/> class.
 /// </summary>
 /// <param name="handler">The handler.</param>
 /// <param name="tracer">The tracer.</param>
 /// <param name="headers">The headers.</param>
 public MessageMethodHandlingDecorator(IMessageMethodHandling handler, ActivitySource tracer, IStandardHeaders headers)
 {
     _handler = handler;
     _tracer  = tracer;
     _headers = headers;
 }
Example #15
0
        internal static Activity CreateTestActivity(
            bool setAttributes = true,
            Dictionary <string, object> additionalAttributes = null,
            bool addEvents    = true,
            bool addLinks     = true,
            Resource resource = null,
            ActivityKind kind = ActivityKind.Client)
        {
            var startTimestamp = DateTime.UtcNow;
            var endTimestamp   = startTimestamp.AddSeconds(60);
            var eventTimestamp = DateTime.UtcNow;
            var traceId        = ActivityTraceId.CreateFromString("e8ea7e9ac72de94e91fabc613f9686b2".AsSpan());

            var parentSpanId = ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 });

            var attributes = new Dictionary <string, object>
            {
                { "stringKey", "value" },
                { "longKey", 1L },
                { "longKey2", 1 },
                { "doubleKey", 1D },
                { "doubleKey2", 1F },
                { "boolKey", true },
            };

            if (additionalAttributes != null)
            {
                foreach (var attribute in additionalAttributes)
                {
                    attributes.Add(attribute.Key, attribute.Value);
                }
            }

            var events = new List <ActivityEvent>
            {
                new ActivityEvent(
                    "Event1",
                    eventTimestamp,
                    new Dictionary <string, object>
                {
                    { "key", "value" },
                }
                    ),
                new ActivityEvent(
                    "Event2",
                    eventTimestamp,
                    new Dictionary <string, object>
                {
                    { "key", "value" },
                }
                    ),
            };

            var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan());

            var activitySource = new ActivitySource(nameof(CreateTestActivity));
            var activity       = activitySource.StartActivity(
                "Name",
                kind,
                parentContext: new ActivityContext(traceId, parentSpanId, ActivityTraceFlags.Recorded),
                tags: setAttributes ?
                // TODO: reverse here for now so it matches order in tests.
                attributes.Reverse().Select(kvp => new KeyValuePair <string, string>(kvp.Key, kvp.Value.ToString()))
                    : null,
                links: addLinks ?
                new[] { new ActivityLink(new ActivityContext(
                                             traceId,
                                             linkedSpanId,
                                             ActivityTraceFlags.Recorded)), }
                    : null,
                startTime: startTimestamp);

            if (addEvents)
            {
                // TODO: reverse here for now so it matches order in tests.
                events.Reverse();
                foreach (var evnt in events)
                {
                    activity.AddEvent(evnt);
                }
            }

            activity.SetEndTime(endTimestamp);
            activity.Stop();

            return(activity);
        }
        public void ToOtlpSpanTest()
        {
            var activitySource = new ActivitySource(nameof(this.ToOtlpSpanTest));

            using var rootActivity = activitySource.StartActivity("root", ActivityKind.Producer);

            var attributes = new Dictionary <string, object>
            {
                ["bool"]   = true,
                ["long"]   = 1L,
                ["string"] = "text",
                ["double"] = 3.14,
                ["unknown_attrib_type"] =
                    new byte[] { 1 }, // TODO: update if arrays of standard attribute types are supported
            };

            var tags = new List <KeyValuePair <string, string> >(attributes.Count);

            foreach (var kvp in attributes)
            {
                rootActivity.AddTag(kvp.Key, kvp.Value.ToString());
                tags.Add(new KeyValuePair <string, string>(kvp.Key, kvp.Value.ToString()));
            }

            var startTime             = new DateTime(2020, 02, 20, 20, 20, 20, DateTimeKind.Utc);
            var expectedUnixTimeTicks = (ulong)(startTime.Ticks - DateTimeOffset.FromUnixTimeMilliseconds(0).Ticks);
            var duration = TimeSpan.FromMilliseconds(1555);

            rootActivity.SetStartTime(startTime);
            rootActivity.SetEndTime(startTime + duration);

            Span <byte> traceIdSpan = stackalloc byte[16];

            rootActivity.TraceId.CopyTo(traceIdSpan);
            var traceId = traceIdSpan.ToArray();

            var otlpSpan = rootActivity.ToOtlpSpan();

            Assert.NotNull(otlpSpan);
            Assert.Equal("root", otlpSpan.Name);
            Assert.Equal(OtlpTrace.Span.Types.SpanKind.Producer, otlpSpan.Kind);
            Assert.Equal(traceId, otlpSpan.TraceId);
            Assert.Empty(otlpSpan.ParentSpanId);
            Assert.Null(otlpSpan.Status);
            Assert.Empty(otlpSpan.Events);
            Assert.Empty(otlpSpan.Links);
            AssertActivityTagsIntoOtlpAttributes(tags, otlpSpan.Attributes);

            var expectedStartTimeUnixNano = 100 * expectedUnixTimeTicks;

            Assert.Equal(expectedStartTimeUnixNano, otlpSpan.StartTimeUnixNano);
            var expectedEndTimeUnixNano = expectedStartTimeUnixNano + (duration.TotalMilliseconds * 1_000_000);

            Assert.Equal(expectedEndTimeUnixNano, otlpSpan.EndTimeUnixNano);

            var childLinks = new List <ActivityLink> {
                new ActivityLink(rootActivity.Context, attributes)
            };
            var childActivity = activitySource.StartActivity(
                "child",
                ActivityKind.Client,
                rootActivity.Context,
                links: childLinks);

            var childEvents = new List <ActivityEvent> {
                new ActivityEvent("e0"), new ActivityEvent("e1", attributes)
            };

            childActivity.AddEvent(childEvents[0]);
            childActivity.AddEvent(childEvents[1]);

            Span <byte> parentIdSpan = stackalloc byte[8];

            rootActivity.Context.SpanId.CopyTo(parentIdSpan);
            var parentId = parentIdSpan.ToArray();

            otlpSpan = childActivity.ToOtlpSpan();

            Assert.NotNull(otlpSpan);
            Assert.Equal("child", otlpSpan.Name);
            Assert.Equal(OtlpTrace.Span.Types.SpanKind.Client, otlpSpan.Kind);
            Assert.Equal(traceId, otlpSpan.TraceId);
            Assert.Equal(parentId, otlpSpan.ParentSpanId);
            Assert.Empty(otlpSpan.Attributes);

            Assert.Equal(childEvents.Count, otlpSpan.Events.Count);
            for (var i = 0; i < childEvents.Count; i++)
            {
                Assert.Equal(childEvents[i].Name, otlpSpan.Events[i].Name);
                AssertOtlpAttributes(childEvents[i].Attributes.ToList(), otlpSpan.Events[i].Attributes);
            }

            childLinks.Reverse();
            Assert.Equal(childLinks.Count, otlpSpan.Links.Count);
            for (var i = 0; i < childLinks.Count; i++)
            {
                AssertOtlpAttributes(childLinks[i].Attributes.ToList(), otlpSpan.Links[i].Attributes);
            }
        }
Example #17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RollbackMessageCommandHandlerDecorator"/> class.
 /// </summary>
 /// <param name="handler">The handler.</param>
 /// <param name="tracer">The tracer.</param>
 public RollbackMessageCommandHandlerDecorator(ICommandHandler <RollbackMessageCommand <string> > handler, ActivitySource tracer)
 {
     _handler = handler;
     _tracer  = tracer;
 }
Example #18
0
        static void Main(string[] args)
        {
            Console.WriteLine("Peloton To Garmin");
            var config = new Configuration();

            Health.Set(HealthStatus.Healthy);

            var runtimeVersion = Environment.Version.ToString();
            var os             = Environment.OSVersion.Platform.ToString();
            var osVersion      = Environment.OSVersion.VersionString;
            var assembly       = Assembly.GetExecutingAssembly();
            var versionInfo    = FileVersionInfo.GetVersionInfo(assembly.Location);
            var version        = versionInfo.ProductVersion;

            try
            {
                IConfiguration configProviders = new ConfigurationBuilder()
                                                 .AddJsonFile(Path.Join(Environment.CurrentDirectory, "configuration.local.json"), optional: true, reloadOnChange: true)
                                                 .AddEnvironmentVariables(prefix: "P2G_")
                                                 .AddCommandLine(args)
                                                 .Build();

                configProviders.GetSection(nameof(App)).Bind(config.App);
                configProviders.GetSection(nameof(Format)).Bind(config.Format);
                configProviders.GetSection(nameof(Peloton)).Bind(config.Peloton);
                configProviders.GetSection(nameof(Garmin)).Bind(config.Garmin);
                configProviders.GetSection(nameof(Observability)).Bind(config.Observability);
                configProviders.GetSection(nameof(Developer)).Bind(config.Developer);

                // https://github.com/serilog/serilog-settings-configuration
                Log.Logger = new LoggerConfiguration()
                             .ReadFrom.Configuration(configProviders, sectionName: $"{nameof(Observability)}:Serilog")
                             .Enrich.WithSpan()
                             .CreateLogger();

                ChangeToken.OnChange(() => configProviders.GetReloadToken(), () =>
                {
                    Log.Information("Config change detected, reloading config values.");
                    configProviders.GetSection(nameof(App)).Bind(config.App);
                    configProviders.GetSection(nameof(Format)).Bind(config.Format);
                    configProviders.GetSection(nameof(Peloton)).Bind(config.Peloton);
                    configProviders.GetSection(nameof(Garmin)).Bind(config.Garmin);
                    configProviders.GetSection(nameof(Developer)).Bind(config.Developer);

                    GarminUploader.ValidateConfig(config);

                    Log.Information("Config reloaded. Changes will take effect at the end of the current sleeping cycle.");
                });

                Log.Debug("P2G Version: {@Version}", version);
                Log.Debug("Operating System: {@Os}", osVersion);
                Log.Debug("DotNet Runtime: {@DotnetRuntime}", runtimeVersion);

                PelotonService.ValidateConfig(config.Peloton);
                GarminUploader.ValidateConfig(config);
                Common.Metrics.ValidateConfig(config.Observability);
                Tracing.ValidateConfig(config.Observability);

                FlurlConfiguration.Configure(config);
            }
            catch (Exception e)
            {
                Log.Fatal(e, "Exception during config setup.");
                Health.Set(HealthStatus.Dead);
                throw;
            }

            IDisposable dotNetRuntimeMetrics = null;

            try
            {
                using var metrics       = Common.Metrics.EnableMetricsServer(config.Observability.Prometheus);
                using var tracing       = Tracing.EnableTracing(config.Observability.Jaeger);
                using var tracingSource = new ActivitySource("ROOT");

                if (config.Observability.Prometheus.Enabled)
                {
                    dotNetRuntimeMetrics = DotNetRuntimeStatsBuilder
                                           .Customize()
                                           .WithContentionStats()
                                           .WithJitStats()
                                           .WithThreadPoolStats()
                                           .WithGcStats()
                                           .WithExceptionStats()
                                           .StartCollecting();
                }

                BuildInfo.WithLabels(version, os, osVersion, runtimeVersion).Set(1);

                if (config.Peloton.NumWorkoutsToDownload <= 0)
                {
                    Console.Write("How many workouts to grab? ");
                    int num = Convert.ToInt32(Console.ReadLine());
                    config.Peloton.NumWorkoutsToDownload = num;
                }

                if (config.App.EnablePolling)
                {
                    while (config.App.EnablePolling)
                    {
                        RunAsync(config).GetAwaiter().GetResult();
                        Log.Information("Sleeping for {@Seconds} seconds...", config.App.PollingIntervalSeconds);

                        var now         = DateTime.UtcNow;
                        var nextRunTime = now.AddSeconds(config.App.PollingIntervalSeconds);
                        NextSyncTime.Set(new DateTimeOffset(nextRunTime).ToUnixTimeSeconds());
                        Thread.Sleep(config.App.PollingIntervalSeconds * 1000);
                    }
                }
                else
                {
                    RunAsync(config).GetAwaiter().GetResult();
                }
            }
            catch (Exception e)
            {
                Log.Fatal(e, "Uncaught Exception.");
                Health.Set(HealthStatus.Dead);
            }
            finally
            {
                Log.CloseAndFlush();
                Console.ReadLine();
                dotNetRuntimeMetrics?.Dispose();
            }
        }
Example #19
0
        public async Task CheckingZPagesProcessor()
        {
            const string          ActivitySourceName = "zpages.test";
            ZPagesExporterOptions options            = new ZPagesExporterOptions
            {
                RetentionTime = 100_000,
                Url           = "http://localhost:7284/rpcz/",
            };
            ZPagesExporter exporter        = new ZPagesExporter(options);
            var            zpagesProcessor = new ZPagesProcessor(exporter);

            var source    = new ActivitySource(ActivitySourceName);
            var activity0 = source.StartActivity("Test Zipkin Activity 1");

            zpagesProcessor.OnStart(activity0);

            // checking size of dictionaries from ZPagesActivityTracker
            Assert.Equal(1, ZPagesActivityTracker.ProcessingList.First().Value);
            Assert.Equal(1, ZPagesActivityTracker.TotalCount.First().Value);
            Assert.Single(ZPagesActivityTracker.TotalEndedCount);
            Assert.Single(ZPagesActivityTracker.TotalErrorCount);
            Assert.Single(ZPagesActivityTracker.TotalLatency);

            var activity1 = source.StartActivity("Test Zipkin Activity 1");

            zpagesProcessor.OnStart(activity1);

            // checking size of dictionaries from ZPagesActivityTracker
            Assert.Equal(2, ZPagesActivityTracker.ProcessingList.First().Value);
            Assert.Equal(2, ZPagesActivityTracker.TotalCount.First().Value);
            Assert.Single(ZPagesActivityTracker.TotalEndedCount);
            Assert.Single(ZPagesActivityTracker.TotalErrorCount);
            Assert.Single(ZPagesActivityTracker.TotalLatency);

            var activity2 = source.StartActivity("Test Zipkin Activity 2");

            zpagesProcessor.OnStart(activity2);

            // checking size of dictionaries from ZPagesActivityTracker
            Assert.Equal(2, ZPagesActivityTracker.ProcessingList.Count);
            Assert.Equal(2, ZPagesActivityTracker.TotalCount.Count);
            Assert.Equal(2, ZPagesActivityTracker.TotalEndedCount.Count);
            Assert.Equal(2, ZPagesActivityTracker.TotalErrorCount.Count);
            Assert.Equal(2, ZPagesActivityTracker.TotalLatency.Count);

            activity0?.Stop();
            activity1?.Stop();
            activity2?.Stop();
            zpagesProcessor.OnEnd(activity0);
            zpagesProcessor.OnEnd(activity1);
            zpagesProcessor.OnEnd(activity2);

            // checking if activities were processed
            Assert.Equal(0, ZPagesActivityTracker.ProcessingList.First().Value);
            Assert.Equal(0, ZPagesActivityTracker.ProcessingList.Last().Value);
            Assert.Empty(ZPagesActivityTracker.ZQueue);

            var zpagesServer = new ZPagesExporterStatsHttpServer(exporter);

            zpagesServer.Start();

            using var httpResponseMessage = await HttpClient.GetAsync("http://localhost:7284/rpcz/");

            Assert.True(httpResponseMessage.IsSuccessStatusCode);

            var content = await httpResponseMessage.Content.ReadAsStringAsync();

            Assert.Contains($"<td>Test Zipkin Activity 1</td>", content);
            Assert.Contains($"<td>Test Zipkin Activity 2</td>", content);

            zpagesProcessor.Dispose();
            zpagesServer.Stop();
            zpagesServer.Dispose();
            exporter.Dispose();
        }
Example #20
0
 internal Tracer(ActivitySource activitySource)
 {
     this.ActivitySource = activitySource;
 }
        internal static object Run(ConsoleOptions options)
        {
            // Enable OpenTelemetry for the source "MyCompany.MyProduct.MyWebServer"
            // and use a single pipeline with a custom MyProcessor, and Console exporter.
            using var openTelemetry = OpenTelemetrySdk.EnableOpenTelemetry(
                      (builder) => builder.AddActivitySource("MyCompany.MyProduct.MyWebServer")
                      .SetResource(Resources.CreateServiceResource("MyServiceName"))
                      .UseConsoleExporter(opt => opt.DisplayAsJson = options.DisplayAsJson,
                                          (p) => p.AddProcessor((next) => new MyProcessor(next))));

            // The above line is required only in applications
            // which decide to use Open Telemetry.

            // Libraries would simply write the following lines of code to
            // emit activities, which are the .NET representation of OT Spans.
            var source = new ActivitySource("MyCompany.MyProduct.MyWebServer");

            // The below commented out line shows more likely code in a real world webserver.
            // using (var parent = source.StartActivity("HttpIn", ActivityKind.Server, HttpContext.Request.Headers["traceparent"] ))
            using (var parent = source.StartActivity("HttpIn", ActivityKind.Server))
            {
                // TagNames can follow the OT guidelines
                // from https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/trace/semantic_conventions
                parent?.AddTag("http.method", "GET");
                parent?.AddTag("http.host", "MyHostName");
                if (parent != null)
                {
                    parent.DisplayName = "HttpIn DisplayName";

                    // IsAllDataRequested is equivalent of Span.IsRecording
                    if (parent.IsAllDataRequested)
                    {
                        parent.AddTag("expensive data", "This data is expensive to obtain. Avoid it if activity is not being recorded");
                    }
                }

                try
                {
                    // Actual code to achieve the purpose of the library.
                    // For websebserver example, this would be calling
                    // user middlware pipeline.

                    // There can be child activities.
                    // In this example HttpOut is a child of HttpIn.
                    using (var child = source.StartActivity("HttpOut", ActivityKind.Client))
                    {
                        child?.AddTag("http.url", "www.mydependencyapi.com");
                        try
                        {
                            // do actual work.

                            child?.AddEvent(new ActivityEvent("sample activity event."));
                            child?.AddTag("http.status_code", "200");
                        }
                        catch (Exception)
                        {
                            child?.AddTag("http.status_code", "500");
                        }
                    }

                    parent?.AddTag("http.status_code", "200");
                }
                catch (Exception)
                {
                    parent?.AddTag("http.status_code", "500");
                }
            }

            System.Console.WriteLine("Press Enter key to exit.");

            return(null);
        }
Example #22
0
 public DynamoDbItemService(Settings settings, ActivitySource activitySource)
 {
     _jsonSerializer = new JsonSerializer();
     _settings       = settings;
     _activitySource = activitySource;
 }
Example #23
0
        private static async Task RunAsync()
        {
            var endpoint = "/delay/5ms";

            using var listener = new HttpEventListener();

            source = new ActivitySource("http-client-test");

            var serviceCollection = new ServiceCollection();

            serviceCollection.AddHttpOptionsTelemetry(builder => builder.AddConsoleExporter());


            serviceCollection.AddHttpClientOptions(options =>
            {
                options.ServiceName           = "service";
                options.Handler.MaxConnection = 500;
                _server.ConfigureWireMockServer(options);
            });


            var services =
                serviceCollection.BuildServiceProvider();
            await Task.WhenAll(services.GetServices <IHostedService>()
                               .Select(e => e.StartAsync(CancellationToken.None)));

            var factory = services.GetRequiredService <IHttpClientFactory>();
            var client  = factory.CreateClient("service");

            var stopwatch = Stopwatch.StartNew();

            Console.WriteLine("oooo: ");

            do
            {
                try
                {
                    await client.GetAsync(endpoint).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                }
            } while (Console.ReadKey().Key != ConsoleKey.Escape);


            do
            {
                try
                {
                    var activityLinks = new List <ActivityLink>();
                    var initialTags   = new ActivityTagsCollection();

                    initialTags["com.mycompany.product.mytag1"] = "tagValue1";
                    initialTags["com.mycompany.product.mytag2"] = "tagValue2";

                    var linkedContext1 = new ActivityContext(
                        ActivityTraceId.CreateRandom(),
                        ActivitySpanId.CreateRandom(),
                        ActivityTraceFlags.None);

                    var linkedContext2 = new ActivityContext(
                        ActivityTraceId.CreateRandom(),
                        ActivitySpanId.CreateRandom(),
                        ActivityTraceFlags.Recorded);

                    activityLinks.Add(new ActivityLink(linkedContext1));
                    activityLinks.Add(new ActivityLink(linkedContext2));


                    using var activity = source.StartActivity(
                              "ActivityWithLinks",
                              ActivityKind.Server,
                              default(ActivityContext),
                              initialTags,
                              activityLinks);
                    var latencyStats = await TrafficGenerator
                                       .GenerateTraffic(100, () => client.GetAsync(endpoint))
                                       .Latency()
                                       .TakeUntil(DateTimeOffset.Now.AddSeconds(20));

                    Console.WriteLine(latencyStats.Print());
                    await client.GetAsync(endpoint).ConfigureAwait(false);

                    System.Console.WriteLine("Press Enter key to continue.");
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            } while (Console.ReadKey().Key != ConsoleKey.Escape);
        }
        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));
            }
        }
Example #25
0
        public void ToOtlpSpanTest()
        {
            var activitySource = new ActivitySource(nameof(this.ToOtlpSpanTest));

            using var rootActivity = activitySource.StartActivity("root", ActivityKind.Producer);

            var attributes = new List <KeyValuePair <string, object> >
            {
                new KeyValuePair <string, object>("bool", true),
                new KeyValuePair <string, object>("long", 1L),
                new KeyValuePair <string, object>("string", "text"),
                new KeyValuePair <string, object>("double", 3.14),
                new KeyValuePair <string, object>("int", 1),
                new KeyValuePair <string, object>("datetime", DateTime.UtcNow),
                new KeyValuePair <string, object>("bool_array", new bool[] { true, false }),
                new KeyValuePair <string, object>("int_array", new int[] { 1, 2 }),
                new KeyValuePair <string, object>("double_array", new double[] { 1.0, 2.09 }),
                new KeyValuePair <string, object>("string_array", new string[] { "a", "b" }),
            };

            foreach (var kvp in attributes)
            {
                rootActivity.SetTag(kvp.Key, kvp.Value);
            }

            var startTime = new DateTime(2020, 02, 20, 20, 20, 20, DateTimeKind.Utc);

            DateTimeOffset dateTimeOffset;

#if NET452
            dateTimeOffset = DateTimeOffsetExtensions.FromUnixTimeMilliseconds(0);
#else
            dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(0);
#endif

            var expectedUnixTimeTicks = (ulong)(startTime.Ticks - dateTimeOffset.Ticks);
            var duration = TimeSpan.FromMilliseconds(1555);

            rootActivity.SetStartTime(startTime);
            rootActivity.SetEndTime(startTime + duration);

            Span <byte> traceIdSpan = stackalloc byte[16];
            rootActivity.TraceId.CopyTo(traceIdSpan);
            var traceId = traceIdSpan.ToArray();

            var otlpSpan = rootActivity.ToOtlpSpan();

            Assert.NotNull(otlpSpan);
            Assert.Equal("root", otlpSpan.Name);
            Assert.Equal(OtlpTrace.Span.Types.SpanKind.Producer, otlpSpan.Kind);
            Assert.Equal(traceId, otlpSpan.TraceId);
            Assert.Empty(otlpSpan.ParentSpanId);
            Assert.Null(otlpSpan.Status);
            Assert.Empty(otlpSpan.Events);
            Assert.Empty(otlpSpan.Links);
            AssertOtlpAttributes(attributes, otlpSpan.Attributes);

            var expectedStartTimeUnixNano = 100 * expectedUnixTimeTicks;
            Assert.Equal(expectedStartTimeUnixNano, otlpSpan.StartTimeUnixNano);
            var expectedEndTimeUnixNano = expectedStartTimeUnixNano + (duration.TotalMilliseconds * 1_000_000);
            Assert.Equal(expectedEndTimeUnixNano, otlpSpan.EndTimeUnixNano);

            var childLinks = new List <ActivityLink> {
                new ActivityLink(rootActivity.Context, new ActivityTagsCollection(attributes))
            };
            var childActivity = activitySource.StartActivity(
                "child",
                ActivityKind.Client,
                rootActivity.Context,
                links: childLinks);

            childActivity.SetStatus(Status.Error);

            var childEvents = new List <ActivityEvent> {
                new ActivityEvent("e0"), new ActivityEvent("e1", default, new ActivityTagsCollection(attributes))
 static DotPulsarActivitySource()
 {
     ActivitySource = new ActivitySource(Constants.ClientName, Constants.ClientVersion);
 }
Example #27
0
        static async Task Main(string[] args)
        {
            var opts = new OptionSet()
            {
                { "u|user="******"(REQUIRED) A github user with admin access.", u => Config.Github.User = u }
                , { "t|token=", "(REQUIRED) A github token that has admin access to the org.", t => Config.Github.Token = t }
                , { "o|org=", "The organization we need to run the actions against (defaults to `sectigo-eng`)", o => Config.Github.Org = o }
                , { "teams=", "A file with the desired team structure in JSON format. If this is set, this will enforce that team structure (including removing members from teams). We expect a Dictionary where the key is the team name, and the value a list of string with the user login names.", ts => Config.TeamStructureFile = ts }
                , { "repos=", "A file with the desired repository teams access in JSON format.", rs => Config.RepoStructureFile = rs }
                , { "report=", "The path were we output the audit report. This defaults to ./", o => Config.ReportingPath = o }
                , { "d|dryrun=", "Should this run authoritative updates (`no`-dryrun), or only display changes (`yes`.Run a dryrun please). Must be either 'yes' or 'no'. Defaults to 'yes'.", (string dry) => Config.DryRunMode = dry.ToLower() }
                , { "no-dryrun", "Run authoritative updates. This can be destructive. This is the greedy option over --dryrun=yes|no.", d => Config.DryRunMode = "no" }
                , { "validate=", "Should this run include validation checks .Runes X exist or not). Excluding these (or `only` running these) saves significant api hits for rate limiting. Must be either `yes` or `no` or `only`. Defaults to `yes`", (string val) => Config.ValidationMode = val.ToLower() }
                , { "tags=", "Only runs the tasks listed here. Note that if this argument is specified, and is inclusive, any tasks that do not have tags will not be run. Expects a CSV. By default everything runs. Current options are `OnlyTeams`", tags => Config.WithTags = new List <string>(tags.Split(',').Where(s => !string.IsNullOrWhiteSpace(s))) }
                , { "e=", "Can only be used with --tags. While exclude any tags listed from the current run. Can be used as a flag, or value of `yes` or `no` Defaults to off.)", (string exclude) => Config.ExludeTagsMode = exclude }
                , { "contextPath=", "If set, will load all the supported manifests (yaml or yml) from that directory, and those will apply to the settings. Path has to exists.", c => Config.ContextPath = c }
                , { "h|help", p => Config.Help = true }
            };

            try
            {
                opts.Parse(args);
                Console.WriteLine($"Current configuration: {Config.ToString()}");
            }
            catch (OptionException e)
            {
                Console.WriteLine(e.Message);
                return;
            }

            if (!Config.ValidateInput() || Config.Help)
            {
                opts.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (Config.Honeycomb.Validate())
            {
                Console.WriteLine("Setting up telemetry");
                source = new ActivitySource("gitman.App", "1.0.0");
                tracer = Sdk
                         .CreateTracerProviderBuilder()
                         .AddHoneycomb(new HoneycombOptions
                {
                    ServiceName = Config.Honeycomb.ServiceName,
                    ApiKey      = Config.Honeycomb.ApiKey,
                    Dataset     = Config.Honeycomb.Dataset
                })
                         .AddSource("gitman.*")
                         .Build();
            }

            using var root = source?.StartActivity("app");

            if (!Config.DryRun)
            {
                Console.WriteLine("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                Console.WriteLine("!!!                                 Non-DryRun mode                                     !!!");
                if (Config.OnlyValidate)
                {
                    Console.WriteLine("!!!       But w're only running in validation mode, so there shouldn't be changes.      !!!");
                }
                else
                {
                    Console.WriteLine("!!!                              Changes WILL BE authorative                            !!!");
                }
                Console.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n");
            }

            // For the github sdk to allow us to specify our GithubHttpCache, we have to add all this other
            // nonsense to it.
            client = new GitHubClient(new Connection(
                                          new ProductHeaderValue("SuperMassiveCLI")
                                          , GitHubClient.GitHubApiUrl
                                          , new InMemoryCredentialStore(Credentials.Anonymous)
                                          // this is the only thing that really matters in this instantiation. There is no other way
                                          // to set this up.
                                          , new Octokit.Internal.HttpClientAdapter(() => new Helpers.GithubHttpCache())
                                          , new Octokit.Internal.SimpleJsonSerializer()
                                          ));
            client.Credentials = new Credentials(Config.Github.User, Config.Github.Token);

            var loader = new ResourceLoader();

            if (!string.IsNullOrEmpty(Config.ContextPath))
            {
                loader.LoadResources(Config.ContextPath);
            }

            Console.WriteLine("\n\nChecking merge setting");
            await new Merging {
                Client = client, Loader = loader
            }.Run();

            Console.WriteLine("\n\nChecking branch protections");
            await new Protection()
            {
                Client = client, Loader = loader
            }.Run();

            Console.WriteLine("\n\nPerforming team audit");
            var audit = new Audit(outputPath: Config.ReportingPath)
            {
                Client = client
            };
            await audit.Run();

            if (Config.HasTeamsStructureFile)
            {
                var repository_description = GetRepositoryDescription();
                var proposed_teams         = GetTeams();

                Console.WriteLine($"\n\nChecking for solo collaborators");
                await new OnlyTeams(repository_description, proposed_teams)
                {
                    Client = client
                }.Run();

                Console.WriteLine("\n\nChecking teams");
                await new Teams(proposed_teams)
                {
                    Client = client
                }.Run();

                Console.WriteLine("\n\nChecking teams memberships");
                await new TeamMemberships(proposed_teams)
                {
                    Client = client
                }.Run();


                if (Config.HasRepoStructureFile)
                {
                    Console.WriteLine("\n\nChecking collaborators repository access");
                    await new RepositoryAccess(repository_description, proposed_teams.Keys)
                    {
                        Client = client
                    }.Run();
                }
            }
        }
        public void IncomingRequestOneWayOperationInstrumentationTest()
        {
            List <Activity> stoppedActivities = new List <Activity>();

            using ActivityListener activityListener = new ActivityListener
                  {
                      ShouldListenTo  = activitySource => true,
                      ActivityStopped = activity => stoppedActivities.Add(activity),
                  };

            ActivitySource.AddActivityListener(activityListener);
            TracerProvider tracerProvider = Sdk.CreateTracerProviderBuilder()
                                            .AddWcfInstrumentation()
                                            .Build();

            ServiceClient client = new ServiceClient(
                new NetTcpBinding(),
                new EndpointAddress(new Uri(this.serviceBaseUri, "/Service")));

            try
            {
                client.ExecuteWithOneWay(new ServiceRequest());
                this.thrownExceptionsHandle.WaitOne(3000);
            }
            finally
            {
                if (client.State == CommunicationState.Faulted)
                {
                    client.Abort();
                }
                else
                {
                    client.Close();
                }

                tracerProvider?.Shutdown();
                tracerProvider?.Dispose();

                WcfInstrumentationActivitySource.Options = null;
            }

            // Assert
            Assert.Empty(this.thrownExceptions);

            Assert.NotEmpty(stoppedActivities);
            Assert.Single(stoppedActivities);

            Activity activity = stoppedActivities[0];

            Assert.Equal("http://opentelemetry.io/Service/ExecuteWithOneWay", activity.DisplayName);
            Assert.Equal("ExecuteWithOneWay", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcMethodTag).Value);
            Assert.DoesNotContain(activity.TagObjects, t => t.Key == WcfInstrumentationConstants.SoapReplyActionTag);

            Assert.Equal(WcfInstrumentationActivitySource.IncomingRequestActivityName, activity.OperationName);
            Assert.Equal(WcfInstrumentationConstants.WcfSystemValue, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcSystemTag).Value);
            Assert.Equal("http://opentelemetry.io/Service", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.RpcServiceTag).Value);
            Assert.Equal(this.serviceBaseUri.Host, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.NetHostNameTag).Value);
            Assert.Equal(this.serviceBaseUri.Port, activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.NetHostPortTag).Value);
            Assert.Equal("net.tcp", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.WcfChannelSchemeTag).Value);
            Assert.Equal("/Service", activity.TagObjects.FirstOrDefault(t => t.Key == WcfInstrumentationConstants.WcfChannelPathTag).Value);
        }
Example #29
0
        internal static Activity CreateTestActivity(
            bool setAttributes = true,
            Dictionary <string, object> additionalAttributes = null,
            bool addEvents    = true,
            bool addLinks     = true,
            Resource resource = null,
            ActivityKind kind = ActivityKind.Client)
        {
            var startTimestamp = DateTime.UtcNow;
            var endTimestamp   = startTimestamp.AddSeconds(60);
            var eventTimestamp = DateTime.UtcNow;
            var traceId        = ActivityTraceId.CreateFromString("e8ea7e9ac72de94e91fabc613f9686b2".AsSpan());

            var parentSpanId = ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 });

            var attributes = new Dictionary <string, object>
            {
                { "stringKey", "value" },
                { "longKey", 1L },
                { "longKey2", 1 },
                { "doubleKey", 1D },
                { "doubleKey2", 1F },
                { "boolKey", true },
                { "int_array", new int[] { 1, 2 } },
                { "bool_array", new bool[] { true, false } },
                { "double_array", new double[] { 1.0, 1.1 } },
                { "string_array", new string[] { "a", "b" } },
            };

            if (additionalAttributes != null)
            {
                foreach (var attribute in additionalAttributes)
                {
                    attributes.Add(attribute.Key, attribute.Value);
                }
            }

            var events = new List <ActivityEvent>
            {
                new ActivityEvent(
                    "Event1",
                    eventTimestamp,
                    new ActivityTagsCollection(new Dictionary <string, object>
                {
                    { "key", "value" },
                })),
                new ActivityEvent(
                    "Event2",
                    eventTimestamp,
                    new ActivityTagsCollection(new Dictionary <string, object>
                {
                    { "key", "value" },
                })),
            };

            var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan());

            var activitySource = new ActivitySource(nameof(CreateTestActivity));

            var tags = setAttributes ?
                       attributes
                    : null;
            var links = addLinks ?
                        new[]
            {
                new ActivityLink(new ActivityContext(
                                     traceId,
                                     linkedSpanId,
                                     ActivityTraceFlags.Recorded)),
            }
                    : null;

            var activity = activitySource.StartActivity(
                "Name",
                kind,
                parentContext: new ActivityContext(traceId, parentSpanId, ActivityTraceFlags.Recorded),
                tags,
                links,
                startTime: startTimestamp);

            if (addEvents)
            {
                foreach (var evnt in events)
                {
                    activity.AddEvent(evnt);
                }
            }

            activity.SetEndTime(endTimestamp);
            activity.Stop();

            return(activity);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="SendMessageCommandHandlerDecorator"/> class.
 /// </summary>
 /// <param name="handler">The handler.</param>
 /// <param name="tracer">The tracer.</param>
 /// <param name="headers">The headers.</param>
 /// <param name="connectionInformation">The connection information.</param>
 public SendMessageCommandHandlerDecorator(ICommandHandlerWithOutput <SendMessageCommand, long> handler, ActivitySource tracer,
                                           IHeaders headers, IConnectionInformation connectionInformation)
 {
     _handler = handler;
     _tracer  = tracer;
     _headers = headers;
     _connectionInformation = connectionInformation;
 }