Exemple #1
0
 /// <summary>@ToDo: Complete documentation before stable release. {632}</summary>
 /// <param name="telemetryItem">@ToDo: Complete documentation before stable release. {469}</param>
 /// <param name="aggregate">@ToDo: Complete documentation before stable release. {380}</param>
 protected abstract void PopulateDataValues(MetricTelemetry telemetryItem, MetricAggregate aggregate);
        private void RecordNormalMetric(TelemetryConfiguration telemetryPipeline)
        {
            MetricSeries durationMeric = telemetryPipeline.GetMetricManager().CreateNewSeries(
                "Item Add duration",
                new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false));

            MockContainerDataStructure dataStructure = new MockContainerDataStructure((c) => TimeSpan.FromSeconds(c));

            DateTimeOffset experimentStart = new DateTimeOffset(2017, 9, 14, 0, 0, 0, TimeSpan.Zero);

            // Stop the default minute-ly cycle so that it does not interfere with our virtual time debugging:
            Task fireAndForget = telemetryPipeline.GetMetricManager().StopDefaultAggregationCycleAsync();

            telemetryPipeline.GetMetricManager().StartOrCycleAggregators(CycleKind.Custom, experimentStart, futureFilter: null);

            const int ExperimentLengthSecs = 60 * 10;
            const int IntervalLengthSecs   = 60;

            int totalSecs    = 0;
            int intervalSecs = 0;

            int       itemsThisTime   = 0;
            const int maxItemsAtATime = 4;

            int operationsCount = 0;

            while (totalSecs < ExperimentLengthSecs)
            {
                itemsThisTime = (itemsThisTime + 1) % maxItemsAtATime;

                int addItemCount    = 1 + (itemsThisTime + 1) % maxItemsAtATime;
                int removeItemCount = 1 + itemsThisTime % maxItemsAtATime;

                Trace.WriteLine($"{totalSecs})");
                Trace.WriteLine(addItemCount);
                Trace.WriteLine(removeItemCount);
                Trace.WriteLine("");

                TimeSpan duration;

                dataStructure.AddItems(addItemCount, out duration);
                operationsCount++;

                int durationSecs = (int)duration.TotalSeconds;
                durationMeric.TrackValue(durationSecs);

                totalSecs    += durationSecs;
                intervalSecs += durationSecs;

                dataStructure.RemoveItems(removeItemCount, out duration);
                operationsCount++;

                durationSecs = (int)duration.TotalSeconds;
                durationMeric.TrackValue(durationSecs);

                totalSecs    += durationSecs;
                intervalSecs += durationSecs;

                if (intervalSecs >= IntervalLengthSecs)
                {
                    AggregationPeriodSummary aggregatedMetrics = telemetryPipeline.GetMetricManager().StartOrCycleAggregators(
                        CycleKind.Custom,
                        experimentStart.AddSeconds(totalSecs),
                        futureFilter: null);
                    Assert.IsNotNull(aggregatedMetrics);

                    IReadOnlyList <MetricAggregate> aggregates = aggregatedMetrics.NonpersistentAggregates;
                    Assert.IsNotNull(aggregates);
                    Assert.AreEqual(1, aggregates.Count);

                    MetricAggregate aggregate = aggregates[0];
                    Assert.IsNotNull(aggregates);

                    Assert.AreEqual(1.0, aggregate.Data["Min"]);
                    Assert.AreEqual(4.0, aggregate.Data["Max"]);
                    Assert.AreEqual(operationsCount, aggregate.Data["Count"]);
                    Assert.AreEqual("Item Add duration", aggregate.MetricId);
                    Assert.IsNotNull(aggregate.Dimensions);
                    Assert.AreEqual(0, aggregate.Dimensions.Count);
                    Assert.AreEqual((double)intervalSecs, aggregate.Data["Sum"]);
                    Assert.AreEqual(experimentStart.AddSeconds(totalSecs - intervalSecs), aggregate.AggregationPeriodStart);

                    intervalSecs   %= IntervalLengthSecs;
                    operationsCount = 0;

                    Assert.AreEqual(0, intervalSecs, "For the above to work, the number of wirtual secs must exactly fit into IntervalLengthSecs.");
                }
            }
            {
                AggregationPeriodSummary aggregatedMetrics = telemetryPipeline.GetMetricManager().StartOrCycleAggregators(
                    CycleKind.Custom,
                    experimentStart.AddSeconds(totalSecs),
                    futureFilter: null);
                Assert.IsNotNull(aggregatedMetrics);

                IReadOnlyList <MetricAggregate> aggregates = aggregatedMetrics.NonpersistentAggregates;
                Assert.IsNotNull(aggregates);
                Assert.AreEqual(0, aggregates.Count);
            }
            {
                durationMeric.TrackValue("7");
                durationMeric.TrackValue("8");
                durationMeric.TrackValue("9.0");
                totalSecs += 24;
            }
            {
                AggregationPeriodSummary aggregatedMetrics = telemetryPipeline.GetMetricManager().StopAggregators(
                    CycleKind.Custom,
                    experimentStart.AddSeconds(totalSecs));
                Assert.IsNotNull(aggregatedMetrics);

                IReadOnlyList <MetricAggregate> aggregates = aggregatedMetrics.NonpersistentAggregates;
                Assert.IsNotNull(aggregates);

                MetricAggregate aggregate = aggregates[0];
                Assert.IsNotNull(aggregates);

                Assert.AreEqual(7.0, aggregate.Data["Min"]);
                Assert.AreEqual(9.0, aggregate.Data["Max"]);
                Assert.AreEqual(3, aggregate.Data["Count"]);
                Assert.AreEqual("Item Add duration", aggregate.MetricId);
                Assert.IsNotNull(aggregate.Dimensions);
                Assert.AreEqual(0, aggregate.Dimensions.Count);
                Assert.AreEqual(24.0, aggregate.Data["Sum"]);
                Assert.AreEqual(experimentStart.AddSeconds(totalSecs - 24), aggregate.AggregationPeriodStart);
            }
        }
        /// <summary>
        /// Used to make sure we report 0 values if nothing new comes in
        /// </summary>
        public static void HandleZeroReports(DateTime currentMinute)
        {
            foreach (var item in _LastAggregates)
            {
                MetricSetting setting;
                if (_MetricSettings.TryGetValue(item.Value.NameKey, out setting))
                {
                    if (setting == null)
                    {
                        MetricSetting remove;
                        _MetricSettings.TryRemove(item.Value.NameKey, out remove);
                        continue;
                    }

                    MetricAggregate agg = new MetricAggregate(item.Value.Category, item.Value.Name, item.Value.MetricType);
                    agg.OccurredUtc = currentMinute;


                    switch (item.Value.MetricType)
                    {
                    case MetricType.Counter:
                        setting.AutoReportLastValueIfNothingReported = false;    //do not allow this
                        break;

                    case MetricType.CounterTime:
                        setting.AutoReportLastValueIfNothingReported = false;     //do not allow this
                        break;

                    case MetricType.MetricAverage:
                        break;

                    case MetricType.MetricLast:
                        break;
                    }

                    if (setting.AutoReportZeroIfNothingReported)
                    {
                        agg.Count = 1;
                        agg.Value = 0;
                    }
                    else if (setting.AutoReportLastValueIfNothingReported)
                    {
                        agg.Count = item.Value.Count;
                        agg.Value = item.Value.Value;
                    }
                    else
                    {
                        continue;
                    }

                    string aggKey = agg.AggregateKey();

                    if (!_AggregateMetrics.ContainsKey(aggKey))
                    {
                        agg.NameKey = item.Value.NameKey;
                        StackifyAPILogger.Log("Creating 0 default value for " + aggKey);
                        _AggregateMetrics[aggKey] = agg;
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Read everything in the queue up to a certain time point
        /// </summary>
        private static void ReadAllQueuedMetrics()
        {
            // read only up until now so it doesn't get stuck in an endless loop
            // Loop through add sum up the totals of the counts and values by aggregate key then pass it all in at once to update the aggregate dictionary so it is done in one pass
            // key is the aggregate key which is the metric name, type and rounded minute of the occurrence

            var maxDate = DateTime.UtcNow;

            StackifyAPILogger.Log($"ReadAllQueuedMetrics {maxDate}");

            var batches = new Dictionary <string, MetricAggregate>();

            long processed = 0;

            Metric metric;

            while (MetricQueue.TryDequeue(out metric))
            {
                processed++;

                metric.CalcAndSetAggregateKey();

                if (batches.ContainsKey(metric.AggregateKey) == false)
                {
                    var nameKey = metric.CalcNameKey();

                    var agg = new MetricAggregate(metric);

                    if (metric.IsIncrement)
                    {
                        if (LastAggregates.ContainsKey(nameKey))
                        {
                            // if wanting to do increments we need to grab the last value so we know what to increment
                            metric.Value = LastAggregates[nameKey].Value;
                        }
                    }

                    batches[metric.AggregateKey] = agg;

                    // if it is null don't do anything
                    // we are doing it where the aggregates are created so we don't do it one very single metric, just once per batch to optimize performance
                    if (metric.Settings != null)
                    {
                        MetricSettings[nameKey] = metric.Settings;
                    }
                }

                batches[metric.AggregateKey].Count++;

                if (metric.IsIncrement)
                {
                    // safety
                    var val = batches[metric.AggregateKey].Value;
                    if (val.Equals(double.MinValue) || val.Equals(double.MaxValue))
                    {
                        batches[metric.AggregateKey].Value = 0;

                        StackifyAPILogger.Log($"Read queued metrics reset increment {metric.AggregateKey} to zero due to min/max value of {val}");
                    }

                    //add or subtract
                    batches[metric.AggregateKey].Value += metric.Value;

                    // allow negative?
                    if (metric.Settings != null && batches[metric.AggregateKey].Value < 0 && metric.Settings.AllowNegativeGauge == false)
                    {
                        batches[metric.AggregateKey].Value = 0;
                    }
                }
                else if (metric.MetricType == MetricType.MetricLast)
                {
                    //should end up the last value
                    batches[metric.AggregateKey].Value = metric.Value;
                }
                else
                {
                    batches[metric.AggregateKey].Value += metric.Value;
                }

                if (metric.Occurred > maxDate)
                {
                    //we don't need anything more this recent so bail
                    break;
                }
            }

            StackifyAPILogger.Log($"Read queued metrics processed {processed} for max date {maxDate}");

            foreach (KeyValuePair <string, MetricAggregate> batch in batches)
            {
                Aggregate(batch.Value);
            }
        }
        public async Task TrackAsync_CorrectlyCopiesTelemetryContextDimensions()
        {
            const string mockInstrumentationKey = "103CFCEC-BDA6-4EBC-B1F0-2652654DC6FD";

            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");

                    aggregate.AggregationPeriodStart = new DateTimeOffset(1492, 10, 12, 0, 0, 0, TimeSpan.Zero);

                    aggregate.Dimensions["Dim 1"] = "DV1";
                    aggregate.Dimensions["Dim 2"] = "DV2";
                    aggregate.Dimensions["Dim 3"] = "DV3";
                    aggregate.Dimensions["Dim 2"] = "DV2a";
                    aggregate.Dimensions["Dim 4"] = "";
                    aggregate.Dimensions["Dim 5"] = null;
                    aggregate.Dimensions["Dim 6"] = "  ";
                    aggregate.Dimensions[""]      = "DVb1";
                    aggregate.Dimensions[" "]     = "DVb2";
                    Assert.ThrowsException <ArgumentNullException>(() => { aggregate.Dimensions[null] = "DVb2"; });

                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.InstrumentationKey] = "Aggregate's Instrumentsion Key";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Property("Prop 1")] = "PV1";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Property("Prop 2")] = "PV2";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Property("Dim 1")]  = "Dim V 1";

                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Cloud.RoleInstance]          = "A";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Cloud.RoleName]              = "B";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Component.Version]           = "C";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.Id]                   = "D";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.Language]             = "E";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.Model]                = "F";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.NetworkType]          = "G";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.OemName]              = "H";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.OperatingSystem]      = "I";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.ScreenResolution]     = "J";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.Type]                 = "K";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Location.Ip]                 = "L";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Operation.CorrelationVector] = "M";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Operation.Id]                = "N";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Operation.Name]              = "O";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Operation.ParentId]          = "P";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Operation.SyntheticSource]   = "R";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Session.Id]                  = "S";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Session.IsFirst]             = "TRUE";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.User.AccountId]              = "U";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.User.AuthenticatedUserId]    = "V";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.User.Id]        = "W";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.User.UserAgent] = "X";

                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    // This is super strange. Count is changed from 0 to 1 in MetricTelemetry.Sanitize(). But it seems to happen only in Debug mode!
                    // This needs to be investigated! (@ToDo)
                    // It would indicate that we are sending different telemetry from exactly the same code depending on whether the app
                    // runs under a debugger. That wouldn't be good. (Noticed with SDK 2.3)
                    int expectedCount = Debugger.IsAttached ? 1 : 0;
                    Util.ValidateNumericAggregateValues(
                        metricTelemetry,
                        "mid-foobar",
                        expectedCount,
                        sum:    0,
                        max:    0,
                        min:    0,
                        stdDev: 0,
                        timestamp:  new DateTimeOffset(1492, 10, 12, 0, 0, 0, TimeSpan.Zero),
                        periodMs:   "0");

                    string props = $"metricTelemetry.Properties[{metricTelemetry.Properties.Count}] {{ ";
                    foreach (KeyValuePair <string, string> kvp in metricTelemetry.Properties)
                    {
                        props = props + $"[\"{kvp.Key}\"]=\"{kvp.Value}\", ";
                    }
                    props = props + " }";

                    // This is another super strange case where we seem to be gettin gdifferent results depending on whether a dubugger is attached.
                    // It seems to be the same Sanitization issue as above (@ToDo)
                    if (Debugger.IsAttached)
                    {
                        Assert.AreEqual(9, metricTelemetry.Properties.Count, props);
                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 1"));
                        Assert.AreEqual("DV1", metricTelemetry.Properties["Dim 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 2"));
                        Assert.AreEqual("DV2a", metricTelemetry.Properties["Dim 2"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 3"));
                        Assert.AreEqual("DV3", metricTelemetry.Properties["Dim 3"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Prop 1"));
                        Assert.AreEqual("PV1", metricTelemetry.Properties["Prop 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Prop 2"));
                        Assert.AreEqual("PV2", metricTelemetry.Properties["Prop 2"]);
                    }
                    else
                    {
                        Assert.AreEqual(11, metricTelemetry.Properties.Count, props);
                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 1"));
                        Assert.AreEqual("DV1", metricTelemetry.Properties["Dim 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 2"));
                        Assert.AreEqual("DV2a", metricTelemetry.Properties["Dim 2"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 3"));
                        Assert.AreEqual("DV3", metricTelemetry.Properties["Dim 3"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 4"));
                        Assert.AreEqual("", metricTelemetry.Properties["Dim 4"]);

                        Assert.IsFalse(metricTelemetry.Properties.ContainsKey("Dim 5"));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 6"));
                        Assert.AreEqual("  ", metricTelemetry.Properties["Dim 6"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Prop 1"));
                        Assert.AreEqual("PV1", metricTelemetry.Properties["Prop 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Prop 2"));
                        Assert.AreEqual("PV2", metricTelemetry.Properties["Prop 2"]);
                    }

                    Util.ValidateSdkVersionString(metricTelemetry.Context.GetInternalContext().SdkVersion);
                    Assert.AreEqual("Aggregate's Instrumentsion Key", metricTelemetry.Context.InstrumentationKey);

                    Assert.AreEqual("A", metricTelemetry.Context.Cloud.RoleInstance);
                    Assert.AreEqual("B", metricTelemetry.Context.Cloud.RoleName);
                    Assert.AreEqual("C", metricTelemetry.Context.Component.Version);
                    Assert.AreEqual("D", metricTelemetry.Context.Device.Id);
#pragma warning disable CS0618 // Type or member is obsolete
                    Assert.AreEqual("E", metricTelemetry.Context.Device.Language);
#pragma warning restore CS0618 // Type or member is obsolete
                    Assert.AreEqual("F", metricTelemetry.Context.Device.Model);
#pragma warning disable CS0618 // Type or member is obsolete
                    Assert.AreEqual("G", metricTelemetry.Context.Device.NetworkType);
#pragma warning restore CS0618 // Type or member is obsolete
                    Assert.AreEqual("H", metricTelemetry.Context.Device.OemName);
                    Assert.AreEqual("I", metricTelemetry.Context.Device.OperatingSystem);
#pragma warning disable CS0618 // Type or member is obsolete
                    Assert.AreEqual("J", metricTelemetry.Context.Device.ScreenResolution);
#pragma warning restore CS0618 // Type or member is obsolete
                    Assert.AreEqual("K", metricTelemetry.Context.Device.Type);
                    Assert.AreEqual("L", metricTelemetry.Context.Location.Ip);
                    Assert.AreEqual("M", metricTelemetry.Context.Operation.CorrelationVector);
                    Assert.AreEqual("N", metricTelemetry.Context.Operation.Id);
                    Assert.AreEqual("O", metricTelemetry.Context.Operation.Name);
                    Assert.AreEqual("P", metricTelemetry.Context.Operation.ParentId);
                    Assert.AreEqual("R", metricTelemetry.Context.Operation.SyntheticSource);
                    Assert.AreEqual("S", metricTelemetry.Context.Session.Id);
                    Assert.AreEqual(true, metricTelemetry.Context.Session.IsFirst);
                    Assert.AreEqual("U", metricTelemetry.Context.User.AccountId);
                    Assert.AreEqual("V", metricTelemetry.Context.User.AuthenticatedUserId);
                    Assert.AreEqual("W", metricTelemetry.Context.User.Id);
                    Assert.AreEqual("X", metricTelemetry.Context.User.UserAgent);
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");

                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Cloud.RoleName]  = "";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Device.Model]    = null;
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Location.Ip]     = "  ";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Session.IsFirst] = "0";

                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    Assert.AreEqual(1, metricTelemetry.Properties.Count);
                    Assert.IsTrue(metricTelemetry.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

                    Util.ValidateSdkVersionString(metricTelemetry.Context.GetInternalContext().SdkVersion);

                    Assert.AreEqual(null, metricTelemetry.Context.Cloud.RoleName);
                    Assert.AreEqual(null, metricTelemetry.Context.Device.Model);
                    Assert.AreEqual("  ", metricTelemetry.Context.Location.Ip);
                    Assert.AreEqual(false, metricTelemetry.Context.Session.IsFirst);
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");

                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Session.Id]      = "some string";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Session.IsFirst] = "bad string";

                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    Assert.AreEqual(1, metricTelemetry.Properties.Count);
                    Assert.IsTrue(metricTelemetry.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

                    Util.ValidateSdkVersionString(metricTelemetry.Context.GetInternalContext().SdkVersion);

                    Assert.AreEqual("some string", metricTelemetry.Context.Session.Id);
                    Assert.AreEqual(null, metricTelemetry.Context.Session.IsFirst);
                }
            }
        }
        public async Task TrackAsync_SendsCorrectly()
        {
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    using (var cancelControl = new CancellationTokenSource())
                    {
                        cancelControl.Cancel();
                        await Assert.ThrowsExceptionAsync <ArgumentNullException>(() => pipelineAdapter.TrackAsync(null, cancelControl.Token));
                    }
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    using (var cancelControl = new CancellationTokenSource())
                    {
                        cancelControl.Cancel();
                        await Assert.ThrowsExceptionAsync <OperationCanceledException>(() => pipelineAdapter.TrackAsync(
                                                                                           new MetricAggregate("mid", "BadMoniker"),
                                                                                           cancelControl.Token));
                    }
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    using (var cancelControl = new CancellationTokenSource())
                    {
                        await Assert.ThrowsExceptionAsync <ArgumentException>(() => pipelineAdapter.TrackAsync(
                                                                                  new MetricAggregate("mid", "BadMoniker"),
                                                                                  cancelControl.Token));
                    }
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    using (var cancelControl = new CancellationTokenSource())
                    {
                        cancelControl.Cancel();
                        await Assert.ThrowsExceptionAsync <OperationCanceledException>(() => pipelineAdapter.TrackAsync(
                                                                                           new MetricAggregate("mid", MetricConfigurations.Common.AggregateKinds().Measurement().Moniker),
                                                                                           cancelControl.Token));
                    }
                }
            }
            {
                // Force registration of the converter with the telemetry pipeline:
                new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false);

                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    {
                        var agregate = new MetricAggregate("M1", MetricConfigurations.Common.AggregateKinds().Measurement().Moniker);
                        agregate.Data["Count"] = 1;
                        agregate.Data["Sum"]   = 10;
                        await pipelineAdapter.TrackAsync(agregate, CancellationToken.None);
                    }
                    {
                        var agregate = new MetricAggregate("M2", MetricConfigurations.Common.AggregateKinds().Measurement().Moniker);
                        agregate.Data["Count"] = 0;
                        agregate.Data["Sum"]   = 20;
                        await pipelineAdapter.TrackAsync(agregate, CancellationToken.None);
                    }
                    {
                        var agregate = new MetricAggregate("M3", MetricConfigurations.Common.AggregateKinds().Measurement().Moniker);
                        agregate.Data["Sum"] = 30;
                        await pipelineAdapter.TrackAsync(agregate, CancellationToken.None);
                    }
                    {
                        var agregate = new MetricAggregate("M4", MetricConfigurations.Common.AggregateKinds().Measurement().Moniker);
                        agregate.Data["Count"] = 2.9;
                        agregate.Data["Sum"]   = -40;
                        await pipelineAdapter.TrackAsync(agregate, CancellationToken.None);
                    }

                    // This is super strange. Count is changed from 0 to 1 in MetricTelemetry.Sanitize(). But it seems to happen only in Debug mode!
                    // This needs to be investigated! (@ToDo)
                    // It would indicate that we are sending different telemetry from exactly the same code depending on whether the app
                    // runs under a debugger. That wouldn't be good. (Noticed with SDK 2.3)
                    int expectedCountWhenZero = Debugger.IsAttached ? 1 : 0;

                    Assert.IsNotNull(telemetrySentToChannel);
                    Assert.AreEqual(4, telemetrySentToChannel.Count);

                    Assert.AreEqual(1, telemetrySentToChannel.Where((item) => (item as MetricTelemetry).Name.Equals("M1")).Count());
                    Assert.AreEqual(1, (telemetrySentToChannel.First((item) => (item as MetricTelemetry).Name.Equals("M1")) as MetricTelemetry).Count);
                    Assert.AreEqual(10.0, (telemetrySentToChannel.First((item) => (item as MetricTelemetry).Name.Equals("M1")) as MetricTelemetry).Sum);

                    Assert.AreEqual(1, telemetrySentToChannel.Where((item) => (item as MetricTelemetry).Name.Equals("M2")).Count());
                    Assert.AreEqual(expectedCountWhenZero, (telemetrySentToChannel.First((item) => (item as MetricTelemetry).Name.Equals("M2")) as MetricTelemetry).Count);
                    Assert.AreEqual(20.0, (telemetrySentToChannel.First((item) => (item as MetricTelemetry).Name.Equals("M2")) as MetricTelemetry).Sum);

                    Assert.AreEqual(1, telemetrySentToChannel.Where((item) => (item as MetricTelemetry).Name.Equals("M3")).Count());
                    Assert.AreEqual(expectedCountWhenZero, (telemetrySentToChannel.First((item) => (item as MetricTelemetry).Name.Equals("M3")) as MetricTelemetry).Count);
                    Assert.AreEqual(30.0, (telemetrySentToChannel.First((item) => (item as MetricTelemetry).Name.Equals("M3")) as MetricTelemetry).Sum);

                    Assert.AreEqual(1, telemetrySentToChannel.Where((item) => (item as MetricTelemetry).Name.Equals("M4")).Count());
                    Assert.AreEqual(3, (telemetrySentToChannel.First((item) => (item as MetricTelemetry).Name.Equals("M4")) as MetricTelemetry).Count);
                    Assert.AreEqual(-40.0, (telemetrySentToChannel.First((item) => (item as MetricTelemetry).Name.Equals("M4")) as MetricTelemetry).Sum);
                }
            }
        }
        public async Task TrackAsync_HandlesDifferentAggregates()
        {
            const string mockInstrumentationKey = "103CFCEC-BDA6-4EBC-B1F0-2652654DC6FD";

            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Something");
                    await Assert.ThrowsExceptionAsync <ArgumentException>(() => pipelineAdapter.TrackAsync(aggregate, CancellationToken.None));

                    Assert.AreEqual(0, telemetrySentToChannel.Count);
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");
                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    // This is super strange. Count is changed from 0 to 1 in MetricTelemetry.Sanitize(). But it seems to happen only in Debug mode!
                    // This needs to be investigated! (@ToDo)
                    // It would indicate that we are sending different telemetry from exactly the same code depending on whether the app
                    // runs under a debugger. That wouldn't be good. (Noticed with SDK 2.3)
                    int expectedCount = Debugger.IsAttached ? 1 : 0;
                    Util.ValidateNumericAggregateValues(metricTelemetry, "mid-foobar", expectedCount, sum: 0, max: 0, min: 0, stdDev: 0);

                    Assert.AreEqual(1, metricTelemetry.Properties.Count);
                    Assert.IsTrue(metricTelemetry.Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                    Assert.AreEqual("0", metricTelemetry.Context.Properties[Util.AggregationIntervalMonikerPropertyKey]);
                    Assert.IsTrue((metricTelemetry.Timestamp - DateTimeOffset.Now).Duration() < TimeSpan.FromMilliseconds(100));


                    Assert.AreEqual(mockInstrumentationKey, metricTelemetry.Context.InstrumentationKey);
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");

                    aggregate.AggregationPeriodStart    = new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8));
                    aggregate.AggregationPeriodDuration = TimeSpan.FromSeconds(90);

                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    // This is super strange. Count is changed from 0 to 1 in MetricTelemetry.Sanitize(). But it seems to happen only in Debug mode!
                    // This needs to be investigated! (@ToDo)
                    // It would indicate that we are sending different telemetry from exactly the same code depending on whether the app
                    // runs under a debugger. That wouldn't be good. (Noticed with SDK 2.3)
                    int expectedCount = Debugger.IsAttached ? 1 : 0;
                    Util.ValidateNumericAggregateValues(
                        metricTelemetry,
                        "mid-foobar",
                        expectedCount,
                        sum:        0,
                        max:        0,
                        min:        0,
                        stdDev:     0,
                        timestamp:  new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8)),
                        periodMs:   "90000");
                    Assert.AreEqual(1, metricTelemetry.Properties.Count);

                    Assert.AreEqual(mockInstrumentationKey, metricTelemetry.Context.InstrumentationKey);
                    Util.ValidateSdkVersionString(metricTelemetry.Context.GetInternalContext().SdkVersion);
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");

                    aggregate.AggregationPeriodStart    = new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8));
                    aggregate.AggregationPeriodDuration = TimeSpan.FromSeconds(90);

                    aggregate.Data["Foo"] = "Bar";

                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    // This is super strange. Count is changed from 0 to 1 in MetricTelemetry.Sanitize(). But it seems to happen only in Debug mode!
                    // This needs to be investigated! (@ToDo)
                    // It would indicate that we are sending different telemetry from exactly the same code depending on whether the app
                    // runs under a debugger. That wouldn't be good. (Noticed with SDK 2.3)
                    int expectedCount = Debugger.IsAttached ? 1 : 0;
                    Util.ValidateNumericAggregateValues(
                        metricTelemetry,
                        "mid-foobar",
                        expectedCount,
                        sum:        0,
                        max:        0,
                        min:        0,
                        stdDev:     0,
                        timestamp:  new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8)),
                        periodMs:   "90000");
                    Assert.AreEqual(1, metricTelemetry.Properties.Count);

                    Assert.AreEqual(mockInstrumentationKey, metricTelemetry.Context.InstrumentationKey);
                    Util.ValidateSdkVersionString(metricTelemetry.Context.GetInternalContext().SdkVersion);
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");

                    aggregate.AggregationPeriodStart    = new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8));
                    aggregate.AggregationPeriodDuration = TimeSpan.FromSeconds(90);

                    aggregate.Data["Murr"] = "Miau";
                    aggregate.Data["Purr"] = null;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Count]  = 1.2;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Sum]    = "one";
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Min]    = "2.3";
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Max]    = "-4";
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.StdDev] = 5;

                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    Util.ValidateNumericAggregateValues(
                        metricTelemetry,
                        "mid-foobar",
                        count:      1,
                        sum:        0,
                        max:        -4,
                        min:        2.3,
                        stdDev:     5,
                        timestamp:  new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8)),
                        periodMs:   "90000");
                    Assert.AreEqual(1, metricTelemetry.Properties.Count);

                    Assert.AreEqual(mockInstrumentationKey, metricTelemetry.Context.InstrumentationKey);
                    Util.ValidateSdkVersionString(metricTelemetry.Context.GetInternalContext().SdkVersion);
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");

                    aggregate.AggregationPeriodStart    = new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8));
                    aggregate.AggregationPeriodDuration = TimeSpan.FromSeconds(90);

                    aggregate.Data["Murr"] = "Miau";
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Count]  = -3.7;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Sum]    = "-100";
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Min]    = -10000000000;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Max]    = ((double)Int32.MaxValue) + 100;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.StdDev] = -2;

                    aggregate.Dimensions["Dim 1"] = "DV1";
                    aggregate.Dimensions["Dim 2"] = "DV2";
                    aggregate.Dimensions["Dim 3"] = "DV3";
                    aggregate.Dimensions["Dim 2"] = "DV2a";
                    aggregate.Dimensions["Dim 4"] = "";
                    aggregate.Dimensions["Dim 5"] = null;
                    aggregate.Dimensions["Dim 6"] = "  ";

                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    // This is super strange. Count is changed from 0 to 1 in MetricTelemetry.Sanitize(). But it seems to happen only in Debug mode!
                    // This needs to be investigated! (@ToDo)
                    // It would indicate that we are sending different telemetry from exactly the same code depending on whether the app
                    // runs under a debugger. That wouldn't be good. (Noticed with SDK 2.3)
                    int expectedCount = Debugger.IsAttached ? 1 : -4;
                    Util.ValidateNumericAggregateValues(
                        metricTelemetry,
                        "mid-foobar",
                        expectedCount,
                        sum:        -100,
                        max:        ((double)Int32.MaxValue) + 100,
                        min:        -10000000000,
                        stdDev:     -2,
                        timestamp:  new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8)),
                        periodMs:   "90000");

                    string props = $"metricTelemetry.Properties[{metricTelemetry.Properties.Count}] {{ ";
                    foreach (KeyValuePair <string, string> kvp in metricTelemetry.Properties)
                    {
                        props = props + $"[\"{kvp.Key}\"]=\"{kvp.Value}\", ";
                    }
                    props = props + " }";

                    // This is another super strange case where we seem to be gettin gdifferent results depending on whether a dubugger is attached.
                    // It seems to be the same Sanitization issue as above (@ToDo)
                    if (Debugger.IsAttached)
                    {
                        Assert.AreEqual(4, metricTelemetry.Properties.Count, props);
                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 1"));
                        Assert.AreEqual("DV1", metricTelemetry.Properties["Dim 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 2"));
                        Assert.AreEqual("DV2a", metricTelemetry.Properties["Dim 2"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 3"));
                        Assert.AreEqual("DV3", metricTelemetry.Properties["Dim 3"]);
                    }
                    else
                    {
                        Assert.AreEqual(6, metricTelemetry.Properties.Count, props);
                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 1"));
                        Assert.AreEqual("DV1", metricTelemetry.Properties["Dim 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 2"));
                        Assert.AreEqual("DV2a", metricTelemetry.Properties["Dim 2"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 3"));
                        Assert.AreEqual("DV3", metricTelemetry.Properties["Dim 3"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 4"));
                        Assert.AreEqual("", metricTelemetry.Properties["Dim 4"]);

                        Assert.IsFalse(metricTelemetry.Properties.ContainsKey("Dim 5"));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 6"));
                        Assert.AreEqual("  ", metricTelemetry.Properties["Dim 6"]);
                    }

                    Assert.AreEqual(mockInstrumentationKey, metricTelemetry.Context.InstrumentationKey);
                    Util.ValidateSdkVersionString(metricTelemetry.Context.GetInternalContext().SdkVersion);
                }
            }
            {
                IList <ITelemetry>     telemetrySentToChannel;
                TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out telemetrySentToChannel);
                using (telemetryPipeline)
                {
                    telemetryPipeline.InstrumentationKey = mockInstrumentationKey;
                    var pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);

                    var aggregate = new MetricAggregate("mid-foobar", "Microsoft.Azure.Measurement");

                    aggregate.AggregationPeriodStart    = new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8));
                    aggregate.AggregationPeriodDuration = TimeSpan.FromSeconds(90);

                    aggregate.Data["Murr"] = "Miau";
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Count]  = -3.7;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Sum]    = null;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Min]    = -10000000000;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.Max]    = ((double)Int32.MaxValue) + 100;
                    aggregate.Data[MetricConfigurations.Common.AggregateKinds().Measurement().DataKeys.StdDev] = -2;

                    aggregate.Dimensions["Dim 1"] = "DV1";
                    aggregate.Dimensions["Dim 2"] = "DV2";
                    aggregate.Dimensions["Dim 3"] = "DV3";
                    aggregate.Dimensions["Dim 2"] = "DV2a";
                    aggregate.Dimensions["Dim 4"] = "";
                    aggregate.Dimensions["Dim 5"] = null;
                    aggregate.Dimensions["Dim 6"] = "  ";
                    aggregate.Dimensions[""]      = "DVb1";
                    aggregate.Dimensions[" "]     = "DVb2";
                    Assert.ThrowsException <ArgumentNullException>(() => { aggregate.Dimensions[null] = "DVb2"; });

                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.InstrumentationKey] = "Aggregate's Instrumentsion Key";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Property("Prop 1")] = "PV1";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Property("Prop 2")] = "PV2";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Property("Dim 1")]  = "Dim V 1";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Operation.Id]       = "OpId xx";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Operation.Name]     = "OpName xx";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.User.UserAgent]     = "UA xx";
                    aggregate.Dimensions[MetricDimensionNames.TelemetryContext.Cloud.RoleName]     = "RN xx";

                    await pipelineAdapter.TrackAsync(aggregate, CancellationToken.None);

                    Assert.AreEqual(1, telemetrySentToChannel.Count);
                    Assert.IsInstanceOfType(telemetrySentToChannel[0], typeof(MetricTelemetry));
                    MetricTelemetry metricTelemetry = (MetricTelemetry)telemetrySentToChannel[0];

                    // This is super strange. Count is changed from 0 to 1 in MetricTelemetry.Sanitize(). But it seems to happen only in Debug mode!
                    // This needs to be investigated! (@ToDo)
                    // It would indicate that we are sending different telemetry from exactly the same code depending on whether the app
                    // runs under a debugger. That wouldn't be good. (Noticed with SDK 2.3)
                    int expectedCount = Debugger.IsAttached ? 1 : -4;
                    Util.ValidateNumericAggregateValues(
                        metricTelemetry,
                        "mid-foobar",
                        expectedCount,
                        sum:        0,
                        max:        ((double)Int32.MaxValue) + 100,
                        min:        -10000000000,
                        stdDev:     -2,
                        timestamp:  new DateTimeOffset(2017, 10, 30, 0, 1, 0, TimeSpan.FromHours(8)),
                        periodMs:   "90000");

                    string props = $"metricTelemetry.Properties[{metricTelemetry.Properties.Count}] {{ ";
                    foreach (KeyValuePair <string, string> kvp in metricTelemetry.Properties)
                    {
                        props = props + $"[\"{kvp.Key}\"]=\"{kvp.Value}\", ";
                    }
                    props = props + " }";

                    // This is another super strange case where we seem to be gettin gdifferent results depending on whether a dubugger is attached.
                    // It seems to be the same Sanitization issue as above (@ToDo)
                    if (Debugger.IsAttached)
                    {
                        Assert.AreEqual(6, metricTelemetry.Properties.Count, props);
                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 1"));
                        Assert.AreEqual("DV1", metricTelemetry.Properties["Dim 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 2"));
                        Assert.AreEqual("DV2a", metricTelemetry.Properties["Dim 2"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 3"));
                        Assert.AreEqual("DV3", metricTelemetry.Properties["Dim 3"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Prop 1"));
                        Assert.AreEqual("PV1", metricTelemetry.Properties["Prop 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Prop 2"));
                        Assert.AreEqual("PV2", metricTelemetry.Properties["Prop 2"]);
                    }
                    else
                    {
                        Assert.AreEqual(8, metricTelemetry.Properties.Count, props);
                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 1"));
                        Assert.AreEqual("DV1", metricTelemetry.Properties["Dim 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 2"));
                        Assert.AreEqual("DV2a", metricTelemetry.Properties["Dim 2"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 3"));
                        Assert.AreEqual("DV3", metricTelemetry.Properties["Dim 3"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 4"));
                        Assert.AreEqual("", metricTelemetry.Properties["Dim 4"]);

                        Assert.IsFalse(metricTelemetry.Properties.ContainsKey("Dim 5"));

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Dim 6"));
                        Assert.AreEqual("  ", metricTelemetry.Properties["Dim 6"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Prop 1"));
                        Assert.AreEqual("PV1", metricTelemetry.Properties["Prop 1"]);

                        Assert.IsTrue(metricTelemetry.Properties.ContainsKey("Prop 2"));
                        Assert.AreEqual("PV2", metricTelemetry.Properties["Prop 2"]);
                    }

                    Assert.AreEqual("OpId xx", metricTelemetry.Context.Operation.Id);
                    Assert.AreEqual("OpName xx", metricTelemetry.Context.Operation.Name);
                    Assert.AreEqual("UA xx", metricTelemetry.Context.User.UserAgent);
                    Assert.AreEqual("RN xx", metricTelemetry.Context.Cloud.RoleName);

                    Assert.AreEqual("Aggregate's Instrumentsion Key", metricTelemetry.Context.InstrumentationKey);
                    Util.ValidateSdkVersionString(metricTelemetry.Context.GetInternalContext().SdkVersion);
                }
            }
        }
 protected override void PopulateDataValues(MetricTelemetry telemetryItem, MetricAggregate aggregate)
 {
     telemetryItem.Count             = 1;
     telemetryItem.Sum               = aggregate.GetDataValue <double>(MetricSeriesConfigurationForTestingAccumulatorBehavior.Constants.AggregateKindDataKeys.Sum, 0.0);
     telemetryItem.Min               = aggregate.GetDataValue <double>(MetricSeriesConfigurationForTestingAccumulatorBehavior.Constants.AggregateKindDataKeys.Min, 0.0);
     telemetryItem.Max               = aggregate.GetDataValue <double>(MetricSeriesConfigurationForTestingAccumulatorBehavior.Constants.AggregateKindDataKeys.Max, 0.0);
     telemetryItem.StandardDeviation = null;
 }
Exemple #9
0
        public void PersistentAggregates()
        {
            {
                MetricAggregate[] p = new MetricAggregate[0];
                var period          = new AggregationPeriodSummary(p, null);

                Assert.IsNull(period.NonpersistentAggregates);

                Assert.IsNotNull(period.PersistentAggregates);
                Assert.AreSame(p, period.PersistentAggregates);
                Assert.AreEqual(0, period.PersistentAggregates.Count);
            }
            {
                MetricAggregate[] p = new MetricAggregate[] { new MetricAggregate("mns1", "mid1", "KindA"),
                                                              new MetricAggregate("mns2", "mid2", "KindB"),
                                                              new MetricAggregate("mns3", "mid3", "KindC") };
                var period = new AggregationPeriodSummary(p, null);

                Assert.IsNull(period.NonpersistentAggregates);

                Assert.IsNotNull(period.PersistentAggregates);
                Assert.AreSame(p, period.PersistentAggregates);
                Assert.AreEqual(3, period.PersistentAggregates.Count);

                Assert.AreEqual("mns1", period.PersistentAggregates[0].MetricNamespace);
                Assert.AreEqual("mid1", period.PersistentAggregates[0].MetricId);
                Assert.AreEqual("KindA", period.PersistentAggregates[0].AggregationKindMoniker);

                Assert.AreEqual("mns2", period.PersistentAggregates[1].MetricNamespace);
                Assert.AreEqual("mid2", period.PersistentAggregates[1].MetricId);
                Assert.AreEqual("KindB", period.PersistentAggregates[1].AggregationKindMoniker);

                Assert.AreEqual("mns3", period.PersistentAggregates[2].MetricNamespace);
                Assert.AreEqual("mid3", period.PersistentAggregates[2].MetricId);
                Assert.AreEqual("KindC", period.PersistentAggregates[2].AggregationKindMoniker);
            }
            {
                MetricAggregate[] np = new MetricAggregate[] { new MetricAggregate("MNS1", "mid1", "KindA"),
                                                               new MetricAggregate("MNS2", "mid2", "KindB"),
                                                               new MetricAggregate("MNS3", "mid3", "KindC") };
                var period = new AggregationPeriodSummary(null, np);

                Assert.IsNull(period.PersistentAggregates);

                Assert.IsNotNull(period.NonpersistentAggregates);
                Assert.AreSame(np, period.NonpersistentAggregates);
                Assert.AreEqual(3, period.NonpersistentAggregates.Count);

                Assert.AreEqual("MNS1", period.NonpersistentAggregates[0].MetricNamespace);
                Assert.AreEqual("mid1", period.NonpersistentAggregates[0].MetricId);
                Assert.AreEqual("KindA", period.NonpersistentAggregates[0].AggregationKindMoniker);

                Assert.AreEqual("MNS2", period.NonpersistentAggregates[1].MetricNamespace);
                Assert.AreEqual("mid2", period.NonpersistentAggregates[1].MetricId);
                Assert.AreEqual("KindB", period.NonpersistentAggregates[1].AggregationKindMoniker);

                Assert.AreEqual("MNS3", period.NonpersistentAggregates[2].MetricNamespace);
                Assert.AreEqual("mid3", period.NonpersistentAggregates[2].MetricId);
                Assert.AreEqual("KindC", period.NonpersistentAggregates[2].AggregationKindMoniker);
            }
        }