public void Process(ITelemetry item)
        {
            // check telemetry type
            if (item is DependencyTelemetry)
            {
                var d = item as DependencyTelemetry;

                // increment counters
                var metrics = _metrics.GetOrAdd(d.Type, (type) =>
                {
                    var numberOfDependencies = _manager.CreateMetric("# of dependencies", new Dictionary <string, string> {
                        { "type", type }
                    });
                    var dependenciesDuration = _manager.CreateMetric("dependencies duration (ms)", new Dictionary <string, string> {
                        { "type", type }
                    });
                    return(new Tuple <Metric, Metric>(numberOfDependencies, dependenciesDuration));
                });

                metrics.Item1.Track(1);
                metrics.Item2.Track(d.Duration.TotalMilliseconds);

                if (d.Duration < TimeSpan.FromMilliseconds(100))
                {
                    // if dependency duration > 100 msec then stop telemetry
                    // processing and return from the pipeline
                    return;
                }
            }

            this._next.Process(item);
        }
        public void InitializeExtractor(MetricManager metricManager)
        {
            this.responseSuccessTimeMetric = metricManager.CreateMetric(
                MetricTerms.Autocollection.Metric.RequestDuration.Name,
                new Dictionary <string, string>()
            {
                [MetricTerms.Autocollection.Request.PropertyNames.Success] = Boolean.TrueString,
                [MetricTerms.Autocollection.MetricId.Moniker.Key]          = MetricTerms.Autocollection.Metric.RequestDuration.Id,
            });

            this.responseFailureTimeMetric = metricManager.CreateMetric(
                MetricTerms.Autocollection.Metric.RequestDuration.Name,
                new Dictionary <string, string>()
            {
                [MetricTerms.Autocollection.Request.PropertyNames.Success] = Boolean.FalseString,
                [MetricTerms.Autocollection.MetricId.Moniker.Key]          = MetricTerms.Autocollection.Metric.RequestDuration.Id,
            });
        }
Пример #3
0
        static void Main_backup(string[] args)
        {
            var state = new _State();

            state.Initialize();

            TelemetryConfiguration configuration = new TelemetryConfiguration();

            configuration.InstrumentationKey = "fb8a0b03-235a-4b52-b491-307e9fd6b209";

            var telemetryChannel = new ServerTelemetryChannel();

            telemetryChannel.Initialize(configuration);
            configuration.TelemetryChannel = telemetryChannel;


            // data collection modules
            var dependencies = new DependencyTrackingTelemetryModule();

            dependencies.Initialize(configuration);

            // telemetry initializers
            configuration.TelemetryInitializers.Add(new AppVersionTelemetryInitializer());
            configuration.TelemetryInitializers.Add(new DefaultTelemetryInitializer());
            configuration.TelemetryInitializers.Add(new BusinessTelemetryInitializer());
            configuration.TelemetryInitializers.Add(new NodeNameTelemetryInitializer());
            configuration.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());

            // telemetry processors
            configuration.TelemetryProcessorChainBuilder
            .Use((next) => { return(new PriceCalculatorTelemetryProcessor(next, state.Collected)); })
//                .Use((next) => { return new MyTelemetryProcessor(next); })
//                .Use((next) => { return new CleanAutoCollecctedTelemetryProcessor(next); })
//                .Use((next) => { return new ExampleTelemetryProcessor(next); })
            // send only 10% of all dependency data
            .Use((next) =>
            {
                return(new SamplingTelemetryProcessor(next)
                {
                    IncludedTypes = "Dependency",
                    SamplingPercentage = 10
                });
            })
            // start sampling when load exceeds 2 events per second for all telemetry types except events
            .Use((next) =>
            {
                return(new AdaptiveSamplingTelemetryProcessor(next)
                {
                    ExcludedTypes = "Event",
                    MaxTelemetryItemsPerSecond = 2,
                    SamplingPercentageIncreaseTimeout = TimeSpan.FromSeconds(1),
                    SamplingPercentageDecreaseTimeout = TimeSpan.FromSeconds(1),
                    EvaluationInterval = TimeSpan.FromSeconds(1),
                    InitialSamplingPercentage = 25
                });
            })
            .Use((next) => { return(new PriceCalculatorTelemetryProcessor(next, state.Sent)); })
            .Build();

            TelemetryClient client = new TelemetryClient(configuration);

            var iterations = 0;


            MetricManager metricManager    = new MetricManager(client);
            var           itemsProcessed   = metricManager.CreateMetric("Items processed");
            var           processingFailed = metricManager.CreateMetric("Failed processing");
            var           processingSize   = metricManager.CreateMetric("Processing size");


            while (!state.IsTerminated)
            {
                iterations++;

                using (var operaiton = client.StartOperation <RequestTelemetry>("Process item"))
                {
                    client.TrackEvent("test");
                    client.TrackTrace("Something happened");

                    try
                    {
                        HttpClient http = new HttpClient();
                        var        task = http.GetStringAsync("http://bing.com");
                        task.Wait();

                        // metrics aggregation:
                        //itemsProcessed.Track(1);
                        //processingSize.Track(task.Result.Length);
                        //processingFailed.Track(0);

                        //client.TrackMetric("Response size", task.Result.Length);
                        //client.TrackMetric("Successful responses", 1);
                    }
                    catch (Exception exc)
                    {
                        //client.TrackMetric("Successful responses", 0);
                        //operaiton.Telemetry.Success = false;

                        // metrics aggregation:
                        //processingFailed.Track(1);
                    }
                }
            }

            Console.WriteLine($"Program sent 1Mb of telemetry in {iterations} iterations!");
            Console.ReadLine();
        }
