예제 #1
0
        public async Task RecordBinary_WithoutTraceId_NotCallRecordOnSpanTracer()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);

            await zipkinClient.RecordBinary <object>(null, null, null);

            await zipkinClient.RecordBinary <object>(null, "value", null);

            await zipkinClient.RecordBinary <object>(null, "value", new object());

            await zipkinClient.RecordBinary <object>(null, null, new object());

            await zipkinClient.RecordBinary <object>(null, null, new object());

            await zipkinClient.RecordBinary <object>(new Span("span", null), null, null);

            await zipkinClient.RecordBinary <object>(new Span("span", null), null, new object());

            await zipkinClient.RecordBinary <object>(new Span("span", null), "value", null);

            await zipkinClient.RecordBinary <object>(new Span("span", null), "value", new object());

            await spanTracer.DidNotReceiveWithAnyArgs().RecordBinary(null, null, null);
        }
예제 #2
0
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);

            var zipkinConfig = new ZipkinConfig
            {
                Domain =
                    request => new Uri(
                        "https://listing.hepsiburada.com"),
                ZipkinBaseUri          = new Uri("http://192.168.99.100:32776"),
                SpanProcessorBatchSize = 1,
                SampleRate             = 1
            };

            //ioc
            var builder = new ContainerBuilder();

            var config = GlobalConfiguration.Configuration;

            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

            builder.RegisterWebApiFilterProvider(config);

            builder.RegisterWebApiModelBinderProvider();

            builder.Register(c => new ZipkinClient(zipkinConfig, HttpContext.Current)).As <IZipkinClient>()
            .SingleInstance();

            var container = builder.Build();

            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        }
예제 #3
0
        public SpanProcessor(ISpanProcessorTask spanProcessorTask, ISpanCollector spanCollector,
                             ZipkinConfig zipkinConfig, ILogger <SpanProcessor> logger)
        {
            if (spanProcessorTask == null)
            {
                throw new ArgumentNullException(nameof(spanProcessorTask));
            }
            if (spanCollector == null)
            {
                throw new ArgumentNullException(nameof(spanCollector));
            }
            if (zipkinConfig == null)
            {
                throw new ArgumentNullException(nameof(zipkinConfig));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            _zipkinConfig      = zipkinConfig;
            _spanCollector     = spanCollector;
            _serializableSpans = new ConcurrentQueue <JsonSpan>();
            _logger            = logger;
            _spanProcessorTask = spanProcessorTask;
        }
예제 #4
0
        public void Init(HttpApplication context)
        {
            context.BeginRequest += (sender, args) =>
            {
                string url = HttpContext.Current.Request.Path;

                var zipkinConfig = new ZipkinConfig();

                var traceProvider = new TraceProvider(new System.Web.HttpContextWrapper(HttpContext.Current), zipkinConfig.DontSampleListCsv, zipkinConfig.ZipkinSampleRate);
                var logger        = new MDLogger(LogManager.GetLogger(this.GetType()), traceProvider, new AssemblyInformation());

                ITracerClient zipkinClient = new ZipkinClient(traceProvider, url, logger);

                zipkinClient.StartServerTrace();

                HttpContext.Current.Items["zipkinClient"] = zipkinClient;

                var stopwatch = new Stopwatch();
                HttpContext.Current.Items["zipkinStopwatch"] = stopwatch;
                stopwatch.Start();
            };

            context.EndRequest += (sender, args) =>
            {
                var stopwatch = (Stopwatch)HttpContext.Current.Items["zipkinStopwatch"];
                stopwatch.Stop();

                var zipkinClient = (ITracerClient)HttpContext.Current.Items["zipkinClient"];

                zipkinClient.EndServerTrace(stopwatch.Elapsed.Milliseconds * 1000);
            };
        }
예제 #5
0
        private void Application_EndRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext     context     = application.Context;

            if (_client == null && HttpContext.Current != null && HttpContext.Current.Handler != null)
            {
                var zipkinConfig = new ZipkinConfig
                {
                    Domain =
                        request => new Uri(
                            "https://product.hepsiburada.com"),
                    ZipkinBaseUri          = new Uri("http://192.168.99.100:32772"),
                    SpanProcessorBatchSize = 1,
                    SampleRate             = 1
                };

                _client = new ZipkinClient(zipkinConfig, HttpContext.Current);
            }
            if (_client != null)
            {
                var spanData = context.Items["span"];
                if (spanData != null)
                {
                    var span = spanData as Span;
                    _client.EndServerTrace(span);
                    context.Items.Remove("span");
                }
            }
        }
