Exemple #1
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();


            var appInsightsConfig = app.ApplicationServices.GetService <TelemetryConfiguration>();

            TelemetryProcessorChainBuilder builder = appInsightsConfig.TelemetryProcessorChainBuilder;

            // some custom telemetry processor for Application Insights that filters out synthetic traffic (e.g traffic that comes from Azure to keep the server awake).
            builder.UseAdaptiveSampling(excludedTypes: "Exception");
            builder.UseAdaptiveSampling(maxTelemetryItemsPerSecond: 10000);
            builder.Build();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
Exemple #2
0
        public void UseAdaptiveSamplingWithSettingsParameterAndExcludedTypesThrowsArgumentNullExceptionSettingsIsNull()
        {
            var tc = new TelemetryConfiguration {
                TelemetryChannel = new StubTelemetryChannel()
            };
            var channelBuilder = new TelemetryProcessorChainBuilder(tc);

            AssertEx.Throws <ArgumentNullException>(() => channelBuilder.UseAdaptiveSampling(null, null, "request"));
        }
Exemple #3
0
        public void UseAdaptiveSamplingWithSettingsParameterThrowsArgumentNullExceptionSettingsIsNull()
        {
            var tc = new TelemetryConfiguration {
                TelemetryChannel = new StubTelemetryChannel()
            };
            var channelBuilder = new TelemetryProcessorChainBuilder(tc);

            AssertEx.Throws <ArgumentNullException>(() => channelBuilder.UseAdaptiveSampling(default(SamplingPercentageEstimatorSettings), null));
        }
Exemple #4
0
        public void UseAdaptiveSamplingAddsAdaptiveSamplingProcessorToTheChainWithCorrectExcludedTypes()
        {
            var tc = new TelemetryConfiguration {
                TelemetryChannel = new StubTelemetryChannel()
            };
            var channelBuilder = new TelemetryProcessorChainBuilder(tc);

            channelBuilder.UseAdaptiveSampling("request");
            channelBuilder.Build();

            Assert.AreEqual("request", ((AdaptiveSamplingTelemetryProcessor)tc.TelemetryProcessorChain.FirstTelemetryProcessor).ExcludedTypes);
        }
Exemple #5
0
        public void UseAdaptiveSamplingAddsAdaptiveSamplingProcessorToTheChain()
        {
            var tc = new TelemetryConfiguration {
                TelemetryChannel = new StubTelemetryChannel()
            };
            var channelBuilder = new TelemetryProcessorChainBuilder(tc);

            channelBuilder.UseAdaptiveSampling();
            channelBuilder.Build();

            AssertEx.IsType <AdaptiveSamplingTelemetryProcessor>(tc.TelemetryProcessorChain.FirstTelemetryProcessor);
        }
