From 3ff314b411a60e5cca10991ea26b80593b8c0db8 Mon Sep 17 00:00:00 2001 From: David Duffy Date: Wed, 27 Apr 2016 19:07:05 -0700 Subject: [PATCH] Switched to using ConcurrentDictionary, deleted SnapshottingDictionary, and fixed unit tests. --- .../RichPayloadEventSourceTest.cs | 267 +++++---------- .../Shared/Core.Shared.Tests.projitems | 1 - .../DataContracts/EventTelemetryTest.cs | 15 +- .../DataContracts/ExceptionTelemetryTest.cs | 5 +- .../DataContracts/PageViewTelemetryTest.cs | 16 +- .../DataContracts/RequestTelemetryTest.cs | 16 +- .../DataContracts/TelemetryContextTest.cs | 3 +- .../SnapshottingDictionaryTest.cs | 307 ------------------ .../DataContracts/DependencyTelemetry.cs | 3 +- .../Shared/DataContracts/EventTelemetry.cs | 2 +- .../DataContracts/ExceptionTelemetry.cs | 2 +- .../Shared/DataContracts/MetricTelemetry.cs | 2 +- .../Shared/DataContracts/PageViewTelemetry.cs | 2 +- .../PerformanceCounterTelemetry.cs | 2 +- .../Shared/DataContracts/RequestTelemetry.cs | 3 +- .../DataContracts/SessionStateTelemetry.cs | 4 +- .../Shared/DataContracts/TelemetryContext.cs | 8 +- .../Shared/DataContracts/TraceTelemetry.cs | 3 +- .../External/AppInsightsTypes.g.cs | 25 +- .../External/PerformanceCounterData.g.cs | 15 +- .../Implementation/SnapshottingDictionary.cs | 81 ----- src/Core/Managed/Shared/Shared.projitems | 1 - 22 files changed, 149 insertions(+), 634 deletions(-) delete mode 100644 Test/CoreSDK.Test/Shared/Extensibility/Implementation/SnapshottingDictionaryTest.cs delete mode 100644 src/Core/Managed/Shared/Extensibility/Implementation/SnapshottingDictionary.cs diff --git a/Test/CoreSDK.Test/Net46/Extensibility/Implementation/RichPayloadEventSourceTest.cs b/Test/CoreSDK.Test/Net46/Extensibility/Implementation/RichPayloadEventSourceTest.cs index c939811812..1e07715adc 100644 --- a/Test/CoreSDK.Test/Net46/Extensibility/Implementation/RichPayloadEventSourceTest.cs +++ b/Test/CoreSDK.Test/Net46/Extensibility/Implementation/RichPayloadEventSourceTest.cs @@ -4,241 +4,150 @@ using System.Collections.Generic; using System.Diagnostics.Tracing; using System.Linq; - + using Channel; using Microsoft.ApplicationInsights.DataContracts; using Microsoft.VisualStudio.TestTools.UnitTesting; + /// + /// Tests the rich payload event source tracking. + /// [TestClass] - public class RichPayloadEventSourceTest { + /// + /// Tests tracking request telemetry. + /// [TestMethod] public void RichPayloadEventSourceRequestSentTest() { - var client = new TelemetryClient(); - client.InstrumentationKey = Guid.NewGuid().ToString(); - - using (var listener = new Microsoft.ApplicationInsights.TestFramework.TestEventListener()) - { - listener.EnableEvents(RichPayloadEventSource.Log.EventSourceInternal, EventLevel.Verbose, RichPayloadEventSource.Keywords.Requests); - - var item = new RequestTelemetry("TestRequest", DateTimeOffset.Now, TimeSpan.FromMilliseconds(10), "200", true); - item.Context.Properties.Add("property1", "value1"); - item.Context.User.Id = "testUserId"; - item.Context.Operation.Id = Guid.NewGuid().ToString(); - - client.TrackRequest(item); - - var actualEvent = listener.Messages.FirstOrDefault(); - - Assert.IsNotNull(actualEvent); - Assert.AreEqual(client.InstrumentationKey, actualEvent.Payload[0]); - - object[] tags = actualEvent.Payload[1] as object[]; - Assert.AreEqual("ai.user.id", ((Dictionary)(tags[0]))["Key"]); - Assert.AreEqual("testUserId", ((Dictionary)(tags[0]))["Value"]); - - Assert.AreEqual("ai.operation.id", ((Dictionary)(tags[1]))["Key"]); - Assert.AreEqual(item.Context.Operation.Id, ((Dictionary)(tags[1]))["Value"]); - - Assert.IsNotNull(actualEvent.Payload[2]); - } + this.DoTracking( + RichPayloadEventSource.Keywords.Requests, + new RequestTelemetry("TestRequest", DateTimeOffset.Now, TimeSpan.FromMilliseconds(10), "200", true), + (client, item) => { client.TrackRequest((RequestTelemetry)item); }); } + /// + /// Tests tracking trace telemetry. + /// [TestMethod] public void RichPayloadEventSourceTraceSentTest() { - var client = new TelemetryClient(); - client.InstrumentationKey = Guid.NewGuid().ToString(); - - using (var listener = new Microsoft.ApplicationInsights.TestFramework.TestEventListener()) - { - listener.EnableEvents(RichPayloadEventSource.Log.EventSourceInternal, EventLevel.Verbose, RichPayloadEventSource.Keywords.Traces); - - var item = new TraceTelemetry("TestTrace", SeverityLevel.Information); - item.Context.Properties.Add("property1", "value1"); - item.Context.User.Id = "testUserId"; - item.Context.Operation.Id = Guid.NewGuid().ToString(); - - client.TrackTrace(item); - - var actualEvent = listener.Messages.FirstOrDefault(); - - Assert.IsNotNull(actualEvent); - Assert.AreEqual(client.InstrumentationKey, actualEvent.Payload[0]); - - object[] tags = actualEvent.Payload[1] as object[]; - Assert.AreEqual("ai.user.id", ((Dictionary)(tags[0]))["Key"]); - Assert.AreEqual("testUserId", ((Dictionary)(tags[0]))["Value"]); - - Assert.AreEqual("ai.operation.id", ((Dictionary)(tags[1]))["Key"]); - Assert.AreEqual(item.Context.Operation.Id, ((Dictionary)(tags[1]))["Value"]); - - Assert.IsNotNull(actualEvent.Payload[2]); - } + this.DoTracking( + RichPayloadEventSource.Keywords.Traces, + new TraceTelemetry("TestTrace", SeverityLevel.Information), + (client, item) => { client.TrackTrace((TraceTelemetry)item); }); } + /// + /// Tests tracking event telemetry. + /// [TestMethod] public void RichPayloadEventSourceEventSentTest() { - var client = new TelemetryClient(); - client.InstrumentationKey = Guid.NewGuid().ToString(); - - using (var listener = new Microsoft.ApplicationInsights.TestFramework.TestEventListener()) - { - listener.EnableEvents(RichPayloadEventSource.Log.EventSourceInternal, EventLevel.Verbose, RichPayloadEventSource.Keywords.Events); - - var item = new EventTelemetry("TestEvent"); - item.Context.Properties.Add("property1", "value1"); - item.Context.User.Id = "testUserId"; - item.Context.Operation.Id = Guid.NewGuid().ToString(); - - client.TrackEvent(item); - - var actualEvent = listener.Messages.FirstOrDefault(); - - Assert.IsNotNull(actualEvent); - Assert.AreEqual(client.InstrumentationKey, actualEvent.Payload[0]); - - object[] tags = actualEvent.Payload[1] as object[]; - Assert.AreEqual("ai.user.id", ((Dictionary)(tags[0]))["Key"]); - Assert.AreEqual("testUserId", ((Dictionary)(tags[0]))["Value"]); - - Assert.AreEqual("ai.operation.id", ((Dictionary)(tags[1]))["Key"]); - Assert.AreEqual(item.Context.Operation.Id, ((Dictionary)(tags[1]))["Value"]); - - Assert.IsNotNull(actualEvent.Payload[2]); - } + this.DoTracking( + RichPayloadEventSource.Keywords.Events, + new EventTelemetry("TestEvent"), + (client, item) => { client.TrackEvent((EventTelemetry)item); }); } + /// + /// Tests tracking exception telemetry. + /// [TestMethod] public void RichPayloadEventSourceExceptionSentTest() { - var client = new TelemetryClient(); - client.InstrumentationKey = Guid.NewGuid().ToString(); - - using (var listener = new Microsoft.ApplicationInsights.TestFramework.TestEventListener()) - { - listener.EnableEvents(RichPayloadEventSource.Log.EventSourceInternal, EventLevel.Verbose, RichPayloadEventSource.Keywords.Exceptions); - - var item = new ExceptionTelemetry(new SystemException("Test")); - item.Context.Properties.Add("property1", "value1"); - item.Context.User.Id = "testUserId"; - item.Context.Operation.Id = Guid.NewGuid().ToString(); - - client.TrackException(item); - - var actualEvent = listener.Messages.FirstOrDefault(); - - Assert.IsNotNull(actualEvent); - Assert.AreEqual(client.InstrumentationKey, actualEvent.Payload[0]); - - object[] tags = actualEvent.Payload[1] as object[]; - Assert.AreEqual("ai.user.id", ((Dictionary)(tags[0]))["Key"]); - Assert.AreEqual("testUserId", ((Dictionary)(tags[0]))["Value"]); - - Assert.AreEqual("ai.operation.id", ((Dictionary)(tags[1]))["Key"]); - Assert.AreEqual(item.Context.Operation.Id, ((Dictionary)(tags[1]))["Value"]); - - Assert.IsNotNull(actualEvent.Payload[2]); - } + this.DoTracking( + RichPayloadEventSource.Keywords.Exceptions, + new ExceptionTelemetry(new SystemException("Test")), + (client, item) => { client.TrackException((ExceptionTelemetry)item); }); } + /// + /// Tests tracking metric telemetry. + /// [TestMethod] public void RichPayloadEventSourceMetricSentTest() { - var client = new TelemetryClient(); - client.InstrumentationKey = Guid.NewGuid().ToString(); - - using (var listener = new Microsoft.ApplicationInsights.TestFramework.TestEventListener()) - { - listener.EnableEvents(RichPayloadEventSource.Log.EventSourceInternal, EventLevel.Verbose, RichPayloadEventSource.Keywords.Metrics); - - var item = new MetricTelemetry("TestMetric", 1); - item.Context.Properties.Add("property1", "value1"); - item.Context.User.Id = "testUserId"; - item.Context.Operation.Id = Guid.NewGuid().ToString(); - - client.TrackMetric(item); - - var actualEvent = listener.Messages.FirstOrDefault(); - - Assert.IsNotNull(actualEvent); - Assert.AreEqual(client.InstrumentationKey, actualEvent.Payload[0]); - - object[] tags = actualEvent.Payload[1] as object[]; - Assert.AreEqual("ai.user.id", ((Dictionary)(tags[0]))["Key"]); - Assert.AreEqual("testUserId", ((Dictionary)(tags[0]))["Value"]); - - Assert.AreEqual("ai.operation.id", ((Dictionary)(tags[1]))["Key"]); - Assert.AreEqual(item.Context.Operation.Id, ((Dictionary)(tags[1]))["Value"]); - - Assert.IsNotNull(actualEvent.Payload[2]); - } + this.DoTracking( + RichPayloadEventSource.Keywords.Metrics, + new MetricTelemetry("TestMetric", 1), + (client, item) => { client.TrackMetric((MetricTelemetry)item); }); } + /// + /// Tests tracking dependency telemetry. + /// [TestMethod] public void RichPayloadEventSourceDependencySentTest() { - var client = new TelemetryClient(); - client.InstrumentationKey = Guid.NewGuid().ToString(); - - using (var listener = new Microsoft.ApplicationInsights.TestFramework.TestEventListener()) - { - listener.EnableEvents(RichPayloadEventSource.Log.EventSourceInternal, EventLevel.Verbose, RichPayloadEventSource.Keywords.Dependencies); - - var item = new DependencyTelemetry("TestDependency", "TestCommand", DateTimeOffset.Now, TimeSpan.Zero, true); - item.Context.Properties.Add("property1", "value1"); - item.Context.User.Id = "testUserId"; - item.Context.Operation.Id = Guid.NewGuid().ToString(); - - client.TrackDependency(item); - - var actualEvent = listener.Messages.FirstOrDefault(); - - Assert.IsNotNull(actualEvent); - Assert.AreEqual(client.InstrumentationKey, actualEvent.Payload[0]); - - object[] tags = actualEvent.Payload[1] as object[]; - Assert.AreEqual("ai.user.id", ((Dictionary)(tags[0]))["Key"]); - Assert.AreEqual("testUserId", ((Dictionary)(tags[0]))["Value"]); - - Assert.AreEqual("ai.operation.id", ((Dictionary)(tags[1]))["Key"]); - Assert.AreEqual(item.Context.Operation.Id, ((Dictionary)(tags[1]))["Value"]); - - Assert.IsNotNull(actualEvent.Payload[2]); - } + this.DoTracking( + RichPayloadEventSource.Keywords.Dependencies, + new DependencyTelemetry("TestDependency", "TestCommand", DateTimeOffset.Now, TimeSpan.Zero, true), + (client, item) => { client.TrackDependency((DependencyTelemetry)item); }); } + /// + /// Tests tracking page view telemetry. + /// [TestMethod] public void RichPayloadEventSourcePageViewSentTest() + { + this.DoTracking( + RichPayloadEventSource.Keywords.PageViews, + new PageViewTelemetry("TestPage"), + (client, item) => { client.TrackPageView((PageViewTelemetry)item); }); + } + + /// + /// Helper method to setup shared context and call the desired tracking for testing. + /// + /// The event keywords to enable. + /// The telemetry item to track. + /// The tracking callback to execute. + private void DoTracking(EventKeywords keywords, ITelemetry item, Action track) { var client = new TelemetryClient(); client.InstrumentationKey = Guid.NewGuid().ToString(); using (var listener = new Microsoft.ApplicationInsights.TestFramework.TestEventListener()) { - listener.EnableEvents(RichPayloadEventSource.Log.EventSourceInternal, EventLevel.Verbose, RichPayloadEventSource.Keywords.PageViews); + listener.EnableEvents(RichPayloadEventSource.Log.EventSourceInternal, EventLevel.Verbose, keywords); - var item = new PageViewTelemetry("TestPage"); item.Context.Properties.Add("property1", "value1"); item.Context.User.Id = "testUserId"; item.Context.Operation.Id = Guid.NewGuid().ToString(); - client.TrackPageView(item); + track(client, item); var actualEvent = listener.Messages.FirstOrDefault(); Assert.IsNotNull(actualEvent); Assert.AreEqual(client.InstrumentationKey, actualEvent.Payload[0]); + int keysFound = 0; object[] tags = actualEvent.Payload[1] as object[]; - Assert.AreEqual("ai.user.id", ((Dictionary)(tags[0]))["Key"]); - Assert.AreEqual("testUserId", ((Dictionary)(tags[0]))["Value"]); - - Assert.AreEqual("ai.operation.id", ((Dictionary)(tags[1]))["Key"]); - Assert.AreEqual(item.Context.Operation.Id, ((Dictionary)(tags[1]))["Value"]); - + foreach (object tagObject in tags) + { + Dictionary tag = (Dictionary)tagObject; + Assert.IsNotNull(tag); + string key = (string)tag["Key"]; + object value = tag["Value"]; + if (!string.IsNullOrWhiteSpace(key)) + { + if (key == "ai.user.id") + { + Assert.AreEqual("testUserId", value); + ++keysFound; + } + else if (key == "ai.operation.id") + { + Assert.AreEqual(item.Context.Operation.Id, value); + ++keysFound; + } + } + } + + Assert.AreEqual(2, keysFound); Assert.IsNotNull(actualEvent.Payload[2]); } } diff --git a/Test/CoreSDK.Test/Shared/Core.Shared.Tests.projitems b/Test/CoreSDK.Test/Shared/Core.Shared.Tests.projitems index a62c1eea17..b34d7dfaea 100644 --- a/Test/CoreSDK.Test/Shared/Core.Shared.Tests.projitems +++ b/Test/CoreSDK.Test/Shared/Core.Shared.Tests.projitems @@ -45,7 +45,6 @@ - diff --git a/Test/CoreSDK.Test/Shared/DataContracts/EventTelemetryTest.cs b/Test/CoreSDK.Test/Shared/DataContracts/EventTelemetryTest.cs index 660c572040..155e813061 100644 --- a/Test/CoreSDK.Test/Shared/DataContracts/EventTelemetryTest.cs +++ b/Test/CoreSDK.Test/Shared/DataContracts/EventTelemetryTest.cs @@ -97,14 +97,17 @@ public void SanitizeWillTrimAppropriateFields() Assert.Equal(new string('Z', Property.MaxEventNameLength), telemetry.Name); Assert.Equal(2, telemetry.Properties.Count); - Assert.Equal(new string('X', Property.MaxDictionaryNameLength), telemetry.Properties.Keys.ToArray()[0]); - Assert.Equal(new string('X', Property.MaxValueLength), telemetry.Properties.Values.ToArray()[0]); - Assert.Equal(new string('X', Property.MaxDictionaryNameLength - 3) + "001", telemetry.Properties.Keys.ToArray()[1]); - Assert.Equal(new string('X', Property.MaxValueLength), telemetry.Properties.Values.ToArray()[1]); + string[] keys = telemetry.Properties.Keys.OrderBy(s => s).ToArray(); + string[] values = telemetry.Properties.Values.OrderBy(s => s).ToArray(); + Assert.Equal(new string('X', Property.MaxDictionaryNameLength), keys[1]); + Assert.Equal(new string('X', Property.MaxValueLength), values[1]); + Assert.Equal(new string('X', Property.MaxDictionaryNameLength - 3) + "001", keys[0]); + Assert.Equal(new string('X', Property.MaxValueLength), values[0]); Assert.Equal(2, telemetry.Metrics.Count); - Assert.Equal(new string('Y', Property.MaxDictionaryNameLength), telemetry.Metrics.Keys.ToArray()[0]); - Assert.Equal(new string('Y', Property.MaxDictionaryNameLength - 3) + "001", telemetry.Metrics.Keys.ToArray()[1]); + keys = telemetry.Metrics.Keys.OrderBy(s => s).ToArray(); + Assert.Equal(new string('Y', Property.MaxDictionaryNameLength), keys[1]); + Assert.Equal(new string('Y', Property.MaxDictionaryNameLength - 3) + "001", keys[0]); } [TestMethod] diff --git a/Test/CoreSDK.Test/Shared/DataContracts/ExceptionTelemetryTest.cs b/Test/CoreSDK.Test/Shared/DataContracts/ExceptionTelemetryTest.cs index 629a87dc5a..aeacd6da34 100644 --- a/Test/CoreSDK.Test/Shared/DataContracts/ExceptionTelemetryTest.cs +++ b/Test/CoreSDK.Test/Shared/DataContracts/ExceptionTelemetryTest.cs @@ -403,8 +403,9 @@ public void SanitizeWillTrimMetricsNameAndValueInExceptionTelemetry() ((ITelemetry)telemetry).Sanitize(); Assert.Equal(2, telemetry.Metrics.Count); - Assert.Equal(new string('Y', Property.MaxDictionaryNameLength), telemetry.Metrics.Keys.ToArray()[0]); - Assert.Equal(new string('Y', Property.MaxDictionaryNameLength - 3) + "001", telemetry.Metrics.Keys.ToArray()[1]); + string[] keys = telemetry.Metrics.Keys.OrderBy(s => s).ToArray(); + Assert.Equal(new string('Y', Property.MaxDictionaryNameLength), keys[1]); + Assert.Equal(new string('Y', Property.MaxDictionaryNameLength - 3) + "001", keys[0]); } [TestMethod] diff --git a/Test/CoreSDK.Test/Shared/DataContracts/PageViewTelemetryTest.cs b/Test/CoreSDK.Test/Shared/DataContracts/PageViewTelemetryTest.cs index ad0652b3c5..c1fbaeb681 100644 --- a/Test/CoreSDK.Test/Shared/DataContracts/PageViewTelemetryTest.cs +++ b/Test/CoreSDK.Test/Shared/DataContracts/PageViewTelemetryTest.cs @@ -70,7 +70,6 @@ public void PageViewTelemetrySerializesToJsonCorrectly() Assert.Equal(expected.Name, item.Data.BaseData.Name); Assert.Equal(expected.Duration, item.Data.BaseData.Duration); Assert.Equal(expected.Url.ToString(), item.Data.BaseData.Url); - Assert.Equal(expected.Metrics, item.Data.BaseData.Measurements); Assert.Equal(expected.Properties.ToArray(), item.Data.BaseData.Properties.ToArray()); } @@ -91,14 +90,17 @@ public void SanitizeWillTrimAppropriateFields() Assert.Equal(new string('Z', Property.MaxNameLength), telemetry.Name); Assert.Equal(2, telemetry.Properties.Count); - Assert.Equal(new string('X', Property.MaxDictionaryNameLength), telemetry.Properties.Keys.ToArray()[0]); - Assert.Equal(new string('X', Property.MaxValueLength), telemetry.Properties.Values.ToArray()[0]); - Assert.Equal(new string('X', Property.MaxDictionaryNameLength - 3) + "001", telemetry.Properties.Keys.ToArray()[1]); - Assert.Equal(new string('X', Property.MaxValueLength), telemetry.Properties.Values.ToArray()[1]); + string[] keys = telemetry.Properties.Keys.OrderBy(s => s).ToArray(); + string[] values = telemetry.Properties.Values.OrderBy(s => s).ToArray(); + Assert.Equal(new string('X', Property.MaxDictionaryNameLength), keys[1]); + Assert.Equal(new string('X', Property.MaxValueLength), values[1]); + Assert.Equal(new string('X', Property.MaxDictionaryNameLength - 3) + "001", keys[0]); + Assert.Equal(new string('X', Property.MaxValueLength), values[0]); Assert.Equal(2, telemetry.Metrics.Count); - Assert.Equal(new string('Y', Property.MaxDictionaryNameLength), telemetry.Metrics.Keys.ToArray()[0]); - Assert.Equal(new string('Y', Property.MaxDictionaryNameLength - 3) + "001", telemetry.Metrics.Keys.ToArray()[1]); + keys = telemetry.Metrics.Keys.OrderBy(s => s).ToArray(); + Assert.Equal(new string('Y', Property.MaxDictionaryNameLength), keys[1]); + Assert.Equal(new string('Y', Property.MaxDictionaryNameLength - 3) + "001", keys[0]); Assert.Equal(new Uri("http://foo.com/" + new string('Y', Property.MaxUrlLength - 15)), telemetry.Url); } diff --git a/Test/CoreSDK.Test/Shared/DataContracts/RequestTelemetryTest.cs b/Test/CoreSDK.Test/Shared/DataContracts/RequestTelemetryTest.cs index 10496c0f33..cf5346d9d3 100644 --- a/Test/CoreSDK.Test/Shared/DataContracts/RequestTelemetryTest.cs +++ b/Test/CoreSDK.Test/Shared/DataContracts/RequestTelemetryTest.cs @@ -113,7 +113,6 @@ public void RequestTelemetrySerializesToJson() Assert.Equal(expected.HttpMethod, item.Data.BaseData.HttpMethod); Assert.Equal(1, item.Data.BaseData.Measurements.Count); - Assert.Equal(expected.Metrics, item.Data.BaseData.Measurements); Assert.Equal(expected.Properties.ToArray(), item.Data.BaseData.Properties.ToArray()); } @@ -153,14 +152,17 @@ public void SanitizeWillTrimAppropriateFields() Assert.Equal(new string('Z', Property.MaxNameLength), telemetry.Name); Assert.Equal(2, telemetry.Properties.Count); - Assert.Equal(new string('X', Property.MaxDictionaryNameLength), telemetry.Properties.Keys.ToArray()[0]); - Assert.Equal(new string('X', Property.MaxValueLength), telemetry.Properties.Values.ToArray()[0]); - Assert.Equal(new string('X', Property.MaxDictionaryNameLength - 3) + "001", telemetry.Properties.Keys.ToArray()[1]); - Assert.Equal(new string('X', Property.MaxValueLength), telemetry.Properties.Values.ToArray()[1]); + string[] keys = telemetry.Properties.Keys.OrderBy(s => s).ToArray(); + string[] values = telemetry.Properties.Values.OrderBy(s => s).ToArray(); + Assert.Equal(new string('X', Property.MaxDictionaryNameLength), keys[1]); + Assert.Equal(new string('X', Property.MaxValueLength), values[1]); + Assert.Equal(new string('X', Property.MaxDictionaryNameLength - 3) + "001", keys[0]); + Assert.Equal(new string('X', Property.MaxValueLength), values[0]); Assert.Equal(2, telemetry.Metrics.Count); - Assert.Equal(new string('Y', Property.MaxDictionaryNameLength), telemetry.Metrics.Keys.ToArray()[0]); - Assert.Equal(new string('Y', Property.MaxDictionaryNameLength - 3) + "001", telemetry.Metrics.Keys.ToArray()[1]); + keys = telemetry.Metrics.Keys.OrderBy(s => s).ToArray(); + Assert.Equal(new string('Y', Property.MaxDictionaryNameLength), keys[1]); + Assert.Equal(new string('Y', Property.MaxDictionaryNameLength - 3) + "001", keys[0]); Assert.Equal(new Uri("http://foo.com/" + new string('Y', Property.MaxUrlLength - 15)), telemetry.Url); diff --git a/Test/CoreSDK.Test/Shared/DataContracts/TelemetryContextTest.cs b/Test/CoreSDK.Test/Shared/DataContracts/TelemetryContextTest.cs index 5d75606e46..cf811b59b9 100644 --- a/Test/CoreSDK.Test/Shared/DataContracts/TelemetryContextTest.cs +++ b/Test/CoreSDK.Test/Shared/DataContracts/TelemetryContextTest.cs @@ -1,6 +1,7 @@ namespace Microsoft.ApplicationInsights.DataContracts { using System; + using System.Collections.Concurrent; using System.Globalization; using System.IO; using System.Reflection; @@ -28,7 +29,7 @@ public void TelemetryContextIsSealedToSupportCompilationAsWinmd() public void ConstructorInitializesTagsWithThreadSafeDictionaryObjects() { var context = new TelemetryContext(); - Assert.IsType>(context.Tags); + Assert.IsType>(context.Tags); } [TestMethod] diff --git a/Test/CoreSDK.Test/Shared/Extensibility/Implementation/SnapshottingDictionaryTest.cs b/Test/CoreSDK.Test/Shared/Extensibility/Implementation/SnapshottingDictionaryTest.cs deleted file mode 100644 index 44295fc297..0000000000 --- a/Test/CoreSDK.Test/Shared/Extensibility/Implementation/SnapshottingDictionaryTest.cs +++ /dev/null @@ -1,307 +0,0 @@ -// -// Copyright © Microsoft. All Rights Reserved. -// - -namespace Microsoft.ApplicationInsights.Extensibility.Implementation -{ - using System.Collections.Generic; - using System.Reflection; - using System.Threading.Tasks; - -#if NET40 || NET45 || NET46 - using Microsoft.VisualStudio.TestTools.UnitTesting; -#else - using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; -#endif - using Assert = Xunit.Assert; - - [TestClass] - public class SnapshottingDictionaryTest - { - [TestClass] - public class Class : SnapshottingDictionaryTest - { - [TestMethod] - public void IsInternalAndNotMeantForPublicConsumption() - { - Assert.False(typeof(SnapshottingDictionary<,>).GetTypeInfo().IsPublic); - } - - [TestMethod] - public void ImplementIDictionaryInterfaceForCompatibilityWithPublicApis() - { - Assert.True(typeof(IDictionary).IsAssignableFrom(typeof(SnapshottingDictionary))); - } - } - - [TestClass] - public class Constructor : SnapshottingDictionaryTest - { - [TestMethod] - public void CreatesNewDictionary() - { - var target = new TestableSnapshottingDictionary(); - Assert.NotNull(target.Collection); - } - } - - [TestClass] - public class CreateSnapshot : SnapshottingDictionaryTest - { - [TestMethod] - public void CreatesClonesGivenDictionary() - { - var target = new TestableSnapshottingDictionary(); - - var key = new object(); - var value = new object(); - var input = new Dictionary { { key, value } }; - IDictionary output = target.CreateSnapshot(input); - - Assert.Same(value, output[key]); - } - } - - [TestClass] - public class Add : SnapshottingDictionaryTest - { - [TestMethod] - public void AddsItemWithGivenKeyInDictionary() - { - var target = new TestableSnapshottingDictionary(); - - var key = new object(); - var value = new object(); - target.Add(key, value); - - Assert.Same(value, target.Collection[key]); - } - - [TestMethod] - public void ResetsSnapshotSoThatItIsRecreatedAtNextRead() - { - var target = new TestableSnapshottingDictionary(); - target.GetSnapshot(); - - target.Add(new object(), new object()); - - Assert.Null(target.Snapshot); - } - - [TestMethod] - public void LocksCollectionForThreadSafety() - { - Task anotherThread; - var target = new TestableSnapshottingDictionary(); - lock (target.Collection) - { - anotherThread = TaskEx.Run(() => target.Add(new object(), new object())); - Assert.False(anotherThread.Wait(20)); - } - - Assert.True(anotherThread.Wait(20)); - } - } - - [TestClass] - public class ContainsKey : SnapshottingDictionaryTest - { - [TestMethod] - public void ReturnsTrueIfSnapshotContainsGivenKey() - { - var target = new TestableSnapshottingDictionary(); - var key = new object(); - target.Snapshot = new Dictionary { { key, null } }; - - Assert.True(target.ContainsKey(key)); - } - } - - [TestClass] - public class Remove : SnapshottingDictionaryTest - { - [TestMethod] - public void RemovesItemWithGivenKeyFromDictionary() - { - var key = new object(); - var target = new TestableSnapshottingDictionary { { key, null } }; - - target.Remove(key); - - Assert.Equal(0, target.Collection.Count); - } - - [TestMethod] - public void ReturnsTrueIfItemWasRemovedSuccessfully() - { - var key = new object(); - var target = new TestableSnapshottingDictionary { { key, null } }; - - Assert.True(target.Remove(key)); - } - - [TestMethod] - public void ResetsSnapshotSoThatItIsRecreatedAtNextRead() - { - var key = new object(); - var target = new TestableSnapshottingDictionary { { key, null } }; - target.GetSnapshot(); - - target.Remove(key); - - Assert.Null(target.Snapshot); - } - - [TestMethod] - public void DoesNotResetSnapshotWhenItemWithGivenKeyWasNotRemoved() - { - var target = new TestableSnapshottingDictionary(); - IDictionary oldSnapshot = target.GetSnapshot(); - - target.Remove(new object()); - - Assert.Same(oldSnapshot, target.Snapshot); - } - - [TestMethod] - public void LocksCollectionForThreadSafety() - { - Task anotherThread; - var key = new object(); - var target = new TestableSnapshottingDictionary { { key, null } }; - lock (target.Collection) - { - anotherThread = TaskEx.Run(() => target.Remove(key)); - Assert.False(anotherThread.Wait(20)); - } - - Assert.True(anotherThread.Wait(20)); - } - } - - [TestClass] - public class TryGetValue : SnapshottingDictionaryTest - { - [TestMethod] - public void ReturnsValueWithGivenKeyInSnapshot() - { - var target = new TestableSnapshottingDictionary(); - var key = new object(); - var value = new object(); - target.Snapshot = new Dictionary { { key, value } }; - - object returnedValue = null; - bool result = target.TryGetValue(key, out returnedValue); - - Assert.True(result); - Assert.Same(value, returnedValue); - } - } - - [TestClass] - public class Keys : SnapshottingDictionaryTest - { - [TestMethod] - public void ReturnsKeysOfSnapshot() - { - var target = new TestableSnapshottingDictionary(); - var key = new object(); - target.Snapshot = new Dictionary { { key, null } }; - - Assert.True(target.Keys.Contains(key)); - } - } - - [TestClass] - public class Values : SnapshottingDictionaryTest - { - [TestMethod] - public void ReturnsValuesOfSnapshot() - { - var target = new TestableSnapshottingDictionary(); - var value = new object(); - target.Snapshot = new Dictionary { { new object(), value } }; - - Assert.True(target.Values.Contains(value)); - } - } - - [TestClass] - public class Item : SnapshottingDictionaryTest - { - [TestMethod] - public void GetterReturnsValueWithGivenKeyInSnapshot() - { - var target = new TestableSnapshottingDictionary(); - var key = new object(); - var value = new object(); - target.Snapshot = new Dictionary { { key, value } }; - - Assert.Same(value, target[key]); - } - - [TestMethod] - public void SetterReplacesItemWithGivenKeyInDictionary() - { - var key = new object(); - var target = new TestableSnapshottingDictionary { { key, null } }; - - var value = new object(); - target[key] = value; - - Assert.Same(value, target.Collection[key]); - } - - [TestMethod] - public void SetterResetsSnapshotSoThatItIsRecreatedAtNextRead() - { - var key = new object(); - var target = new TestableSnapshottingDictionary { { key, null } }; - target.GetSnapshot(); - - target[key] = new object(); - - Assert.Null(target.Snapshot); - } - - [TestMethod] - public void SetterLocksCollectionForThreadSafety() - { - Task anotherThread; - var key = new object(); - var target = new TestableSnapshottingDictionary { { key, null } }; - lock (target.Collection) - { - anotherThread = TaskEx.Run(() => target[key] = new object()); - Assert.False(anotherThread.Wait(20)); - } - - Assert.True(anotherThread.Wait(20)); - } - } - - private class TestableSnapshottingDictionary : SnapshottingDictionary - { - public new IDictionary Collection - { - get { return base.Collection; } - } - - public IDictionary Snapshot - { - get { return this.snapshot; } - set { this.snapshot = value; } - } - - public new IDictionary CreateSnapshot(IDictionary collection) - { - return base.CreateSnapshot(collection); - } - - public new IDictionary GetSnapshot() - { - return base.GetSnapshot(); - } - } - } -} diff --git a/src/Core/Managed/Shared/DataContracts/DependencyTelemetry.cs b/src/Core/Managed/Shared/DataContracts/DependencyTelemetry.cs index 884d68d33b..1eac22bdd5 100644 --- a/src/Core/Managed/Shared/DataContracts/DependencyTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/DependencyTelemetry.cs @@ -3,7 +3,6 @@ namespace Microsoft.ApplicationInsights.DataContracts using System; using System.Collections.Generic; using System.ComponentModel; - using System.Linq; using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.Extensibility.Implementation; using Microsoft.ApplicationInsights.Extensibility.Implementation.External; @@ -30,7 +29,7 @@ public sealed class DependencyTelemetry : OperationTelemetry, ITelemetry, ISuppo public DependencyTelemetry() { this.Data = new RemoteDependencyData() { kind = DataPointType.Aggregation }; - this.context = new TelemetryContext(this.Data.properties, new Dictionary()); + this.context = new TelemetryContext(this.Data.properties); this.Data.dependencyKind = BondDependencyKind.Other; this.Id = Convert.ToBase64String(BitConverter.GetBytes(WeakConcurrentRandom.Instance.Next())); } diff --git a/src/Core/Managed/Shared/DataContracts/EventTelemetry.cs b/src/Core/Managed/Shared/DataContracts/EventTelemetry.cs index 1a1f8c92c1..f3d089ad3b 100644 --- a/src/Core/Managed/Shared/DataContracts/EventTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/EventTelemetry.cs @@ -26,7 +26,7 @@ public sealed class EventTelemetry : ITelemetry, ISupportProperties, ISupportSam public EventTelemetry() { this.Data = new EventData(); - this.context = new TelemetryContext(this.Data.properties, new Dictionary()); + this.context = new TelemetryContext(this.Data.properties); } /// diff --git a/src/Core/Managed/Shared/DataContracts/ExceptionTelemetry.cs b/src/Core/Managed/Shared/DataContracts/ExceptionTelemetry.cs index 256b08273d..4486aa94ba 100644 --- a/src/Core/Managed/Shared/DataContracts/ExceptionTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/ExceptionTelemetry.cs @@ -29,7 +29,7 @@ public sealed class ExceptionTelemetry : ITelemetry, ISupportProperties, ISuppor public ExceptionTelemetry() { this.Data = new ExceptionData(); - this.context = new TelemetryContext(this.Data.properties, new Dictionary()); + this.context = new TelemetryContext(this.Data.properties); this.HandledAt = default(ExceptionHandledAt); } diff --git a/src/Core/Managed/Shared/DataContracts/MetricTelemetry.cs b/src/Core/Managed/Shared/DataContracts/MetricTelemetry.cs index 0a5dff1f66..1bde21b021 100644 --- a/src/Core/Managed/Shared/DataContracts/MetricTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/MetricTelemetry.cs @@ -28,7 +28,7 @@ public MetricTelemetry() { this.Data = new MetricData(); this.Metric = new DataPoint(); - this.Context = new TelemetryContext(this.Data.properties, new Dictionary()); + this.Context = new TelemetryContext(this.Data.properties); // We always have a single 'metric'. this.Data.metrics.Add(this.Metric); diff --git a/src/Core/Managed/Shared/DataContracts/PageViewTelemetry.cs b/src/Core/Managed/Shared/DataContracts/PageViewTelemetry.cs index e80a4a40a6..f9b8aeab55 100644 --- a/src/Core/Managed/Shared/DataContracts/PageViewTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/PageViewTelemetry.cs @@ -33,7 +33,7 @@ public sealed class PageViewTelemetry : ITelemetry, ISupportProperties, ISupport public PageViewTelemetry() { this.Data = new PageViewData(); - this.context = new TelemetryContext(this.Data.properties, new Dictionary()); + this.context = new TelemetryContext(this.Data.properties); } /// diff --git a/src/Core/Managed/Shared/DataContracts/PerformanceCounterTelemetry.cs b/src/Core/Managed/Shared/DataContracts/PerformanceCounterTelemetry.cs index a9e31ce843..57d3f22fdf 100644 --- a/src/Core/Managed/Shared/DataContracts/PerformanceCounterTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/PerformanceCounterTelemetry.cs @@ -24,7 +24,7 @@ public sealed class PerformanceCounterTelemetry : ITelemetry, ISupportProperties public PerformanceCounterTelemetry() { this.Data = new PerformanceCounterData(); - this.context = new TelemetryContext(this.Data.properties, new Dictionary()); + this.context = new TelemetryContext(this.Data.properties); } /// diff --git a/src/Core/Managed/Shared/DataContracts/RequestTelemetry.cs b/src/Core/Managed/Shared/DataContracts/RequestTelemetry.cs index d26e4ccf1d..f1704b56de 100644 --- a/src/Core/Managed/Shared/DataContracts/RequestTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/RequestTelemetry.cs @@ -6,7 +6,6 @@ using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.Extensibility.Implementation; using Microsoft.ApplicationInsights.Extensibility.Implementation.External; - using Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing; /// /// Encapsulates information about a web request handled by the application. @@ -33,7 +32,7 @@ public sealed class RequestTelemetry : OperationTelemetry, ITelemetry, ISupportP public RequestTelemetry() { this.Data = new RequestData(); - this.context = new TelemetryContext(this.Data.properties, new Dictionary()); + this.context = new TelemetryContext(this.Data.properties); this.Id = Convert.ToBase64String(BitConverter.GetBytes(WeakConcurrentRandom.Instance.Next())); } diff --git a/src/Core/Managed/Shared/DataContracts/SessionStateTelemetry.cs b/src/Core/Managed/Shared/DataContracts/SessionStateTelemetry.cs index c2ef36402d..814332fd39 100644 --- a/src/Core/Managed/Shared/DataContracts/SessionStateTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/SessionStateTelemetry.cs @@ -1,9 +1,7 @@ namespace Microsoft.ApplicationInsights.DataContracts { using System; - using System.Collections.Generic; using Microsoft.ApplicationInsights.Channel; - using Microsoft.ApplicationInsights.Extensibility.Implementation; using Microsoft.ApplicationInsights.Extensibility.Implementation.External; /// @@ -22,7 +20,7 @@ public sealed class SessionStateTelemetry : ITelemetry public SessionStateTelemetry() { this.Data = new SessionStateData(); - this.context = new TelemetryContext(new Dictionary(), new Dictionary()); + this.context = new TelemetryContext(); } /// diff --git a/src/Core/Managed/Shared/DataContracts/TelemetryContext.cs b/src/Core/Managed/Shared/DataContracts/TelemetryContext.cs index 57f5d9680b..33150cbc80 100644 --- a/src/Core/Managed/Shared/DataContracts/TelemetryContext.cs +++ b/src/Core/Managed/Shared/DataContracts/TelemetryContext.cs @@ -1,5 +1,6 @@ namespace Microsoft.ApplicationInsights.DataContracts { + using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Threading; @@ -30,16 +31,15 @@ public sealed class TelemetryContext /// Initializes a new instance of the class. /// public TelemetryContext() - : this(new SnapshottingDictionary(), new SnapshottingDictionary()) + : this(new ConcurrentDictionary()) { } - internal TelemetryContext(IDictionary properties, IDictionary tags) + internal TelemetryContext(IDictionary properties) { Debug.Assert(properties != null, "properties"); - Debug.Assert(tags != null, "tags"); this.properties = properties; - this.tags = tags; + this.tags = new ConcurrentDictionary(); } /// diff --git a/src/Core/Managed/Shared/DataContracts/TraceTelemetry.cs b/src/Core/Managed/Shared/DataContracts/TraceTelemetry.cs index 8e9d45ee00..03fd996056 100644 --- a/src/Core/Managed/Shared/DataContracts/TraceTelemetry.cs +++ b/src/Core/Managed/Shared/DataContracts/TraceTelemetry.cs @@ -2,7 +2,6 @@ { using System; using System.Collections.Generic; - using System.Threading; using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.Extensibility.Implementation; using Microsoft.ApplicationInsights.Extensibility.Implementation.External; @@ -27,7 +26,7 @@ public sealed class TraceTelemetry : ITelemetry, ISupportProperties, ISupportSam public TraceTelemetry() { this.Data = new MessageData(); - this.context = new TelemetryContext(this.Data.properties, new Dictionary()); + this.context = new TelemetryContext(this.Data.properties); } /// diff --git a/src/Core/Managed/Shared/Extensibility/Implementation/External/AppInsightsTypes.g.cs b/src/Core/Managed/Shared/Extensibility/Implementation/External/AppInsightsTypes.g.cs index 7cec063c10..7ca4bf9f3c 100644 --- a/src/Core/Managed/Shared/Extensibility/Implementation/External/AppInsightsTypes.g.cs +++ b/src/Core/Managed/Shared/Extensibility/Implementation/External/AppInsightsTypes.g.cs @@ -22,9 +22,10 @@ namespace Microsoft.ApplicationInsights.Extensibility.Implementation.External { + using System.Collections.Concurrent; using System.Collections.Generic; - + [System.CodeDom.Compiler.GeneratedCode("gbc", "3.02")] internal enum DataPointType { @@ -90,7 +91,7 @@ protected MetricData(string fullName, string name) { ver = 2; metrics = new List(); - properties = new Dictionary(); + properties = new ConcurrentDictionary(); } } @@ -175,7 +176,7 @@ protected RemoteDependencyData(string fullName, string name) dependencySource = DependencySourceType.Undefined; commandName = string.Empty; dependencyTypeName = string.Empty; - properties = new Dictionary(); + properties = new ConcurrentDictionary(); } } @@ -233,8 +234,8 @@ protected RequestData(string fullName, string name) responseCode = string.Empty; httpMethod = string.Empty; url = string.Empty; - properties = new Dictionary(); - measurements = new Dictionary(); + properties = new ConcurrentDictionary(); + measurements = new ConcurrentDictionary(); } } @@ -347,8 +348,8 @@ protected ExceptionData(string fullName, string name) handledAt = string.Empty; exceptions = new List(); problemId = string.Empty; - properties = new Dictionary(); - measurements = new Dictionary(); + properties = new ConcurrentDictionary(); + measurements = new ConcurrentDictionary(); } } @@ -377,7 +378,7 @@ protected MessageData(string fullName, string name) { ver = 2; message = string.Empty; - properties = new Dictionary(); + properties = new ConcurrentDictionary(); } } @@ -406,8 +407,8 @@ protected EventData(string fullName, string name) { ver = 2; this.name = string.Empty; - properties = new Dictionary(); - measurements = new Dictionary(); + properties = new ConcurrentDictionary(); + measurements = new ConcurrentDictionary(); } } @@ -592,8 +593,8 @@ protected AvailabilityData(string fullName, string name) result = new TestResult(); runLocation = string.Empty; message = string.Empty; - properties = new Dictionary(); - measurements = new Dictionary(); + properties = new ConcurrentDictionary(); + measurements = new ConcurrentDictionary(); } } } // AI diff --git a/src/Core/Managed/Shared/Extensibility/Implementation/External/PerformanceCounterData.g.cs b/src/Core/Managed/Shared/Extensibility/Implementation/External/PerformanceCounterData.g.cs index ef1389d865..0b0ae0ee1b 100644 --- a/src/Core/Managed/Shared/Extensibility/Implementation/External/PerformanceCounterData.g.cs +++ b/src/Core/Managed/Shared/Extensibility/Implementation/External/PerformanceCounterData.g.cs @@ -22,9 +22,10 @@ namespace Microsoft.ApplicationInsights.Extensibility.Implementation.External { + using System.Collections.Concurrent; using System.Collections.Generic; - + [System.CodeDom.Compiler.GeneratedCode("gbc", "3.02")] internal partial class PerformanceCounterData { @@ -73,17 +74,7 @@ protected PerformanceCounterData(string fullName, string name) counterName = string.Empty; instanceName = string.Empty; kind = DataPointType.Aggregation; - properties = new Dictionary(); + properties = new ConcurrentDictionary(); } } } // AI - - - - - - - - - - diff --git a/src/Core/Managed/Shared/Extensibility/Implementation/SnapshottingDictionary.cs b/src/Core/Managed/Shared/Extensibility/Implementation/SnapshottingDictionary.cs deleted file mode 100644 index 33255b7b1e..0000000000 --- a/src/Core/Managed/Shared/Extensibility/Implementation/SnapshottingDictionary.cs +++ /dev/null @@ -1,81 +0,0 @@ -// -// Copyright © Microsoft. All Rights Reserved. -// - -namespace Microsoft.ApplicationInsights.Extensibility.Implementation -{ - using System.Collections.Generic; - - internal class SnapshottingDictionary : SnapshottingCollection, IDictionary>, IDictionary - { - public SnapshottingDictionary() - : base(new Dictionary()) - { - } - - public ICollection Keys - { - get { return this.GetSnapshot().Keys; } - } - - public ICollection Values - { - get { return this.GetSnapshot().Values; } - } - - public TValue this[TKey key] - { - get - { - return this.GetSnapshot()[key]; - } - - set - { - lock (this.Collection) - { - this.Collection[key] = value; - this.snapshot = null; - } - } - } - - public void Add(TKey key, TValue value) - { - lock (this.Collection) - { - this.Collection.Add(key, value); - this.snapshot = null; - } - } - - public bool ContainsKey(TKey key) - { - return this.GetSnapshot().ContainsKey(key); - } - - public bool Remove(TKey key) - { - lock (this.Collection) - { - bool removed = this.Collection.Remove(key); - if (removed) - { - this.snapshot = null; - } - - return removed; - } - } - - public bool TryGetValue(TKey key, out TValue value) - { - return this.GetSnapshot().TryGetValue(key, out value); - } - - protected sealed override IDictionary CreateSnapshot(IDictionary collection) - { - return new Dictionary(collection); - } - } -} diff --git a/src/Core/Managed/Shared/Shared.projitems b/src/Core/Managed/Shared/Shared.projitems index d63308f77d..08d14da5ce 100644 --- a/src/Core/Managed/Shared/Shared.projitems +++ b/src/Core/Managed/Shared/Shared.projitems @@ -73,7 +73,6 @@ -