예제 #6
0
        private void Application_BeginRequest(Object source,
                                              EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext     context     = application.Context;

            if (_client == null && HttpContext.Current != null && HttpContext.Current.Handler != null)
            {
                var zipkinConfig = new ZipkinConfig
                {
                    Domain =
                        request => new Uri(
                            "https://product.hepsiburada.com"),
                    ZipkinBaseUri          = new Uri("http://192.168.99.100:32772"),
                    SpanProcessorBatchSize = 1,
                    SampleRate             = 1
                };

                _client = new ZipkinClient(zipkinConfig, HttpContext.Current);
            }
            if (_client != null)
            {
                Span span = _client.StartServerTrace(context.Request.Url, context.Request.HttpMethod);
                context.Items.Add("span", span);
            }
        }
예제 #7
0
        public async Task ReceiveServerSpan_InCorrectRequest_ReturnTraceSpan1()
        {
            var requestUri   = new Uri("http://server.com:999/api");
            var requestName  = "request";
            var traceId      = "traceId";
            var parentSpanId = "parentSpanId";
            var spanId       = "spanId";

            var spanCollector  = Substitute.For <ISpanCollector>();
            var zipkinEndpoint = Substitute.For <IServiceEndpoint>();
            var zipkinConfig   = new ZipkinConfig(new Uri("http://localhost"));
            var localEndpoint  = new Endpoint {
                ServiceName = "server.com", Port = 999
            };

            zipkinEndpoint.GetLocalEndpoint(null, null, 0).ReturnsForAnyArgs(localEndpoint);

            var st         = new SpanTracer(zipkinConfig, spanCollector, zipkinEndpoint);
            var trInfo     = new TraceInfo(traceId, spanId, true, false, new Uri("http://localhost"), null, parentSpanId);
            var resultSpan = await st.ReceiveServerSpan(requestName, trInfo, requestUri);

            var annotation = resultSpan.Annotations[0] as Annotation;

            Assert.AreEqual(localEndpoint, annotation.Host);
        }
예제 #8
0
        public void ShouldBeSampled()
        {
            // Arrange
            List <ShouldBeSampledCondition> testScenarios = new List <ShouldBeSampledCondition>()
            {
                // sampledFlag has a valid bool string value
                { new ShouldBeSampledCondition("0", null, 0, new List <string>(), false) },
                { new ShouldBeSampledCondition("1", null, 0, new List <string>(), true) },
                { new ShouldBeSampledCondition("false", null, 0, new List <string>(), false) },
                { new ShouldBeSampledCondition("true", null, 0, new List <string>(), true) },
                { new ShouldBeSampledCondition("FALSE", null, 0, new List <string>(), false) },
                { new ShouldBeSampledCondition("TRUE", null, 0, new List <string>(), true) },
                { new ShouldBeSampledCondition("FalSe", null, 0, new List <string>(), false) },
                { new ShouldBeSampledCondition("TrUe", null, 0, new List <string>(), true) },
                // sampledFlag has an invalid bool string value and requestPath is IsInDontSampleList
                { new ShouldBeSampledCondition(null, "/x", 0, new List <string> {
                        "/x"
                    }, false) },
                { new ShouldBeSampledCondition("", "/x", 0, new List <string> {
                        "/x"
                    }, false) },
                { new ShouldBeSampledCondition("invalidValue", "/x", 0, new List <string>()
                    {
                        "/x"
                    }, false) },
                // sampledFlag has an invalid bool string value, requestPath not in IsInDontSampleList, and sample rate is 0
                { new ShouldBeSampledCondition(null, null, 0, new List <string>(), false) },
                { new ShouldBeSampledCondition(null, "/x", 0, new List <string>(), false) },
                // sampledFlag has an invalid bool string value, requestPath not in IsInDontSampleList, and sample rate is 1
                { new ShouldBeSampledCondition(null, null, 1, new List <string>(), true) },
            };

            foreach (var testScenario in testScenarios)
            {
                var fixture = new Fixture();
                _sut = new ZipkinConfig
                {
                    ExcludedPathList = testScenario.ExcludedPathList,
                    SampleRate       = testScenario.SampleRate
                };

                // Act
                var result = _sut.ShouldBeSampled(testScenario.SampledFlag, testScenario.RequestPath);

                // Assert
                Assert.AreEqual(
                    testScenario.ExpectedOutcome,
                    result,
                    "Scenario: " +
                    $"SampledFlag({testScenario.SampledFlag ?? "null"}), " +
                    $"RequestPath({testScenario.RequestPath ?? "null"}), " +
                    $"SampleRate({testScenario.SampleRate}), " +
                    $"ExcludedPathList({string.Join(",", testScenario.ExcludedPathList)}),");
            }
        }
