/// <summary>
 /// Adds <see cref="AdaptiveSamplingTelemetryProcessor"/> to the <see cref="TelemetryProcessorChainBuilder" />
 /// </summary>
 /// <param name="builder">Instance of <see cref="TelemetryProcessorChainBuilder"/></param>
 /// <param name="settings">Set of settings applicable to dynamic sampling percentage algorithm.</param>
 /// <param name="callback">Callback invoked every time sampling percentage evaluation occurs.</param>
 /// <return>Instance of <see cref="TelemetryProcessorChainBuilder"/>.</return>
 public static TelemetryProcessorChainBuilder UseAdaptiveSampling(
     this TelemetryProcessorChainBuilder builder, 
     SamplingPercentageEstimatorSettings settings,
     AdaptiveSamplingPercentageEvaluatedCallback callback)
 {
     return builder.Use((next) => new AdaptiveSamplingTelemetryProcessor(settings, callback, next) { InitialSamplingPercentage = 100.0 / settings.EffectiveInitialSamplingRate });
 }
        public void MaxTelemetryItemsPerSecondAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();
            settings.MaxTelemetryItemsPerSecond = -10;

            Xunit.Assert.Equal(1E-12, settings.EffectiveMaxTelemetryItemsPerSecond, 12);
        }
        public void MovingAverageRatioSecondsAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();
            settings.MovingAverageRatio = -3;

            Xunit.Assert.Equal(0.25, settings.EffectiveMovingAverageRatio, 12);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SamplingPercentageEstimatorTelemetryProcessor"/> class.
        /// <param name="settings">Dynamic sampling estimator settings.</param>
        /// <param name="callback">Callback to invoke every time sampling percentage is evaluated.</param>
        /// <param name="next">Next TelemetryProcessor in call chain.</param>
        /// </summary>
        public SamplingPercentageEstimatorTelemetryProcessor(
            SamplingPercentageEstimatorSettings settings,
            AdaptiveSamplingPercentageEvaluatedCallback callback,
            ITelemetryProcessor next)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            if (next == null)
            {
                throw new ArgumentNullException("next");
            }

            this.evaluationCallback = callback;
            this.settings           = settings;
            this.next = next;

            this.currenSamplingRate = settings.EffectiveInitialSamplingRate;

            this.itemCount = new ExponentialMovingAverageCounter(settings.EffectiveMovingAverageRatio);

            this.samplingPercentageLastChangeDateTime = DateTimeOffset.UtcNow;

            // set evaluation interval to default value if it is negative or zero
            this.evaluationInterval = this.settings.EffectiveEvaluationInterval;

            // set up timer to run math to estimate sampling percentage
            this.evaluationTimer = new Timer(
                this.EstimateSamplingPercentage,
                null,
                this.evaluationInterval,
                this.evaluationInterval);
        }
        public void SamplingPercentageIncreaseTimeoutSecondsAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();
            settings.SamplingPercentageIncreaseTimeout = TimeSpan.Zero;

            Assert.Equal(TimeSpan.FromMinutes(15), settings.EffectiveSamplingPercentageIncreaseTimeout);
        }
        public void EvaluationIntervalSecondsAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();
            settings.EvaluationInterval = TimeSpan.Zero;

            Assert.Equal(TimeSpan.FromSeconds(15), settings.EffectiveEvaluationInterval);
        }
예제 #7
0
        public void EvaluationIntervalSecondsAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();

            settings.EvaluationInterval = TimeSpan.Zero;

            Assert.AreEqual(TimeSpan.FromSeconds(15), settings.EffectiveEvaluationInterval);
        }
예제 #8
0
        public void MaxTelemetryItemsPerSecondAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();

            settings.MaxTelemetryItemsPerSecond = -10;

            Assert.AreEqual(1E-12, settings.EffectiveMaxTelemetryItemsPerSecond, 12);
        }
예제 #9
0
        public void MovingAverageRatioSecondsAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();

            settings.MovingAverageRatio = -3;

            Assert.AreEqual(0.25, settings.EffectiveMovingAverageRatio, 12);
        }
예제 #10
0
        public void SamplingPercentageIncreaseTimeoutSecondsAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();

            settings.SamplingPercentageIncreaseTimeout = TimeSpan.Zero;

            Assert.AreEqual(TimeSpan.FromMinutes(15), settings.EffectiveSamplingPercentageIncreaseTimeout);
        }
