Beispiel #1
0
        private RequestTelemetry InitializeRequestTelemetry(HttpContext httpContext, Activity activity, long timestamp, string legacyRootId = null)
        {
            var requestTelemetry = new RequestTelemetry();

            if (activity.IdFormat == ActivityIdFormat.W3C)
            {
                var traceId = activity.TraceId.ToHexString();
                requestTelemetry.Id = activity.SpanId.ToHexString();
                requestTelemetry.Context.Operation.Id = traceId;
                AspNetCoreEventSource.Instance.RequestTelemetryCreated("W3C", requestTelemetry.Id, traceId);
            }
            else
            {
                requestTelemetry.Context.Operation.Id = activity.RootId;
                requestTelemetry.Id = activity.Id;
                AspNetCoreEventSource.Instance.RequestTelemetryCreated("Hierarchical", requestTelemetry.Id, requestTelemetry.Context.Operation.Id);
            }

            if (this.proactiveSamplingEnabled &&
                !activity.Recorded &&
                this.configuration != null &&
                !string.IsNullOrEmpty(requestTelemetry.Context.Operation.Id) &&
                SamplingScoreGenerator.GetSamplingScore(requestTelemetry.Context.Operation.Id) >= this.configuration.GetLastObservedSamplingPercentage(requestTelemetry.ItemTypeFlag))
            {
                requestTelemetry.ProactiveSamplingDecision = SamplingDecision.SampledOut;
                AspNetCoreEventSource.Instance.TelemetryItemWasSampledOutAtHead(requestTelemetry.Context.Operation.Id);
            }

            //// When the item is proactively sampled out, we can avoid heavy operations that do not have known dependency later in the pipeline.
            //// We mostly exclude operations that were deemed heavy as per the corresponding profiler trace of this code path.

            if (requestTelemetry.ProactiveSamplingDecision != SamplingDecision.SampledOut)
            {
                foreach (var prop in activity.Baggage)
                {
                    if (!requestTelemetry.Properties.ContainsKey(prop.Key))
                    {
                        requestTelemetry.Properties[prop.Key] = prop.Value;
                    }
                }

                if (!string.IsNullOrEmpty(legacyRootId))
                {
                    requestTelemetry.Properties[LegacyRootIdProperty] = legacyRootId;
                }
            }

            this.client.InitializeInstrumentationKey(requestTelemetry);
            requestTelemetry.Source = this.GetAppIdFromRequestHeader(httpContext.Request.Headers, requestTelemetry.Context.InstrumentationKey);

            requestTelemetry.Start(timestamp);
            httpContext.Features.Set(requestTelemetry);

            return(requestTelemetry);
        }
        private RequestTelemetry InitializeRequestTelemetry(HttpContext httpContext, Activity activity, long timestamp)
        {
            var requestTelemetry = new RequestTelemetry();

            if (!this.enableW3CHeaders)
            {
                requestTelemetry.Context.Operation.Id = activity.RootId;
                requestTelemetry.Id = activity.Id;
            }
            else
            {
                activity.UpdateTelemetry(requestTelemetry, false);
            }

            if (this.proactiveSamplingEnabled &&
                this.configuration != null &&
                !string.IsNullOrEmpty(requestTelemetry.Context.Operation.Id) &&
                SamplingScoreGenerator.GetSamplingScore(requestTelemetry.Context.Operation.Id) >= this.configuration.GetLastObservedSamplingPercentage(requestTelemetry.ItemTypeFlag))
            {
                requestTelemetry.IsSampledOutAtHead = true;
                AspNetCoreEventSource.Instance.TelemetryItemWasSampledOutAtHead(requestTelemetry.Context.Operation.Id);
            }

            //// When the item is proactively sampled out, we can avoid heavy operations that do not have known dependency later in the pipeline.
            //// We mostly exclude operations that were deemed heavy as per the corresponding profiler trace of this code path.

            if (!requestTelemetry.IsSampledOutAtHead)
            {
                foreach (var prop in activity.Baggage)
                {
                    if (!requestTelemetry.Properties.ContainsKey(prop.Key))
                    {
                        requestTelemetry.Properties[prop.Key] = prop.Value;
                    }
                }
            }

            this.client.InitializeInstrumentationKey(requestTelemetry);
            requestTelemetry.Source = GetAppIdFromRequestHeader(httpContext.Request.Headers, requestTelemetry.Context.InstrumentationKey);

            requestTelemetry.Start(timestamp);
            httpContext.Features.Set(requestTelemetry);

            return(requestTelemetry);
        }
        private bool IsSampledIn(ITelemetry telemetry)
        {
            // check if telemetry supports sampling
            var samplingSupportingTelemetry = telemetry as ISupportSampling;

            if (samplingSupportingTelemetry == null)
            {
                return(true);
            }

            // check sampling < 100% is specified
            if (samplingSupportingTelemetry.SamplingPercentage >= 100.0)
            {
                return(true);
            }

            return(SamplingScoreGenerator.GetSamplingScore(telemetry) < samplingSupportingTelemetry.SamplingPercentage);
        }