예제 #9
0
        public void Ctor_NullArguments_ThrowException()
        {
            var logger = Substitute.For <ILogger <SpanProcessorTask> >();
            var config = new ZipkinConfig(new Uri("http://localhost"))
            {
                SpanProcessorBatchSize = 10
            };

            Assert.Catch <ArgumentNullException>(() => new SpanProcessorTask(null, logger), "zipkinConfig");
            Assert.Catch <ArgumentNullException>(() => new SpanProcessorTask(config, null), "logger");
        }
예제 #10
0
        public void Ctor_NullArguments_ThrowException()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            Assert.Catch <ArgumentNullException>(() => new ZipkinClient(null, traceInfoAccessor, spanTracer, logger), "zipkinConfig");
            Assert.Catch <ArgumentNullException>(() => new ZipkinClient(zipkinConfig, null, spanTracer, logger), "traceInfoAccessor");
            Assert.Catch <ArgumentNullException>(() => new ZipkinClient(zipkinConfig, traceInfoAccessor, null, logger), "spanTracer");
            Assert.Catch <ArgumentNullException>(() => new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, null), "logger");
        }
예제 #11
0
        public void SetSampleRate_AlwaysInRange(double sampleRate)
        {
            var config = new ZipkinConfig(new Uri("http://localhost"));

            config.SampleRate = sampleRate;
            config.SampleRate.Should().BeInRange(0, 1);

            if (sampleRate > 0 && sampleRate < 1)
            {
                Assert.AreEqual(sampleRate, config.SampleRate);
            }
        }
예제 #12
0
        public void EndClientTrace_ForNullSpan_NotCallReceiveClientSpan()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);

            zipkinClient.EndClientTrace(null, 0);

            spanTracer.DidNotReceiveWithAnyArgs().ReceiveClientSpan(null, 0);
        }
예제 #13
0
        public async Task StartClientTrace_WithoutMethodName_ReceiveNullSpan()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            traceInfoAccessor.TraceInfo.Returns(ci => new TraceInfo("traceId", string.Empty, true, false, null, null, string.Empty));

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);

            Assert.IsNull(await zipkinClient.StartClientTrace(new Uri("http://localhost"), null));
        }
예제 #14
0
        public void Start_ActionWithException_IsNotRethrow()
        {
            var logger = Substitute.For <ILogger <SpanProcessorTask> >();
            var config = new ZipkinConfig(new Uri("http://localhost"))
            {
                SpanProcessorBatchSize = 10
            };

            var sp = new SpanProcessorTask(config, logger);

            Assert.DoesNotThrow(() => sp.Start(() => Task.Run(() => { throw new Exception(); })));
            sp.Stop();
        }
예제 #15
0
        public void Init()
        {
            var fixture = new Fixture();

            _sut = new ZipkinConfig
            {
                ZipkinBaseUri              = new Uri("http://zipkin.com"),
                Domain                     = r => new Uri("http://server.com"),
                SpanProcessorBatchSize     = fixture.Create <uint>(),
                ExcludedPathList           = new List <string>(),
                SampleRate                 = 0,
                NotToBeDisplayedDomainList = new List <string>()
            };
        }