Exemple #6
0
        public void UseAdaptiveSamplingAddsAdaptiveSamplingProcessorToTheChainWithCorrectMaxTelemetryItemsPerSecond()
        {
            var tc = new TelemetryConfiguration {
                TelemetryChannel = new StubTelemetryChannel()
            };
            var channelBuilder = new TelemetryProcessorChainBuilder(tc);

            channelBuilder.UseAdaptiveSampling(5);
            channelBuilder.Build();

            Assert.AreEqual(5, ((AdaptiveSamplingTelemetryProcessor)tc.TelemetryProcessorChain.FirstTelemetryProcessor).MaxTelemetryItemsPerSecond);
        }
        public void AllTelemetryCapturedWhenProductionRateIsLow()
        {
            var sentTelemetry = new List <ITelemetry>();
            int itemsProduced = 0;

            using (var tc = new TelemetryConfiguration()
            {
                TelemetryChannel = new StubTelemetryChannel()
            })
            {
                var chainBuilder = new TelemetryProcessorChainBuilder(tc);

                // set up adaptive sampling that evaluates and changes sampling % frequently
                chainBuilder
                .UseAdaptiveSampling(
                    new Channel.Implementation.SamplingPercentageEstimatorSettings()
                {
                    EvaluationInterval = TimeSpan.FromSeconds(1),
                    SamplingPercentageDecreaseTimeout = TimeSpan.FromSeconds(2),
                    SamplingPercentageIncreaseTimeout = TimeSpan.FromSeconds(2),
                },
                    this.TraceSamplingPercentageEvaluation)
                .Use((next) => new StubTelemetryProcessor(next)
                {
                    OnProcess = (t) => sentTelemetry.Add(t)
                });

                chainBuilder.Build();

                const int productionFrequencyMs = 1000;

                var productionTimer = new Timer(
                    (state) =>
                {
                    tc.TelemetryProcessorChain.Process(new RequestTelemetry());
                    itemsProduced++;
                },
                    null,
                    productionFrequencyMs,
                    productionFrequencyMs);

                Thread.Sleep(25000);

                // dispose timer and wait for callbacks to complete
                DisposeTimer(productionTimer);
            }

            Assert.AreEqual(itemsProduced, sentTelemetry.Count);
        }
        public void AdaptiveSamplingSetsExcludedTypesOnInternalSamplingProcessor()
        {
            var tc = new TelemetryConfiguration {
                TelemetryChannel = new StubTelemetryChannel()
            };
            var channelBuilder = new TelemetryProcessorChainBuilder(tc);

            channelBuilder.UseAdaptiveSampling(5, "request;");
            channelBuilder.Build();

            var fieldInfo = typeof(AdaptiveSamplingTelemetryProcessor).GetField("samplingProcessor", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
            SamplingTelemetryProcessor internalProcessor = (SamplingTelemetryProcessor)fieldInfo.GetValue(tc.TelemetryProcessorChain.FirstTelemetryProcessor);

            Assert.AreEqual("request;", internalProcessor.ExcludedTypes);
        }
Exemple #9
0
        public void UseAdaptiveSamplingAddsAdaptiveSamplingProcessorToTheChainWithCorrectSettings()
        {
            SamplingPercentageEstimatorSettings settings = new SamplingPercentageEstimatorSettings
            {
                MaxSamplingPercentage = 13
            };
            AdaptiveSamplingPercentageEvaluatedCallback callback = (second, percentage, samplingPercentage, changed, estimatorSettings) => { };

            var tc = new TelemetryConfiguration {
                TelemetryChannel = new StubTelemetryChannel()
            };
            var channelBuilder = new TelemetryProcessorChainBuilder(tc);

            channelBuilder.UseAdaptiveSampling(settings, callback);
            channelBuilder.Build();

            Assert.AreEqual(13, ((AdaptiveSamplingTelemetryProcessor)tc.TelemetryProcessorChain.FirstTelemetryProcessor).MaxSamplingPercentage);
        }
        public void SamplingPercentageAdjustsAccordingToConstantHighProductionRate()
        {
            var sentTelemetry = new List <ITelemetry>();
            int itemsProduced = 0;

            using (var tc = new TelemetryConfiguration()
            {
                TelemetryChannel = new StubTelemetryChannel()
            })
            {
                var chainBuilder = new TelemetryProcessorChainBuilder(tc);

                // set up adaptive sampling that evaluates and changes sampling % frequently
                chainBuilder
                .UseAdaptiveSampling(
                    new Channel.Implementation.SamplingPercentageEstimatorSettings()
                {
                    EvaluationInterval = TimeSpan.FromSeconds(1),
                    SamplingPercentageDecreaseTimeout = TimeSpan.FromSeconds(2),
                    SamplingPercentageIncreaseTimeout = TimeSpan.FromSeconds(2),
                },
                    this.TraceSamplingPercentageEvaluation)
                .Use((next) => new StubTelemetryProcessor(next)
                {
                    OnProcess = (t) => sentTelemetry.Add(t)
                });

                chainBuilder.Build();

                const int productionFrequencyMs = 100;

                var productionTimer = new Timer(
                    (state) =>
                {
                    for (int i = 0; i < 2; i++)
                    {
                        tc.TelemetryProcessorChain.Process(new RequestTelemetry());
                        itemsProduced++;
                    }
                },
                    null,
                    0,
                    productionFrequencyMs);

                Thread.Sleep(25000);

                // dispose timer and wait for callbacks to complete
                DisposeTimer(productionTimer);
            }

            // number of items produced should be close to target of 5/second
            int targetItemCount = 25 * 5;

            // tolrance +-
            int tolerance = targetItemCount / 2;

            Trace.WriteLine(string.Format("'Ideal' telemetry item count: {0}", targetItemCount));
            Trace.WriteLine(string.Format(
                                "Expected range: from {0} to {1}",
                                targetItemCount - tolerance,
                                targetItemCount + tolerance));
            Trace.WriteLine(string.Format(
                                "Actual telemetry item count: {0} ({1:##.##}% of ideal)",
                                sentTelemetry.Count,
                                100.0 * sentTelemetry.Count / targetItemCount));

            Assert.IsTrue(sentTelemetry.Count > targetItemCount - tolerance);
            Assert.IsTrue(sentTelemetry.Count < targetItemCount + tolerance);
        }
        public void SamplingPercentageAdjustsForSpikyProductionRate()
        {
            var sentTelemetry = new List <ITelemetry>();
            int itemsProduced = 0;

            using (var tc = new TelemetryConfiguration()
            {
                TelemetryChannel = new StubTelemetryChannel()
            })
            {
                var chainBuilder = new TelemetryProcessorChainBuilder(tc);

                // set up adaptive sampling that evaluates and changes sampling % frequently
                chainBuilder
                .UseAdaptiveSampling(
                    new SamplingPercentageEstimatorSettings()
                {
                    InitialSamplingPercentage         = 5.0,
                    EvaluationInterval                = TimeSpan.FromSeconds(1),
                    SamplingPercentageDecreaseTimeout = TimeSpan.FromSeconds(2),
                    SamplingPercentageIncreaseTimeout = TimeSpan.FromSeconds(10),
                },
                    this.TraceSamplingPercentageEvaluation)
                .Use((next) => new StubTelemetryProcessor(next)
                {
                    OnProcess = (t) => sentTelemetry.Add(t)
                });

                chainBuilder.Build();

                const int regularProductionFrequencyMs = 100;
                const int spikeProductionFrequencyMs   = 3000;

                using (var regularProductionTimer = new Timer(
                           (state) =>
                {
                    for (int i = 0; i < 2; i++)
                    {
                        tc.TelemetryProcessorChain.Process(new RequestTelemetry());
                        Interlocked.Increment(ref itemsProduced);
                    }
                },
                           null,
                           0,
                           regularProductionFrequencyMs))
                    using (var spikeProductionTimer = new Timer(
                               (state) =>
                    {
                        for (int i = 0; i < 200; i++)
                        {
                            tc.TelemetryProcessorChain.Process(new RequestTelemetry());
                            Interlocked.Increment(ref itemsProduced);
                        }
                    },
                               null,
                               0,
                               spikeProductionFrequencyMs))
                    {
                        Thread.Sleep(30000);
                    }
            }

            // number of items produced should be close to target of 5/second
            int targetItemCount = 30 * 5;
            int tolerance       = targetItemCount / 2;

            Trace.WriteLine(string.Format("'Ideal' telemetry item count: {0}", targetItemCount));
            Trace.WriteLine(string.Format(
                                "Expected range: from {0} to {1}",
                                targetItemCount - tolerance,
                                targetItemCount + tolerance));
            Trace.WriteLine(string.Format(
                                "Actual telemetry item count: {0} ({1:##.##}% of ideal)",
                                sentTelemetry.Count,
                                100.0 * sentTelemetry.Count / targetItemCount));

            Assert.IsTrue(sentTelemetry.Count > targetItemCount - tolerance);
            Assert.IsTrue(sentTelemetry.Count < targetItemCount + tolerance);
        }
        public (int proactivelySampledInAndSentCount, double sentCount) ProactiveSamplingTest(
            int proactivelySampledInRatePerSec,
            int beforeSamplingRatePerSec,
            double targetAfterSamplingRatePerSec,
            double precision,
            int testDurationInSec)
        {
            // we'll ignore telemetry reported during first few percentage evaluations
            int warmUpInSec = 12;

            // we'll produce proactively  sampled in items and also 'normal' items with the same rate
            // but allow only proactively sampled in + a bit more

            // number of items produced should be close to target
            int targetItemCount = (int)(testDurationInSec * targetAfterSamplingRatePerSec);

            var sentTelemetry = new List <ITelemetry>();

            using (var tc = new TelemetryConfiguration()
            {
                TelemetryChannel = new StubTelemetryChannel()
            })
            {
                var chainBuilder = new TelemetryProcessorChainBuilder(tc);

                // set up adaptive sampling that evaluates and changes sampling % frequently
                chainBuilder
                .UseAdaptiveSampling(
                    new Channel.Implementation.SamplingPercentageEstimatorSettings()
                {
                    // help algo get to stabilize earlier
                    InitialSamplingPercentage         = targetAfterSamplingRatePerSec / (double)beforeSamplingRatePerSec * 100,
                    MaxTelemetryItemsPerSecond        = targetAfterSamplingRatePerSec,
                    EvaluationInterval                = TimeSpan.FromSeconds(2),
                    SamplingPercentageDecreaseTimeout = TimeSpan.FromSeconds(4),
                    SamplingPercentageIncreaseTimeout = TimeSpan.FromSeconds(4),
                },
                    this.TraceSamplingPercentageEvaluation)
                .Use((next) => new StubTelemetryProcessor(next)
                {
                    OnProcess = (t) => sentTelemetry.Add(t)
                });

                chainBuilder.Build();

                var sw = Stopwatch.StartNew();
                var productionTimer = new Timer(
                    (state) =>
                {
                    var requests = new RequestTelemetry[beforeSamplingRatePerSec];

                    for (int i = 0; i < beforeSamplingRatePerSec; i++)
                    {
                        requests[i] = new RequestTelemetry()
                        {
                            ProactiveSamplingDecision = i < proactivelySampledInRatePerSec ? SamplingDecision.SampledIn : SamplingDecision.None
                        };

                        requests[i].Context.Operation.Id = ActivityTraceId.CreateRandom().ToHexString();
                    }

                    foreach (var request in requests)
                    {
                        if (((Stopwatch)state).Elapsed.TotalSeconds < warmUpInSec)
                        {
                            // let's ignore telemetry from first few rate evaluations - it does not make sense
                            request.Properties["ignore"] = "true";
                        }

                        tc.TelemetryProcessorChain.Process(request);
                    }
                },
                    sw,
                    0,
                    1000);

                Thread.Sleep(TimeSpan.FromSeconds(testDurationInSec + warmUpInSec));

                // dispose timer and wait for callbacks to complete
                DisposeTimer(productionTimer);
            }

            var notIgnoredSent = sentTelemetry.Where(i => i is ISupportProperties propItem && !propItem.Properties.ContainsKey("ignore")).ToArray();

            var proactivelySampledInAndSentCount = notIgnoredSent.Count(i =>
                                                                        i is ISupportAdvancedSampling advSamplingItem &&
                                                                        advSamplingItem.ProactiveSamplingDecision == SamplingDecision.SampledIn);

            // check that normal sampling requirements still apply (we generated as much items as expected)
            Trace.WriteLine($"'Ideal' telemetry item count: {targetItemCount}");
            Trace.WriteLine($"Expected range: from {targetItemCount - precision * targetItemCount} to {targetItemCount + precision * targetItemCount}");
            Trace.WriteLine(
                $"Actual telemetry item count: {notIgnoredSent.Length} ({100.0 * notIgnoredSent.Length / targetItemCount:##.##}% of ideal)");
            Trace.WriteLine(
                $"Actual proactive sampled in and sent: {proactivelySampledInAndSentCount}");

            Assert.IsTrue(notIgnoredSent.Length / (double)targetItemCount > 1 - precision);
            Assert.IsTrue(notIgnoredSent.Length / (double)targetItemCount < 1 + precision);

            return(proactivelySampledInAndSentCount, notIgnoredSent.Length);
        }