Beispiel #4
0
        public void ProactivelySampledInItemsPassAccordingToScoreIfCurrentRateIsHigherThanExpected()
        {
            var sentTelemetry = new List <ITelemetry>();

            var tc = new TelemetryConfiguration
            {
                TelemetryChannel   = new StubTelemetryChannel(),
                InstrumentationKey = Guid.NewGuid().ToString("D")
            };

            var channelBuilder = new TelemetryProcessorChainBuilder(tc);

            channelBuilder.Use(next => new SamplingTelemetryProcessor(next)
            {
                SamplingPercentage          = 50,
                ProactiveSamplingPercentage = 50
            });
            channelBuilder.Use(next => new StubTelemetryProcessor(next)
            {
                OnProcess = t => sentTelemetry.Add(t)
            });
            channelBuilder.Build();

            int count = 5000;

            for (int i = 0; i < count; i++)
            {
                var item = new RequestTelemetry();
                item.Context.Operation.Id = ActivityTraceId.CreateRandom().ToHexString();

                // generate a lot sampled-in items, only 1/CurrentProactiveSampledInRatioToTarget of them should pass through
                // and SamplingPercentage of sampled-out items
                if (SamplingScoreGenerator.GetSamplingScore(item.Context.Operation.Id) < 80)
                {
                    item.ProactiveSamplingDecision = SamplingDecision.SampledIn;
                }

                tc.TelemetryProcessorChain.Process(item);
            }

            Assert.AreEqual(0, sentTelemetry.Count(i => ((ISupportAdvancedSampling)i).ProactiveSamplingDecision == SamplingDecision.None));
            Assert.AreEqual(count / 2, sentTelemetry.Count(i => ((ISupportAdvancedSampling)i).ProactiveSamplingDecision == SamplingDecision.SampledIn), count / 2 / 10);
        }