예제 #16
0
        public bool ShouldBeSampled(string sampledFlag, string requestPath, double sampleRate, string excludedPath)
        {
            var config = new ZipkinConfig(new Uri("http://localhost"))
            {
                SampleRate = sampleRate
            };

            if (excludedPath != null)
            {
                config.ExcludedPathList.Add(excludedPath);
            }

            return(config.ShouldBeSampled(sampledFlag, requestPath));
        }
예제 #17
0
        public void Ctor_DefaultProcessor_NotStarted()
        {
            var logger            = Substitute.For <ILogger <SpanProcessor> >();
            var spanProcessorTask = Substitute.For <ISpanProcessorTask>();
            var spanCollector     = Substitute.For <ISpanCollector>();
            var config            = new ZipkinConfig(new Uri("http://localhost"))
            {
                SpanProcessorBatchSize = 10
            };

            var sp = new SpanProcessor(spanProcessorTask, spanCollector, config, logger);

            Assert.IsFalse(sp.IsStarted);
        }
예제 #18
0
        public void Start_NullAction_IsNotRunning()
        {
            var logger = Substitute.For <ILogger <SpanProcessorTask> >();
            var config = new ZipkinConfig(new Uri("http://localhost"))
            {
                SpanProcessorBatchSize = 10
            };

            var sp = new SpanProcessorTask(config, logger);

            sp.Start(null);

            Assert.IsFalse(sp.IsRunning);
        }
예제 #19
0
        public async Task StartServerTrace_IsNotSampled_ReturnNullSpan()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            var traceInfo = new TraceInfo(string.Empty, string.Empty, false, false, null, null, string.Empty);

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);

            Assert.IsNull(await zipkinClient.StartServerTrace(null, null, traceInfo));
            Assert.IsNull(await zipkinClient.StartServerTrace(new Uri("http://localhost"), null, traceInfo));
            Assert.IsNull(await zipkinClient.StartServerTrace(new Uri("http://localhost"), "POST", traceInfo));
        }
예제 #20
0
        public void StartClientTrace_WithSpanTracerException_DoesntThrow()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            traceInfoAccessor.TraceInfo.Returns(ci => new TraceInfo("traceId", string.Empty, true, false, null, null, string.Empty));

            spanTracer.WhenForAnyArgs(x => x.SendClientSpan(null, null, null)).Throw <Exception>();

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);

            Assert.DoesNotThrowAsync(() => zipkinClient.StartClientTrace(new Uri("http://localhost"), "POST"));
        }
예제 #21
0
        public void EndServerTrace_ForNullSpan_NotCallSendServerSpan()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            traceInfoAccessor.TraceInfo.Returns(ci => new TraceInfo("traceId", string.Empty, false, false, null, null, string.Empty));

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);

            zipkinClient.EndServerTrace(null, 200);

            spanTracer.DidNotReceiveWithAnyArgs().SendServerSpan(null, 200);
        }