Пример #4
0
        public static void Run()
        {
            TelemetryConfiguration configuration = new TelemetryConfiguration();

            configuration.InstrumentationKey = "fb8a0b03-235a-4b52-b491-307e9fd6b209";

            // automatically track dependency calls
            var dependencies = new DependencyTrackingTelemetryModule();

            dependencies.Initialize(configuration);

            // automatically correlate all telemetry data with request
            configuration.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());

            // set default properties for all telemetry items
            configuration.TelemetryInitializers.Add(new DefaultTelemetryInitializer());

            // send all event telemetry to a different iKey
            configuration.TelemetryInitializers.Add(new BusinessTelemetryInitializer());

            // configure all telemetry to be sent to a single node
            configuration.TelemetryInitializers.Add(new NodeNameTelemetryInitializer());

            // initialize price calculation logic
            var state = new _State();

            state.Initialize();

            // enable sampling
            configuration.TelemetryProcessorChainBuilder
            // this telemetry processor will be executed first for all telemetry items to calculate the size and # of items
            .Use((next) => { return(new PriceCalculatorTelemetryProcessor(next, state.Collected)); })

            // this telemetry processor will be execuyted ONLY when telemetry is sampled in
            .Use((next) => { return(new PriceCalculatorTelemetryProcessor(next, state.Sent)); })
            .Build();


            TelemetryClient client = new TelemetryClient(configuration);

            var iterations = 0;

            // configure metrics collection
            MetricManager metricManager    = new MetricManager(client);
            var           itemsProcessed   = metricManager.CreateMetric("Iterations");
            var           processingFailed = metricManager.CreateMetric("Failed processing");
            var           processingSize   = metricManager.CreateMetric("Processing size");

            while (!state.IsTerminated)
            {
                iterations++;

                using (var operaiton = client.StartOperation <RequestTelemetry>("Process item"))
                {
                    client.TrackEvent("test");
                    client.TrackTrace("Something happened", SeverityLevel.Information);

                    try
                    {
                        HttpClient http = new HttpClient();
                        var        task = http.GetStringAsync("http://bing.com");
                        task.Wait();

                        // metrics aggregation. Metrics are aggregated and sent once per minute
                        itemsProcessed.Track(1);
                        processingSize.Track(task.Result.Length);
                        processingFailed.Track(0);

                        // raw metric telemetry. Each call represents a document.
                        client.TrackMetric("[RAW] Response size", task.Result.Length);
                    }
                    catch (Exception exc)
                    {
                        // raw metric telemetry
                        client.TrackMetric("[RAW] Successful responses", 0);

                        // metrics aggregation:
                        processingFailed.Track(1);

                        client.TrackException(exc);
                        operaiton.Telemetry.Success = false;
                    }
                    finally
                    {
                        client.TrackMetric("[RAW] Iterations", 1);
                        itemsProcessed.Track(1);
                    }

                    //                    client.StopOperation(operaiton);
                    //                    Console.WriteLine($"Iteration {iterations}. Elapesed time: {operaiton.Telemetry.Duration}");
                }
            }

            // send all metrics before exiting the program
            metricManager.Flush();

            Console.WriteLine($"Program sent 100K of telemetry in {iterations} iterations!");
            Console.ReadLine();
        }