Beispiel #5
0
        public void ProactivelySampledInItemsAreNotGivenPriorityIfRatesAreNotSet()
        {
            var sentTelemetry = new List <ITelemetry>();
            TelemetryProcessorChain telemetryProcessorChainWithSampling = CreateTelemetryProcessorChainWithSampling(
                sentTelemetry,
                50);

            for (int i = 0; i < 1000; i++)
            {
                var item = new RequestTelemetry();
                item.Context.Operation.Id = ActivityTraceId.CreateRandom().ToHexString();

                // proactively sample in items with big score, so they should not be sampled in
                if (SamplingScoreGenerator.GetSamplingScore(item.Context.Operation.Id) > 50)
                {
                    item.ProactiveSamplingDecision = SamplingDecision.SampledIn;
                }

                telemetryProcessorChainWithSampling.Process(item);
            }

            Assert.AreEqual(0, sentTelemetry.Count(i => ((ISupportAdvancedSampling)i).ProactiveSamplingDecision == SamplingDecision.SampledIn));
        }
        /// <summary>
        /// Process a collected telemetry item.
        /// </summary>
        /// <param name="item">A collected Telemetry item.</param>
        public void Process(ITelemetry item)
        {
            double samplingPercentage = this.SamplingPercentage;

            //// If sampling rate is 100% and we aren't distinguishing between evaluated/unevaluated items, there is nothing to do:
            if (samplingPercentage >= 100.0 - 1.0E-12 && this.SampledNext.Equals(this.UnsampledNext))
            {
                this.HandlePossibleProactiveSampling(item, samplingPercentage);
                return;
            }

            //// So sampling rate is not 100%, or we must evaluate further

            var advancedSamplingSupportingTelemetry = item as ISupportAdvancedSampling;

            // If someone implemented ISupportSampling and hopes that SamplingTelemetryProcessor will continue to work for them:
            var samplingSupportingTelemetry = advancedSamplingSupportingTelemetry ?? item as ISupportSampling;

            //// If null was passed in as item or if sampling not supported in general, do nothing:
            if (samplingSupportingTelemetry == null)
            {
                this.UnsampledNext.Process(item);
                return;
            }

            //// If telemetry was excluded by type, do nothing:
            if (advancedSamplingSupportingTelemetry != null && !this.IsSamplingApplicable(advancedSamplingSupportingTelemetry.ItemTypeFlag))
            {
                if (TelemetryChannelEventSource.IsVerboseEnabled)
                {
                    TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString());
                }

                this.UnsampledNext.Process(item);
                return;
            }

            //// If telemetry was already sampled, do nothing:
            bool itemAlreadySampled = samplingSupportingTelemetry.SamplingPercentage.HasValue;

            if (itemAlreadySampled)
            {
                this.UnsampledNext.Process(item);
                return;
            }

            //// Ok, now we can actually sample:

            samplingSupportingTelemetry.SamplingPercentage = samplingPercentage;

            bool isSampledIn;

            // if this is executed in adaptive sampling processor (rate ratio has value),
            // and item supports proactive sampling and was sampled in before, we'll give it more weight
            if (this.ProactiveSamplingPercentage.HasValue &&
                advancedSamplingSupportingTelemetry != null &&
                advancedSamplingSupportingTelemetry.ProactiveSamplingDecision == SamplingDecision.SampledIn)
            {
                // if current rate of proactively sampled-in telemetry is too high, ProactiveSamplingPercentage is low:
                // we'll sample in as much proactively sampled in items as we can (based on their sampling score)
                // so that we still keep target rate.
                // if current rate of proactively sampled-in telemetry is less that configured, ProactiveSamplingPercentage
                // is high - it could be > 100 - and we'll sample in all items with proactive SampledIn decision (plus some more in else branch).
                isSampledIn = SamplingScoreGenerator.GetSamplingScore(item) < this.ProactiveSamplingPercentage;
            }
            else
            {
                isSampledIn = SamplingScoreGenerator.GetSamplingScore(item) < samplingPercentage;
            }

            if (isSampledIn)
            {
                if (advancedSamplingSupportingTelemetry != null)
                {
                    this.HandlePossibleProactiveSampling(item, samplingPercentage, advancedSamplingSupportingTelemetry);
                }
                else
                {
                    this.SampledNext.Process(item);
                }
            }
            else
            {
                if (TelemetryChannelEventSource.IsVerboseEnabled)
                {
                    TelemetryChannelEventSource.Log.ItemSampledOut(item.ToString());
                }

                TelemetryDebugWriter.WriteTelemetry(item, nameof(SamplingTelemetryProcessor));
            }
        }