예제 #22
0
        public SpanProcessorTask(ZipkinConfig zipkinConfig, ILogger <SpanProcessorTask> logger)
        {
            if (zipkinConfig == null)
            {
                throw new ArgumentNullException(nameof(zipkinConfig));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            _logger                  = logger;
            _zipkinConfig            = zipkinConfig;
            _cancellationTokenSource = new CancellationTokenSource();
        }
예제 #23
0
        public async Task Start_PropertyIsStarted_IsTrue()
        {
            var logger            = Substitute.For <ILogger <SpanProcessor> >();
            var spanProcessorTask = Substitute.For <ISpanProcessorTask>();
            var spanCollector     = Substitute.For <ISpanCollector>();
            var config            = new ZipkinConfig(new Uri("http://localhost"))
            {
                SpanProcessorBatchSize = 10
            };

            var sp = new SpanProcessor(spanProcessorTask, spanCollector, config, logger);

            await sp.Start();

            Assert.IsTrue(sp.IsStarted);
        }
예제 #24
0
        public void Start_StoppedProcessor_ActionIsNotCalled()
        {
            var isExecute = false;
            var logger    = Substitute.For <ILogger <SpanProcessorTask> >();
            var config    = new ZipkinConfig(new Uri("http://localhost"))
            {
                SpanProcessorBatchSize = 10
            };

            var sp = new SpanProcessorTask(config, logger);

            sp.Stop();
            sp.Start(() => Task.Run(() => isExecute = true));

            Assert.IsFalse(isExecute);
        }
        public void Constructor_GeneratingNew128BitTraceId()
        {
            // Arrange
            var config = new ZipkinConfig
            {
                Create128BitTraceId = true
            };

            // Arrange & Act
            var traceProvider = new TraceProvider(config);

            // Assert
            Assert.IsTrue(Regex.IsMatch(traceProvider.TraceId, regex128BitPattern));
            Assert.IsTrue(Regex.IsMatch(traceProvider.SpanId, regex64BitPattern));
            Assert.AreEqual(string.Empty, traceProvider.ParentSpanId);
            Assert.AreEqual(false, traceProvider.IsSampled);
        }
예제 #26
0
        public async Task StartServerTrace_WithTraceOn_ReceiveSpan()
        {
            var traceInfo         = new TraceInfo(string.Empty, string.Empty, true, false, new Uri("http://localhost"), null);
            var span              = new Span("span", traceInfo);
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            var traceInfoServer = new TraceInfo("traceId", string.Empty, true, false, null, null, string.Empty);

            spanTracer.ReceiveServerSpan(null, null, null).ReturnsForAnyArgs(span);

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);

            Assert.AreSame(await zipkinClient.StartServerTrace(new Uri("http://localhost"), "POST", traceInfoServer), span);
        }
        public static void AddZipkinTracer(this IServiceCollection services, ZipkinConfig config)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            services.AddSingleton(config);
            services.AddSingleton(new BlockingCollection <Span>(config.MaxQueueSize));
            services.AddSingleton <IServiceEndpoint, ServiceEndpoint>();
            services.AddSingleton <ISpanProcessorTask, SpanProcessorTask>();
            services.AddSingleton <ISpanProcessor, SpanProcessor>();
            services.AddSingleton <ITraceInfoAccessor, TraceInfoAccessor>();

            services.AddScoped <ISpanCollector, SpanCollector>();
            services.AddScoped <IZipkinTracer, ZipkinClient>();
            services.AddScoped <ISpanTracer, SpanTracer>();
        }
예제 #28
0
        public void EndClientTrace_WithTraceOn_CallSpanTracer()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            var traceInfo = new TraceInfo("traceId", string.Empty, true, false, null, null, string.Empty);

            traceInfoAccessor.TraceInfo.Returns(ci => traceInfo);

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);

            zipkinClient.EndClientTrace(null, 0);
            zipkinClient.EndClientTrace(new Span("span", traceInfo), 0);

            spanTracer.ReceivedWithAnyArgs(1).ReceiveClientSpan(null, 0);
        }
예제 #29
0
        public async Task RecordLocalComponent_WithoutTraceId_NotCallRecordOnSpanTracer()
        {
            var zipkinConfig      = new ZipkinConfig(new Uri("http://localhost"));
            var traceInfoAccessor = Substitute.For <ITraceInfoAccessor>();
            var spanTracer        = Substitute.For <ISpanTracer>();
            var logger            = Substitute.For <ILogger <ZipkinClient> >();

            var zipkinClient = new ZipkinClient(zipkinConfig, traceInfoAccessor, spanTracer, logger);
            var traceInfo    = new TraceInfo("traceId", string.Empty, true, false, null, null, string.Empty);

            await zipkinClient.RecordLocalComponent(null, null);

            await zipkinClient.RecordLocalComponent(null, "value");

            await zipkinClient.RecordLocalComponent(new Span("span", traceInfo), "value");

            await spanTracer.DidNotReceiveWithAnyArgs().Record(null, string.Empty);
        }
예제 #30
0
        public SpanTracer(ZipkinConfig zipkinConfig, ISpanCollector spanCollector, IServiceEndpoint zipkinEndpoint)
        {
            if (zipkinConfig == null)
            {
                throw new ArgumentNullException(nameof(zipkinConfig));
            }
            if (spanCollector == null)
            {
                throw new ArgumentNullException(nameof(spanCollector));
            }
            if (zipkinEndpoint == null)
            {
                throw new ArgumentNullException(nameof(zipkinEndpoint));
            }

            _spanCollector  = spanCollector;
            _zipkinEndpoint = zipkinEndpoint;
            _zipkinConfig   = zipkinConfig;
        }