Пример #5
0
        public static async Task RunAsync(CancellationToken token)
        {
            // set Instrumentation Key
            var configuration = new TelemetryConfiguration();

            configuration.InstrumentationKey = "fb8a0b03-235a-4b52-b491-307e9fd6b209";

            // automatically track dependency calls
            var dependencies = new DependencyTrackingTelemetryModule();

            dependencies.Initialize(configuration);

            // automatically correlate all telemetry data with request
            configuration.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());

            // initialize state for the telemetry size calculation
            var collectedItems = new ProcessedItems();
            var sentItems      = new ProcessedItems();

            // build telemetry processing pipeline
            configuration.TelemetryProcessorChainBuilder

            // this telemetry processor will be executed first for all telemetry items to calculate the size and # of items
            .Use((next) => { return(new SizeCalculatorTelemetryProcessor(next, collectedItems)); })

            // this is a standard fixed sampling processor that will let only 10%
            .Use((next) =>
            {
                return(new SamplingTelemetryProcessor(next)
                {
                    IncludedTypes = "Dependency",
                    SamplingPercentage = 10,
                });
            })

            // this is a standard adaptive sampling telemetry processor that will sample in/out any telemetry item it receives
            .Use((next) =>
            {
                return(new AdaptiveSamplingTelemetryProcessor(next)
                {
                    ExcludedTypes = "Event",                                     // exclude custom events from being sampled
                    MaxTelemetryItemsPerSecond = 1,                              // default: 5 calls/sec
                    SamplingPercentageIncreaseTimeout = TimeSpan.FromSeconds(1), // default: 2 min
                    SamplingPercentageDecreaseTimeout = TimeSpan.FromSeconds(1), // default: 30 sec
                    EvaluationInterval = TimeSpan.FromSeconds(1),                // default: 15 sec
                    InitialSamplingPercentage = 25,                              // default: 100%
                });
            })

            // this telemetry processor will be execuyted ONLY when telemetry is sampled in
            .Use((next) => { return(new SizeCalculatorTelemetryProcessor(next, sentItems)); })
            .Build();

            var client = new TelemetryClient(configuration);

            // configure metrics collection
            MetricManager metricManager = new MetricManager(client);
            var           reductionsize = metricManager.CreateMetric("Reduction Size");

            var iteration = 0;
            var http      = new HttpClient();

            while (!token.IsCancellationRequested)
            {
                iteration++;

                using (var operation = client.StartOperation <RequestTelemetry>("Process item"))
                {
                    client.TrackEvent("test", new Dictionary <string, string>()
                    {
                        { "iteration", iteration.ToString() }
                    });
                    client.TrackTrace($"Iteration {iteration} happened", SeverityLevel.Information);

                    try
                    {
                        await http.GetStringAsync("http://bing.com");
                    }
                    catch (Exception exc)
                    {
                        client.TrackException(exc);
                        operation.Telemetry.Success = false;
                    }

                    client.StopOperation(operation);
                    Console.WriteLine($"Iteration {iteration}. Elapsed time: {operation.Telemetry.Duration}. Collected Telemetry: {collectedItems.Size}/{collectedItems.Count}. Sent Telemetry: {sentItems.Size}/{sentItems.Count}. Ratio: {1.0 * collectedItems.Size / sentItems.Size}");

                    reductionsize.Track(collectedItems.Size - sentItems.Size);
#pragma warning disable 0618
                    client.TrackMetric("[RAW] Reduction Size", collectedItems.Size - sentItems.Size);
#pragma warning restore 0618
                }
            }
        }
        /// <summary>
        /// Initializes the privates and activates them atomically.
        /// </summary>
        /// <param name="maxDependencyTypesToDiscoverCount">Max number of Dependency Types to discover.</param>
        private void ReinitializeMetrics(int maxDependencyTypesToDiscoverCount)
        {
            MetricManager thisMetricManager = this.metricManager;

            if (thisMetricManager == null)
            {
                MetricsCache newMetrics = new MetricsCache();
                newMetrics.MaxDependencyTypesToDiscover = maxDependencyTypesToDiscoverCount;
                this.metrics = newMetrics;
                return;
            }

            if (maxDependencyTypesToDiscoverCount == 0)
            {
                MetricsCache newMetrics = new MetricsCache();

                newMetrics.Default = new SucceessAndFailureMetrics(
                    thisMetricManager.CreateMetric(
                        MetricTerms.Autocollection.Metric.DependencyCallDuration.Name,
                        new Dictionary <string, string>()
                {
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.Success] = Boolean.TrueString,                      // SUCCESS metric
                    [MetricTerms.Autocollection.MetricId.Moniker.Key] = MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                }),
                    thisMetricManager.CreateMetric(
                        MetricTerms.Autocollection.Metric.DependencyCallDuration.Name,
                        new Dictionary <string, string>()
                {
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.Success] = Boolean.FalseString,                     // FAILURE metric
                    [MetricTerms.Autocollection.MetricId.Moniker.Key] = MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                }));

                newMetrics.Unknown = null;
                newMetrics.ByType  = null;
                newMetrics.MaxDependencyTypesToDiscover   = maxDependencyTypesToDiscoverCount;
                newMetrics.TypeDiscoveryLock              = null;
                newMetrics.DependencyTypesDiscoveredCount = 0;

                this.metrics = newMetrics;
            }
            else
            {
                MetricsCache newMetrics = new MetricsCache();

                newMetrics.Default = new SucceessAndFailureMetrics(
                    thisMetricManager.CreateMetric(
                        MetricTerms.Autocollection.Metric.DependencyCallDuration.Name,
                        new Dictionary <string, string>()
                {
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.Success] = Boolean.TrueString,                      // SUCCESS metric
                    [MetricTerms.Autocollection.MetricId.Moniker.Key] = MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.TypeName] = MetricTerms.Autocollection.DependencyCall.TypeNames.Other,
                }),
                    thisMetricManager.CreateMetric(
                        MetricTerms.Autocollection.Metric.DependencyCallDuration.Name,
                        new Dictionary <string, string>()
                {
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.Success] = Boolean.FalseString,                     // FAILURE metric
                    [MetricTerms.Autocollection.MetricId.Moniker.Key] = MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.TypeName] = MetricTerms.Autocollection.DependencyCall.TypeNames.Other,
                }));

                newMetrics.Unknown = new SucceessAndFailureMetrics(
                    thisMetricManager.CreateMetric(
                        MetricTerms.Autocollection.Metric.DependencyCallDuration.Name,
                        new Dictionary <string, string>()
                {
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.Success] = Boolean.TrueString,                      // SUCCESS metric
                    [MetricTerms.Autocollection.MetricId.Moniker.Key] = MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.TypeName] = MetricTerms.Autocollection.DependencyCall.TypeNames.Unknown,
                }),
                    thisMetricManager.CreateMetric(
                        MetricTerms.Autocollection.Metric.DependencyCallDuration.Name,
                        new Dictionary <string, string>()
                {
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.Success] = Boolean.FalseString,                     // FAILURE metric
                    [MetricTerms.Autocollection.MetricId.Moniker.Key] = MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                    [MetricTerms.Autocollection.DependencyCall.PropertyNames.TypeName] = MetricTerms.Autocollection.DependencyCall.TypeNames.Unknown,
                }));

                newMetrics.ByType = new ConcurrentDictionary <string, SucceessAndFailureMetrics>();
                newMetrics.MaxDependencyTypesToDiscover   = maxDependencyTypesToDiscoverCount;
                newMetrics.TypeDiscoveryLock              = new object();
                newMetrics.DependencyTypesDiscoveredCount = 0;

                this.metrics = newMetrics;
            }
        }
        /// <summary>
        /// Extracts appropriate data points for auto-collected, pre-aggregated metrics from a single <c>DependencyTelemetry</c> item.
        /// </summary>
        /// <param name="fromItem">The telemetry item from which to extract the metric data points.</param>
        /// <param name="isItemProcessed">Whether of not the specified item was processed (aka not ignored) by this extractor.</param>
        public void ExtractMetrics(ITelemetry fromItem, out bool isItemProcessed)
        {
            //// If this item is not a DependencyTelemetry, we will not process it:
            DependencyTelemetry dependencyCall = fromItem as DependencyTelemetry;

            if (dependencyCall == null)
            {
                isItemProcessed = false;
                return;
            }

            MetricManager thisMetricManager = this.metricManager;
            MetricsCache  thisMetrics       = this.metrics;

            //// If there is no MetricManager, then this extractor has not been properly initialized yet:
            if (thisMetricManager == null)
            {
                //// This will be caught and properly logged by the base class:
                throw new InvalidOperationException("Cannot execute ExtractMetrics because this metrics extractor has not been initialized (no metrics manager).");
            }

            //// Get dependency call success status:
            bool dependencyFailed = (dependencyCall.Success != null) && (dependencyCall.Success == false);

            //// Now we need to determine which data series to use:
            Metric metricToTrack = null;

            if (thisMetrics.MaxDependencyTypesToDiscover == 0)
            {
                //// If auto-discovering dependency types is disabled, just pick series based on success status:
                metricToTrack = dependencyFailed
                                    ? thisMetrics.Default.Failure
                                    : thisMetrics.Default.Success;
            }
            else
            {
                //// Pick series based on dependency type (and success status):
                string dependencyType = dependencyCall.Type;

                if (dependencyType == null || dependencyType.Equals(string.Empty, StringComparison.OrdinalIgnoreCase))
                {
                    //// If dependency type is not set, we use "Unknown":
                    metricToTrack = dependencyFailed
                                        ? thisMetrics.Unknown.Failure
                                        : thisMetrics.Unknown.Success;
                }
                else
                {
                    //// See if we have already discovered the current dependency type:
                    SucceessAndFailureMetrics typeMetrics;
                    bool previouslyDiscovered = thisMetrics.ByType.TryGetValue(dependencyType, out typeMetrics);

                    if (previouslyDiscovered)
                    {
                        metricToTrack = dependencyFailed
                                    ? typeMetrics.Failure
                                    : typeMetrics.Success;
                    }
                    else
                    {
                        //// We have not seen the current dependency type yet:

                        if (thisMetrics.ByType.Count >= thisMetrics.MaxDependencyTypesToDiscover)
                        {
                            //// If the limit of types to discover is already reached, just use "Other":
                            metricToTrack = dependencyFailed
                                    ? thisMetrics.Default.Failure
                                    : thisMetrics.Default.Success;
                        }
                        else
                        {
                            //// So we have not yet reached the limit.
                            //// We will need to take a lock to make sure that the number of discovered types is used correctly as a limit.
                            //// Note: this is a very rare case. It is expected to occur only MaxDependencyTypesToDiscover times.
                            //// In case of very high contention, this may happen a little more often,
                            //// but will no longer happen once the MaxDependencyTypesToDiscover limit is reached.

                            const string TypeDiscoveryLimitReachedMessage = "Cannot discover more dependency types because the MaxDependencyTypesToDiscover limit"
                                                                            + " is reached. This is a control-flow exception that should not propagate outside "
                                                                            + "the metric extraction logic.";

                            try
                            {
                                typeMetrics = thisMetrics.ByType.GetOrAdd(
                                    dependencyType,
                                    (depType) =>
                                {
                                    lock (thisMetrics.TypeDiscoveryLock)
                                    {
                                        if (thisMetrics.DependencyTypesDiscoveredCount >= thisMetrics.MaxDependencyTypesToDiscover)
                                        {
                                            throw new InvalidOperationException(TypeDiscoveryLimitReachedMessage);
                                        }

                                        thisMetrics.DependencyTypesDiscoveredCount++;

                                        return(new SucceessAndFailureMetrics(
                                                   thisMetricManager.CreateMetric(
                                                       MetricTerms.Autocollection.Metric.DependencyCallDuration.Name,
                                                       new Dictionary <string, string>()
                                        {
                                            [MetricTerms.Autocollection.DependencyCall.PropertyNames.Success] = Boolean.TrueString,                      // SUCCESS metric
                                            [MetricTerms.Autocollection.MetricId.Moniker.Key] = MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                                            [MetricTerms.Autocollection.DependencyCall.PropertyNames.TypeName] = depType,
                                        }),
                                                   thisMetricManager.CreateMetric(
                                                       MetricTerms.Autocollection.Metric.DependencyCallDuration.Name,
                                                       new Dictionary <string, string>()
                                        {
                                            [MetricTerms.Autocollection.DependencyCall.PropertyNames.Success] = Boolean.FalseString,                     // FAILURE metric
                                            [MetricTerms.Autocollection.MetricId.Moniker.Key] = MetricTerms.Autocollection.Metric.DependencyCallDuration.Id,
                                            [MetricTerms.Autocollection.DependencyCall.PropertyNames.TypeName] = depType,
                                        })));
                                    }
                                });
                            }
                            catch (InvalidOperationException ex)
                            {
                                if (!ex.Message.Equals(TypeDiscoveryLimitReachedMessage, StringComparison.Ordinal))
                                {
#if NET40
                                    throw;
#else
                                    ExceptionDispatchInfo.Capture(ex).Throw();
#endif
                                }

                                //// Limit was reached concurrently. We will use "Other" after all:
                                metricToTrack = dependencyFailed
                                    ? thisMetrics.Default.Failure
                                    : thisMetrics.Default.Success;
                            }

                            //// Use the newly created metric for this newly discovered dependency type:
                            metricToTrack = dependencyFailed
                                    ? typeMetrics.Failure
                                    : typeMetrics.Success;
                        }
                    }   // else OF if (previouslyDiscovered)
                }
            }

            //// Now that we selected the right metric, track the value:
            isItemProcessed = true;
            metricToTrack.Track(dependencyCall.Duration.TotalMilliseconds);
        }