예제 #11
0
        public void MaxSamplingRateAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();

            settings.MinSamplingPercentage = 200;
            Assert.AreEqual(1, settings.EffectiveMaxSamplingRate);

            settings.MinSamplingPercentage = -1;
            Assert.AreEqual(1E8, settings.EffectiveMaxSamplingRate);
        }
        public void MaxSamplingRateAdjustedIfSetToIncorrectValue()
        {
            var settings = new SamplingPercentageEstimatorSettings();

            settings.MinSamplingPercentage = 200;
            Assert.Equal(1, settings.EffectiveMaxSamplingRate);

            settings.MinSamplingPercentage = -1;
            Assert.Equal(1E8, settings.EffectiveMaxSamplingRate);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AdaptiveSamplingTelemetryProcessor"/> class.
        /// <param name="settings">Sampling percentage estimator settings.</param>
        /// <param name="callback">Callback invoked every time sampling percentage is evaluated.</param>
        /// <param name="next">Next TelemetryProcessor in call chain.</param>
        /// </summary>
        public AdaptiveSamplingTelemetryProcessor(
            SamplingPercentageEstimatorSettings settings,
            AdaptiveSamplingPercentageEvaluatedCallback callback,
            ITelemetryProcessor next)
        {
            this.estimatorSettings = settings;
            this.evaluationCallback = callback;

            // make estimatortelemetry processor  work after sampling was done
            this.estimatorProcessor = new SamplingPercentageEstimatorTelemetryProcessor(settings, this.SamplingPercentageChanged, next);
            this.samplingProcessor = new SamplingTelemetryProcessor(this.estimatorProcessor);
        }
예제 #14
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);
        }
        private void SamplingPercentageChanged(
            double afterSamplingTelemetryItemRatePerSecond,
            double currentSamplingPercentage,
            double newSamplingPercentage,
            bool isSamplingPercentageChanged,
            SamplingPercentageEstimatorSettings settings)
        {
            if (isSamplingPercentageChanged)
            {
                this.samplingProcessor.SamplingPercentage = newSamplingPercentage;
                TelemetryChannelEventSource.Log.SamplingChanged(newSamplingPercentage);
            }

            if (this.evaluationCallback != null)
            {
                this.evaluationCallback(
                    afterSamplingTelemetryItemRatePerSecond,
                    currentSamplingPercentage,
                    newSamplingPercentage,
                    isSamplingPercentageChanged,
                    settings);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SamplingPercentageEstimatorTelemetryProcessor"/> class.
        /// <param name="settings">Dynamic sampling estimator settings.</param>
        /// <param name="callback">Callback to invoke every time sampling percentage is evaluated.</param>
        /// <param name="next">Next TelemetryProcessor in call chain.</param>
        /// </summary>
        public SamplingPercentageEstimatorTelemetryProcessor(
            SamplingPercentageEstimatorSettings settings, 
            AdaptiveSamplingPercentageEvaluatedCallback callback, 
            ITelemetryProcessor next)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            if (next == null)
            {
                throw new ArgumentNullException("next");
            }

            this.evaluationCallback = callback;
            this.settings = settings;
            this.next = next;

            this.currenSamplingRate = settings.EffectiveInitialSamplingRate;

            this.itemCount = new ExponentialMovingAverageCounter(settings.EffectiveMovingAverageRatio);

            this.samplingPercentageLastChangeDateTime = DateTimeOffset.UtcNow;

            // set evaluation interval to default value if it is negative or zero
            this.evaluationInterval = this.settings.EffectiveEvaluationInterval;

            // set up timer to run math to estimate sampling percentage
            this.evaluationTimer = new Timer(
                this.EstimateSamplingPercentage, 
                null,
                this.evaluationInterval,
                this.evaluationInterval);
        }
 private void TraceSamplingPercentageEvaluation(
     double afterSamplingTelemetryItemRatePerSecond,
     double currentSamplingPercentage,
     double newSamplingPercentage,
     bool isSamplingPercentageChanged,
     SamplingPercentageEstimatorSettings settings)
 {
     Trace.WriteLine(string.Format(
         "[Sampling% evaluation] {0}, Eps: {1}, Current %: {2}, New %: {3}, Changed: {4}",
         DateTimeOffset.UtcNow.ToString("o"), 
         afterSamplingTelemetryItemRatePerSecond,
         currentSamplingPercentage,
         newSamplingPercentage,
         isSamplingPercentageChanged));
 }