Beispiel #7
0
        /// <summary>
        /// Process a collected telemetry item.
        /// </summary>
        /// <param name="item">A collected Telemetry item.</param>
        public void Process(ITelemetry item)
        {
            double samplingPercentage = this.SamplingPercentage;

            //// If sampling rate is 100% and we aren't distinguishing between evaluated/unevaluated items, there is nothing to do:
            if (this.SampledNext.Equals(this.UnsampledNext) && samplingPercentage >= 100.0 - 1.0E-12)
            {
                this.SampledNext.Process(item);
                return;
            }

            //// So sampling rate is not 100%, or we must evaluate further

            //// If null was passed in as item or if sampling not supported in general, do nothing:
            var samplingSupportingTelemetry = item as ISupportSampling;

            if (samplingSupportingTelemetry == null)
            {
                this.UnsampledNext.Process(item);
                return;
            }

            //// If telemetry was excluded by type, do nothing:
            if (!this.IsSamplingApplicable(item.GetType()))
            {
                if (TelemetryChannelEventSource.IsVerboseEnabled)
                {
                    TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString());
                }

                this.UnsampledNext.Process(item);
                return;
            }

            //// If telemetry was already sampled, do nothing:
            bool itemAlreadySampled = samplingSupportingTelemetry.SamplingPercentage.HasValue;

            if (itemAlreadySampled)
            {
                this.UnsampledNext.Process(item);
                return;
            }

            //// Ok, now we can actually sample:

            samplingSupportingTelemetry.SamplingPercentage = samplingPercentage;
            bool isSampledIn = SamplingScoreGenerator.GetSamplingScore(item) < samplingPercentage;

            if (isSampledIn)
            {
                this.SampledNext.Process(item);
            }
            else
            {
                if (TelemetryChannelEventSource.IsVerboseEnabled)
                {
                    TelemetryChannelEventSource.Log.ItemSampledOut(item.ToString());
                }

                TelemetryDebugWriter.WriteTelemetry(item, this.GetType().Name);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Process a collected telemetry item.
        /// </summary>
        /// <param name="item">A collected Telemetry item.</param>
        public void Process(ITelemetry item)
        {
            double samplingPercentage = this.SamplingPercentage;

            //// If sampling rate is 100% and we aren't distinguishing between evaluated/unevaluated items, there is nothing to do:
            if (samplingPercentage >= 100.0 - 1.0E-12 && this.SampledNext.Equals(this.UnsampledNext))
            {
                this.HandlePossibleProactiveSampling(item, samplingPercentage);
                return;
            }

            //// So sampling rate is not 100%, or we must evaluate further

            var advancedSamplingSupportingTelemetry = item as ISupportAdvancedSampling;

            // If someone implemented ISupportSampling and hopes that SamplingTelemetryProcessor will continue to work for them:
            var samplingSupportingTelemetry = advancedSamplingSupportingTelemetry ?? item as ISupportSampling;

            //// If null was passed in as item or if sampling not supported in general, do nothing:
            if (samplingSupportingTelemetry == null)
            {
                this.UnsampledNext.Process(item);
                return;
            }

            //// If telemetry was excluded by type, do nothing:
            if (advancedSamplingSupportingTelemetry != null && !this.IsSamplingApplicable(advancedSamplingSupportingTelemetry.ItemTypeFlag))
            {
                if (TelemetryChannelEventSource.IsVerboseEnabled)
                {
                    TelemetryChannelEventSource.Log.SamplingSkippedByType(item.ToString());
                }

                this.UnsampledNext.Process(item);
                return;
            }

            //// If telemetry was already sampled, do nothing:
            bool itemAlreadySampled = samplingSupportingTelemetry.SamplingPercentage.HasValue;

            if (itemAlreadySampled)
            {
                this.UnsampledNext.Process(item);
                return;
            }

            //// Ok, now we can actually sample:

            samplingSupportingTelemetry.SamplingPercentage = samplingPercentage;
            bool isSampledIn = SamplingScoreGenerator.GetSamplingScore(item) < samplingPercentage;

            if (isSampledIn)
            {
                if (advancedSamplingSupportingTelemetry != null)
                {
                    this.HandlePossibleProactiveSampling(item, samplingPercentage, advancedSamplingSupportingTelemetry);
                }
                else
                {
                    this.SampledNext.Process(item);
                }
            }
            else
            {
                if (TelemetryChannelEventSource.IsVerboseEnabled)
                {
                    TelemetryChannelEventSource.Log.ItemSampledOut(item.ToString());
                }

                TelemetryDebugWriter.WriteTelemetry(item, nameof(SamplingTelemetryProcessor));
            }
        }