diff --git a/Src/DependencyCollector/Net46.Tests/DependencyTrackingTelemetryModuleTestNet46.cs b/Src/DependencyCollector/Net46.Tests/DependencyTrackingTelemetryModuleTestNet46.cs
index 297950bc8..79747c6ce 100644
--- a/Src/DependencyCollector/Net46.Tests/DependencyTrackingTelemetryModuleTestNet46.cs
+++ b/Src/DependencyCollector/Net46.Tests/DependencyTrackingTelemetryModuleTestNet46.cs
@@ -2,6 +2,7 @@
{
using System;
using System.Diagnostics;
+ using System.IO;
using System.Net;
using Microsoft.ApplicationInsights.Channel;
@@ -54,9 +55,13 @@ public void TestDependencyCollectionNoParentActivity()
module.ProfileQueryEndpoint = FakeProfileApiEndpoint;
module.Initialize(config);
- var url = new Uri("http://bing.com");
+ var url = new Uri("https://www.bing.com/");
HttpWebRequest request = WebRequest.CreateHttp(url);
- request.GetResponse();
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ using (var reader = new StreamReader(response.GetResponseStream()))
+ {
+ reader.ReadToEnd();
+ }
Assert.IsNotNull(sentTelemetry);
var item = (DependencyTelemetry)sentTelemetry;
@@ -118,11 +123,16 @@ public void TestDependencyCollectionWithParentActivity()
module.ProfileQueryEndpoint = FakeProfileApiEndpoint;
module.Initialize(config);
- var url = new Uri("http://bing.com");
+ var url = new Uri("https://www.bing.com/");
HttpWebRequest request = WebRequest.CreateHttp(url);
var parent = new Activity("parent").AddBaggage("k", "v").SetParentId("|guid.").Start();
- request.GetResponse();
+ HttpWebResponse response = (HttpWebResponse)request.GetResponse();
+ using (var reader = new StreamReader(response.GetResponseStream()))
+ {
+ reader.ReadToEnd();
+ }
+
parent.Stop();
Assert.IsNotNull(sentTelemetry);
diff --git a/Src/DependencyCollector/Shared.Tests/DependencyCollector.Shared.Tests.projitems b/Src/DependencyCollector/Shared.Tests/DependencyCollector.Shared.Tests.projitems
index 0b1f15b7f..0d2c1ee01 100644
--- a/Src/DependencyCollector/Shared.Tests/DependencyCollector.Shared.Tests.projitems
+++ b/Src/DependencyCollector/Shared.Tests/DependencyCollector.Shared.Tests.projitems
@@ -13,6 +13,7 @@
+
diff --git a/Src/DependencyCollector/Shared.Tests/Implementation/DesktopDiagnosticSourceHttpProcessingTests.cs b/Src/DependencyCollector/Shared.Tests/Implementation/DesktopDiagnosticSourceHttpProcessingTests.cs
new file mode 100644
index 000000000..157a09052
--- /dev/null
+++ b/Src/DependencyCollector/Shared.Tests/Implementation/DesktopDiagnosticSourceHttpProcessingTests.cs
@@ -0,0 +1,306 @@
+#if NET45
+namespace Microsoft.ApplicationInsights.DependencyCollector.Implementation
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.Linq;
+ using System.Net;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Microsoft.ApplicationInsights.Channel;
+ using Microsoft.ApplicationInsights.Common;
+ using Microsoft.ApplicationInsights.DataContracts;
+ using Microsoft.ApplicationInsights.DependencyCollector.Implementation.Operation;
+ using Microsoft.ApplicationInsights.Extensibility;
+ using Microsoft.ApplicationInsights.Extensibility.Implementation;
+ using Microsoft.ApplicationInsights.TestFramework;
+ using Microsoft.ApplicationInsights.Web.TestFramework;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class DesktopDiagnosticSourceHttpProcessingTests
+ {
+ #region Fields
+ private const string RandomAppIdEndpoint = "http://app.id.endpoint"; // appIdEndpoint - this really won't be used for tests because of the app id provider override.
+ private const int TimeAccuracyMilliseconds = 50;
+ private Uri testUrl = new Uri("http://www.microsoft.com/");
+ private int sleepTimeMsecBetweenBeginAndEnd = 100;
+ private TelemetryConfiguration configuration;
+ private List sendItems;
+ private DesktopDiagnosticSourceHttpProcessing httpProcessingFramework;
+ #endregion //Fields
+
+ #region TestInitialize
+
+ [TestInitialize]
+ public void TestInitialize()
+ {
+ this.configuration = new TelemetryConfiguration();
+ this.sendItems = new List();
+ this.configuration.TelemetryChannel = new StubTelemetryChannel { OnSend = item => this.sendItems.Add(item) };
+ this.configuration.InstrumentationKey = Guid.NewGuid().ToString();
+ this.httpProcessingFramework = new DesktopDiagnosticSourceHttpProcessing(this.configuration, new ObjectInstanceBasedOperationHolder(), /*setCorrelationHeaders*/ true, new List(), RandomAppIdEndpoint);
+ var correlationIdLookupHelper = new CorrelationIdLookupHelper((string ikey) =>
+ {
+ // Pretend App Id is the same as Ikey
+ var tcs = new TaskCompletionSource();
+ tcs.SetResult(ikey);
+ return tcs.Task;
+ });
+ this.httpProcessingFramework.OverrideCorrelationIdLookupHelper(correlationIdLookupHelper);
+ }
+
+ [TestCleanup]
+ public void Cleanup()
+ {
+ }
+ #endregion //TestInitiliaze
+
+ ///
+ /// Validates that OnRequestSend and OnResponseReceive sends valid telemetry.
+ ///
+ [TestMethod]
+ public void RddTestHttpProcessingFrameworkUpdateTelemetryName()
+ {
+ var stopwatch = Stopwatch.StartNew();
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
+ this.httpProcessingFramework.OnRequestSend(request);
+ Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
+ Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
+ var response = TestUtils.GenerateHttpWebResponse(HttpStatusCode.OK);
+ stopwatch.Stop();
+ this.httpProcessingFramework.OnResponseReceive(request, response);
+
+ Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
+ ValidateTelemetryPacketForOnRequestSend(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, true, stopwatch.Elapsed.TotalMilliseconds, "200");
+ }
+
+ ///
+ /// Validates that even if multiple events have fired, as long as there is only
+ /// one HttpWebRequest, only one event should be written, during the first call
+ /// to OnResponseReceive.
+ ///
+ [TestMethod]
+ public void RddTestHttpProcessingFrameworkNoDuplication()
+ {
+ Stopwatch stopwatch = Stopwatch.StartNew();
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
+ var redirectResponse = TestUtils.GenerateHttpWebResponse(HttpStatusCode.Redirect);
+ var successResponse = TestUtils.GenerateHttpWebResponse(HttpStatusCode.OK);
+
+ this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnRequestSend(request);
+ Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
+ Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
+ this.httpProcessingFramework.OnResponseReceive(request, redirectResponse);
+ Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
+
+ this.httpProcessingFramework.OnResponseReceive(request, redirectResponse);
+ this.httpProcessingFramework.OnResponseReceive(request, successResponse);
+ stopwatch.Stop();
+
+ Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
+ ValidateTelemetryPacketForOnRequestSend(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, true, stopwatch.Elapsed.TotalMilliseconds, "302");
+ }
+
+ ///
+ /// Validates if DependencyTelemetry sent contains the cross component correlation ID.
+ ///
+ [TestMethod]
+ [Description("Validates if DependencyTelemetry sent contains the cross component correlation ID.")]
+ public void RddTestHttpProcessingFrameworkOnEndAddsAppIdToTargetField()
+ {
+ // Here is a sample App ID, since the test initialize method adds a random ikey and our mock getAppId method pretends that the appId for a given ikey is the same as the ikey.
+ // This will not match the current component's App ID. Hence represents an external component.
+ string appId = "0935FC42-FE1A-4C67-975C-0C9D5CBDEE8E";
+
+ var request = WebRequest.Create(this.testUrl);
+
+ Dictionary headers = new Dictionary
+ {
+ { RequestResponseHeaders.RequestContextHeader, this.GetCorrelationIdHeaderValue(appId) }
+ };
+
+ var response = TestUtils.GenerateHttpWebResponse(HttpStatusCode.OK, headers);
+
+ this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnResponseReceive(request, response);
+ Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
+ Assert.AreEqual(this.testUrl.Host + " | " + this.GetCorrelationIdValue(appId), ((DependencyTelemetry)this.sendItems[0]).Target);
+ }
+
+ ///
+ /// Ensures that the source request header is added when request is sent.
+ ///
+ [TestMethod]
+ [Description("Ensures that the source request header is added when request is sent.")]
+ public void RddTestHttpProcessingFrameworkOnBeginAddsSourceHeader()
+ {
+ var request = WebRequest.Create(this.testUrl);
+
+ Assert.IsNull(request.Headers[RequestResponseHeaders.RequestContextHeader]);
+
+ this.httpProcessingFramework.OnRequestSend(request);
+ Assert.IsNotNull(request.Headers.GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader, RequestResponseHeaders.RequestContextCorrelationSourceKey));
+ }
+
+ ///
+ /// Ensures that the parent id header is added when request is sent.
+ ///
+ [TestMethod]
+ public void RddTestHttpProcessingFrameworkOnBeginAddsParentIdHeader()
+ {
+ var request = WebRequest.Create(this.testUrl);
+
+ Assert.IsNull(request.Headers[RequestResponseHeaders.StandardParentIdHeader]);
+
+ var client = new TelemetryClient(this.configuration);
+ using (var op = client.StartOperation("request"))
+ {
+ this.httpProcessingFramework.OnRequestSend(request);
+
+ var actualParentIdHeader = request.Headers[RequestResponseHeaders.StandardParentIdHeader];
+ var actualRequestIdHeader = request.Headers[RequestResponseHeaders.RequestIdHeader];
+ Assert.IsNotNull(actualParentIdHeader);
+ Assert.AreNotEqual(actualParentIdHeader, op.Telemetry.Context.Operation.Id);
+
+ Assert.AreEqual(actualParentIdHeader, actualRequestIdHeader);
+#if NET45
+ Assert.IsTrue(actualRequestIdHeader.StartsWith(Activity.Current.Id, StringComparison.Ordinal));
+ Assert.AreNotEqual(Activity.Current.Id, actualRequestIdHeader);
+#else
+ Assert.AreEqual(op.Telemetry.Context.Operation.Id, ApplicationInsightsActivity.GetRootId(request.Headers[RequestResponseHeaders.StandardParentIdHeader]));
+#endif
+ // This code should go away when Activity is fixed: https://github.com/dotnet/corefx/issues/18418
+ // check that Ids are not generated by Activity
+ // so they look like OperationTelemetry.Id
+ var operationId = op.Telemetry.Context.Operation.Id;
+
+ // length is like default RequestTelemetry.Id length
+ Assert.AreEqual(new DependencyTelemetry().Id.Length, operationId.Length);
+
+ // operationId is ulong base64 encoded
+ byte[] data = Convert.FromBase64String(operationId);
+ Assert.AreEqual(8, data.Length);
+ BitConverter.ToUInt64(data, 0);
+
+ // does not look like root Id generated by Activity
+ Assert.AreEqual(1, operationId.Split('-').Length);
+
+ //// end of workaround test
+ }
+ }
+
+ ///
+ /// Ensures that the source request header is not added, as per the config, when request is sent.
+ ///
+ [TestMethod]
+ [Description("Ensures that the source request header is not added when the config commands as such")]
+ public void RddTestHttpProcessingFrameworkOnBeginSkipsAddingSourceHeaderPerConfig()
+ {
+ string hostnamepart = "partofhostname";
+ string url = string.Format(CultureInfo.InvariantCulture, "http://hostnamestart{0}hostnameend.com/path/to/something?param=1", hostnamepart);
+ var request = WebRequest.Create(new Uri(url));
+
+ Assert.IsNull(request.Headers[RequestResponseHeaders.RequestContextHeader]);
+ Assert.AreEqual(0, request.Headers.Keys.Cast().Where((x) => { return x.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase); }).Count());
+
+ var localHttpProcessingFramework = new DesktopDiagnosticSourceHttpProcessing(
+ this.configuration,
+ new ObjectInstanceBasedOperationHolder(),
+ false,
+ new List(),
+ RandomAppIdEndpoint);
+
+ localHttpProcessingFramework.OnRequestSend(request);
+ Assert.IsNull(request.Headers[RequestResponseHeaders.RequestContextHeader]);
+ Assert.AreEqual(0, request.Headers.Keys.Cast().Count(x => x.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)));
+
+ ICollection exclusionList = new SanitizedHostList() { "randomstringtoexclude", hostnamepart };
+ localHttpProcessingFramework = new DesktopDiagnosticSourceHttpProcessing(
+ this.configuration,
+ new ObjectInstanceBasedOperationHolder(),
+ true,
+ exclusionList,
+ RandomAppIdEndpoint);
+ localHttpProcessingFramework.OnRequestSend(request);
+ Assert.IsNull(request.Headers[RequestResponseHeaders.RequestContextHeader]);
+ Assert.AreEqual(0, request.Headers.Keys.Cast().Count(x => x.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)));
+ }
+
+ ///
+ /// Ensures that the source request header is not overwritten if already provided by the user.
+ ///
+ [TestMethod]
+ [Description("Ensures that the source request header is not overwritten if already provided by the user.")]
+ public void RddTestHttpProcessingFrameworkOnBeginDoesNotOverwriteExistingSource()
+ {
+ string sampleHeaderValueWithAppId = RequestResponseHeaders.RequestContextCorrelationSourceKey + "=HelloWorld";
+ var request = WebRequest.Create(this.testUrl);
+
+ request.Headers.Add(RequestResponseHeaders.RequestContextHeader, sampleHeaderValueWithAppId);
+
+ this.httpProcessingFramework.OnRequestSend(request);
+ var actualHeaderValue = request.Headers[RequestResponseHeaders.RequestContextHeader];
+
+ Assert.IsNotNull(actualHeaderValue);
+ Assert.AreEqual(sampleHeaderValueWithAppId, actualHeaderValue);
+
+ string sampleHeaderValueWithoutAppId = "helloWorld";
+ request = WebRequest.Create(this.testUrl);
+
+ request.Headers.Add(RequestResponseHeaders.RequestContextHeader, sampleHeaderValueWithoutAppId);
+
+ this.httpProcessingFramework.OnRequestSend(request);
+ actualHeaderValue = request.Headers[RequestResponseHeaders.RequestContextHeader];
+
+ Assert.IsNotNull(actualHeaderValue);
+ Assert.AreNotEqual(sampleHeaderValueWithAppId, actualHeaderValue);
+ }
+
+ private static void ValidateTelemetryPacketForOnRequestSend(DependencyTelemetry remoteDependencyTelemetryActual, Uri url, string kind, bool? success, double valueMin, string statusCode)
+ {
+ Assert.AreEqual("GET " + url.AbsolutePath, remoteDependencyTelemetryActual.Name, true, "Resource name in the sent telemetry is wrong");
+ string expectedVersion =
+ SdkVersionHelper.GetExpectedSdkVersion(typeof(DependencyTrackingTelemetryModule), prefix: "rddfd:");
+ ValidateTelemetryPacket(remoteDependencyTelemetryActual, url, kind, success, valueMin, statusCode, expectedVersion);
+ }
+
+ private static void ValidateTelemetryPacket(DependencyTelemetry remoteDependencyTelemetryActual, Uri url, string kind, bool? success, double valueMin, string statusCode, string expectedVersion)
+ {
+ Assert.AreEqual(url.Host, remoteDependencyTelemetryActual.Target, true, "Resource target in the sent telemetry is wrong");
+ Assert.AreEqual(url.OriginalString, remoteDependencyTelemetryActual.Data, true, "Resource data in the sent telemetry is wrong");
+ Assert.AreEqual(kind.ToString(), remoteDependencyTelemetryActual.Type, "DependencyKind in the sent telemetry is wrong");
+ Assert.AreEqual(success, remoteDependencyTelemetryActual.Success, "Success in the sent telemetry is wrong");
+ Assert.AreEqual(statusCode, remoteDependencyTelemetryActual.ResultCode, "ResultCode in the sent telemetry is wrong");
+
+ var valueMinRelaxed = valueMin - TimeAccuracyMilliseconds;
+ Assert.IsTrue(
+ remoteDependencyTelemetryActual.Duration >= TimeSpan.FromMilliseconds(valueMinRelaxed),
+ string.Format(CultureInfo.InvariantCulture, "Value (dependency duration = {0}) in the sent telemetry should be equal or more than the time duration between start and end", remoteDependencyTelemetryActual.Duration));
+
+ var valueMax = valueMin + TimeAccuracyMilliseconds;
+ Assert.IsTrue(
+ remoteDependencyTelemetryActual.Duration <= TimeSpan.FromMilliseconds(valueMax),
+ string.Format(CultureInfo.InvariantCulture, "Value (dependency duration = {0}) in the sent telemetry should not be signigficantly bigger then the time duration between start and end", remoteDependencyTelemetryActual.Duration));
+
+ Assert.AreEqual(expectedVersion, remoteDependencyTelemetryActual.Context.GetInternalContext().SdkVersion);
+ }
+
+ private string GetCorrelationIdValue(string appId)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "cid-v1:{0}", appId);
+ }
+
+ private string GetCorrelationIdHeaderValue(string appId)
+ {
+ return string.Format(CultureInfo.InvariantCulture, "{0}=cid-v1:{1}", RequestResponseHeaders.RequestContextCorrelationTargetKey, appId);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Src/DependencyCollector/Shared.Tests/Implementation/FrameworkHttpProcessingTest.cs b/Src/DependencyCollector/Shared.Tests/Implementation/FrameworkHttpProcessingTest.cs
index c9043d759..2fd5ea593 100644
--- a/Src/DependencyCollector/Shared.Tests/Implementation/FrameworkHttpProcessingTest.cs
+++ b/Src/DependencyCollector/Shared.Tests/Implementation/FrameworkHttpProcessingTest.cs
@@ -54,11 +54,13 @@ public void TestInitialize()
return tcs.Task;
});
this.httpProcessingFramework.OverrideCorrelationIdLookupHelper(correlationIdLookupHelper);
+ DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated = false;
}
[TestCleanup]
public void Cleanup()
- {
+ {
+ DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated = false;
}
#endregion //TestInitiliaze
@@ -171,7 +173,7 @@ public void RddTestHttpProcessingFrameworkOnEndHttpCallbackInvalidId()
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
var id1 = ClientServerDependencyTracker.GetIdForRequestObject(request);
var id2 = 200;
- this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnBeginHttpCallback(id1, this.testUrl.ToString());
Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
@@ -187,7 +189,7 @@ public void OnEndHttpCallbackSetsSuccessToFalseForNegativeStatusCode()
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
var id = ClientServerDependencyTracker.GetIdForRequestObject(request);
- this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.ToString());
this.httpProcessingFramework.OnEndHttpCallback(id, null, false, statusCode);
Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
@@ -203,7 +205,7 @@ public void OnEndHttpCallbackSetsSuccessToTrueForLessThan400()
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
var id = ClientServerDependencyTracker.GetIdForRequestObject(request);
- this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.ToString());
this.httpProcessingFramework.OnEndHttpCallback(id, null, false, statusCode);
Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
@@ -212,6 +214,19 @@ public void OnEndHttpCallbackSetsSuccessToTrueForLessThan400()
Assert.IsTrue(actual.Success.Value);
}
+ [TestMethod]
+ public void FrameworkHttpProcessingIsDisabledWhenHttpDesktopDiagSourceIsEnabled()
+ {
+ DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated = true;
+
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
+ var id = ClientServerDependencyTracker.GetIdForRequestObject(request);
+ this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.ToString());
+ this.httpProcessingFramework.OnEndHttpCallback(id, null, false, 200);
+
+ Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be sent");
+ }
+
[TestMethod]
public void OnEndHttpCallbackSetsSuccessToFalseForMoreThan400()
{
@@ -231,7 +246,7 @@ public void HttpProcessorSetsTargetForNonStandardPort()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrlNonStandardPort);
var id = ClientServerDependencyTracker.GetIdForRequestObject(request);
- this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrlNonStandardPort.ToString());
this.httpProcessingFramework.OnEndHttpCallback(id, null, false, 500);
Assert.AreEqual(1, this.sendItems.Count, "Exactly one telemetry item should be sent");
@@ -240,222 +255,6 @@ public void HttpProcessorSetsTargetForNonStandardPort()
Assert.AreEqual(expectedTarget, receivedItem.Target, "HttpProcessingFramework returned incorrect target for non standard port.");
}
- ///
- /// Validates that even if OnBeginHttpCallback is called after OnRequestSend, the
- /// packet should match what's written during OnRequestSend.
- ///
- [TestMethod]
- public void RddTestHttpProcessingFrameworkUpdateTelemetryName()
- {
- Stopwatch stopwatch = Stopwatch.StartNew();
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
- var id = ClientServerDependencyTracker.GetIdForRequestObject(request);
- this.httpProcessingFramework.OnRequestSend(request);
- this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.OriginalString);
- Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
- Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
- this.httpProcessingFramework.OnEndHttpCallback(id, true, false, 200);
- stopwatch.Stop();
-
- Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
- ValidateTelemetryPacketForOnRequestSend(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, true, stopwatch.Elapsed.TotalMilliseconds, "200");
- }
-
- ///
- /// Validates that even if multiple events have fired, as long as there is only
- /// one HttpWebRequest, only one event should be written, during the first call
- /// to OnEndHttpCallback.
- ///
- [TestMethod]
- public void RddTestHttpProcessingFrameworkNoDuplication()
- {
- Stopwatch stopwatch = Stopwatch.StartNew();
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
- var id = ClientServerDependencyTracker.GetIdForRequestObject(request);
- var returnObject = TestUtils.GenerateHttpWebResponse(HttpStatusCode.BadRequest);
-
- this.httpProcessingFramework.OnRequestSend(request);
- this.httpProcessingFramework.OnRequestSend(request);
- this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.OriginalString);
- this.httpProcessingFramework.OnRequestSend(request);
- this.httpProcessingFramework.OnRequestSend(request);
- this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.OriginalString);
- this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.OriginalString);
- this.httpProcessingFramework.OnRequestSend(request);
- Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
- Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
- this.httpProcessingFramework.OnResponseReceive(request, returnObject);
- this.httpProcessingFramework.OnEndHttpCallback(id, false, false, 409);
- this.httpProcessingFramework.OnEndHttpCallback(id, true, false, 304);
- this.httpProcessingFramework.OnResponseReceive(request, returnObject);
- this.httpProcessingFramework.OnEndHttpCallback(id, true, false, 200);
- this.httpProcessingFramework.OnResponseReceive(request, returnObject);
- this.httpProcessingFramework.OnEndHttpCallback(id, false, false, 400);
- stopwatch.Stop();
-
- Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
- ValidateTelemetryPacketForOnRequestSend(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, false, stopwatch.Elapsed.TotalMilliseconds, "409");
- }
-
- ///
- /// Validates if DependencyTelemetry sent contains the cross component correlation ID.
- ///
- [TestMethod]
- [Description("Validates if DependencyTelemetry sent contains the cross component correlation ID.")]
- public void RddTestHttpProcessingFrameworkOnEndAddsAppIdToTargetField()
- {
- // Here is a sample App ID, since the test initialize method adds a random ikey and our mock getAppId method pretends that the appId for a given ikey is the same as the ikey.
- // This will not match the current component's App ID. Hence represents an external component.
- string appId = "0935FC42-FE1A-4C67-975C-0C9D5CBDEE8E";
-
- this.SimulateWebRequestResponseWithAppId(appId);
-
- Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
- Assert.AreEqual(this.testUrl.Host + " | " + this.GetCorrelationIdValue(appId), ((DependencyTelemetry)this.sendItems[0]).Target);
- }
-
- ///
- /// Ensures that the source request header is added when request is sent.
- ///
- [TestMethod]
- [Description("Ensures that the source request header is added when request is sent.")]
- public void RddTestHttpProcessingFrameworkOnBeginAddsSourceHeader()
- {
- var request = WebRequest.Create(this.testUrl);
-
- Assert.IsNull(request.Headers[RequestResponseHeaders.RequestContextHeader]);
-
- this.httpProcessingFramework.OnRequestSend(request);
- Assert.IsNotNull(request.Headers.GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader, RequestResponseHeaders.RequestContextCorrelationSourceKey));
- }
-
- ///
- /// Ensures that the parent id header is added when request is sent.
- ///
- [TestMethod]
- public void RddTestHttpProcessingFrameworkOnBeginAddsParentIdHeader()
- {
- var request = WebRequest.Create(this.testUrl);
-
- Assert.IsNull(request.Headers[RequestResponseHeaders.StandardParentIdHeader]);
-
- var client = new TelemetryClient(this.configuration);
- using (var op = client.StartOperation("request"))
- {
- this.httpProcessingFramework.OnRequestSend(request);
-
- var actualParentIdHeader = request.Headers[RequestResponseHeaders.StandardParentIdHeader];
- var actualRequestIdHeader = request.Headers[RequestResponseHeaders.RequestIdHeader];
- Assert.IsNotNull(actualParentIdHeader);
- Assert.AreNotEqual(actualParentIdHeader, op.Telemetry.Context.Operation.Id);
-
- Assert.AreEqual(actualParentIdHeader, actualRequestIdHeader);
-#if NET45
- Assert.IsTrue(actualRequestIdHeader.StartsWith(Activity.Current.Id, StringComparison.Ordinal));
- Assert.AreNotEqual(Activity.Current.Id, actualRequestIdHeader);
-#else
- Assert.AreEqual(op.Telemetry.Context.Operation.Id, ApplicationInsightsActivity.GetRootId(request.Headers[RequestResponseHeaders.StandardParentIdHeader]));
-#endif
- // This code should go away when Activity is fixed: https://github.com/dotnet/corefx/issues/18418
- // check that Ids are not generated by Activity
- // so they look like OperationTelemetry.Id
- var operationId = op.Telemetry.Context.Operation.Id;
-
- // length is like default RequestTelemetry.Id length
- Assert.AreEqual(new DependencyTelemetry().Id.Length, operationId.Length);
-
- // operationId is ulong base64 encoded
- byte[] data = Convert.FromBase64String(operationId);
- Assert.AreEqual(8, data.Length);
- BitConverter.ToUInt64(data, 0);
-
- // does not look like root Id generated by Activity
- Assert.AreEqual(1, operationId.Split('-').Length);
-
- //// end of workaround test
- }
- }
-
- ///
- /// Ensures that the source request header is not added, as per the config, when request is sent.
- ///
- [TestMethod]
- [Description("Ensures that the source request header is not added when the config commands as such")]
- public void RddTestHttpProcessingFrameworkOnBeginSkipsAddingSourceHeaderPerConfig()
- {
- string hostnamepart = "partofhostname";
- string url = string.Format(CultureInfo.InvariantCulture, "http://hostnamestart{0}hostnameend.com/path/to/something?param=1", hostnamepart);
- var request = WebRequest.Create(new Uri(url));
-
- Assert.IsNull(request.Headers[RequestResponseHeaders.RequestContextHeader]);
- Assert.AreEqual(0, request.Headers.Keys.Cast().Where((x) => { return x.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase); }).Count());
-
- var httpProcessingFramework = new FrameworkHttpProcessing(this.configuration, new CacheBasedOperationHolder("tempCache1", 100 * 1000), /*setCorrelationHeaders*/ false, new List(), RandomAppIdEndpoint);
- httpProcessingFramework.OnRequestSend(request);
- Assert.IsNull(request.Headers[RequestResponseHeaders.RequestContextHeader]);
- Assert.AreEqual(0, request.Headers.Keys.Cast().Where((x) => { return x.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase); }).Count());
-
- ICollection exclusionList = new SanitizedHostList() { "randomstringtoexclude", hostnamepart };
- httpProcessingFramework = new FrameworkHttpProcessing(this.configuration, new CacheBasedOperationHolder("tempCache2", 100 * 1000), /*setCorrelationHeaders*/ true, exclusionList, RandomAppIdEndpoint);
- httpProcessingFramework.OnRequestSend(request);
- Assert.IsNull(request.Headers[RequestResponseHeaders.RequestContextHeader]);
- Assert.AreEqual(0, request.Headers.Keys.Cast().Where((x) => { return x.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase); }).Count());
- }
-
- ///
- /// Ensures that the source request header is not overwritten if already provided by the user.
- ///
- [TestMethod]
- [Description("Ensures that the source request header is not overwritten if already provided by the user.")]
- public void RddTestHttpProcessingFrameworkOnBeginDoesNotOverwriteExistingSource()
- {
- string sampleHeaderValueWithAppId = RequestResponseHeaders.RequestContextCorrelationSourceKey + "=HelloWorld";
- var request = WebRequest.Create(this.testUrl);
-
- request.Headers.Add(RequestResponseHeaders.RequestContextHeader, sampleHeaderValueWithAppId);
-
- this.httpProcessingFramework.OnRequestSend(request);
- var actualHeaderValue = request.Headers[RequestResponseHeaders.RequestContextHeader];
-
- Assert.IsNotNull(actualHeaderValue);
- Assert.AreEqual(sampleHeaderValueWithAppId, actualHeaderValue);
-
- string sampleHeaderValueWithoutAppId = "helloWorld";
- request = WebRequest.Create(this.testUrl);
-
- request.Headers.Add(RequestResponseHeaders.RequestContextHeader, sampleHeaderValueWithoutAppId);
-
- this.httpProcessingFramework.OnRequestSend(request);
- actualHeaderValue = request.Headers[RequestResponseHeaders.RequestContextHeader];
-
- Assert.IsNotNull(actualHeaderValue);
- Assert.AreNotEqual(sampleHeaderValueWithAppId, actualHeaderValue);
- }
-
- ///
- /// Validates HttpProcessingFramework sends correct telemetry on calling OnResponseReceive + OnEndHttpCallback.
- ///
- [TestMethod]
- [Description("Validates HttpProcessingFramework sends correct telemetry on calling OnResponseReceive + OnEndHttpCallback.")]
- [Owner("cithomas")]
- [TestCategory("CVT")]
- public void RddTestHttpProcessingFrameworkOnEndHttpCallback()
- {
- var request = WebRequest.Create(this.testUrl);
- var returnObjectPassed = TestUtils.GenerateHttpWebResponse(HttpStatusCode.OK);
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
- this.httpProcessingFramework.OnRequestSend(request);
- Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
- Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
- this.httpProcessingFramework.OnResponseReceive(request, returnObjectPassed);
- this.httpProcessingFramework.OnEndHttpCallback(ClientServerDependencyTracker.GetIdForRequestObject(request), true, true, 200);
- stopwatch.Stop();
-
- Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
- ValidateTelemetryPacketForOnRequestSend(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, true, stopwatch.Elapsed.TotalMilliseconds, "200");
- }
-
#endregion //BeginEndCallBacks
#region AsyncScenarios
@@ -475,16 +274,16 @@ public void RddTestHttpProcessingFrameworkStartTimeFromGetRequestStreamAsync()
Stopwatch stopwatch = Stopwatch.StartNew();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
var id1 = ClientServerDependencyTracker.GetIdForRequestObject(request);
- this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnBeginHttpCallback(id1, this.testUrl.ToString());
Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
- this.httpProcessingFramework.OnRequestSend(request);
+ this.httpProcessingFramework.OnBeginHttpCallback(id1, this.testUrl.ToString());
Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
this.httpProcessingFramework.OnEndHttpCallback(id1, true, false, 200);
stopwatch.Stop();
Assert.AreEqual(1, this.sendItems.Count, "Exactly one telemetry item should be sent");
- ValidateTelemetryPacketForOnRequestSend(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, true, stopwatch.Elapsed.TotalMilliseconds, "200");
+ ValidateTelemetryPacketForOnBeginHttpCallback(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, true, stopwatch.Elapsed.TotalMilliseconds, "200");
}
#endregion AsyncScenarios
@@ -506,13 +305,13 @@ private static void ValidateTelemetryPacketForOnBeginHttpCallback(
ValidateTelemetryPacket(remoteDependencyTelemetryActual, url, kind, success, valueMin, statusCode, expectedVersion);
}
- private static void ValidateTelemetryPacketForOnRequestSend(
+/* private static void ValidateTelemetryPacketForOnRequestSend(
DependencyTelemetry remoteDependencyTelemetryActual, Uri url, string kind, bool? success, double valueMin, string statusCode)
{
Assert.AreEqual("GET " + url.AbsolutePath, remoteDependencyTelemetryActual.Name, true, "Resource name in the sent telemetry is wrong");
string expectedVersion = SdkVersionHelper.GetExpectedSdkVersion(typeof(DependencyTrackingTelemetryModule), prefix: "rddfd:");
ValidateTelemetryPacket(remoteDependencyTelemetryActual, url, kind, success, valueMin, statusCode, expectedVersion);
- }
+ }*/
private static void ValidateTelemetryPacket(
DependencyTelemetry remoteDependencyTelemetryActual, Uri url, string kind, bool? success, double valueMin, string statusCode, string expectedVersion)
@@ -536,35 +335,6 @@ private static void ValidateTelemetryPacket(
Assert.AreEqual(expectedVersion, remoteDependencyTelemetryActual.Context.GetInternalContext().SdkVersion);
}
- private void SimulateWebRequestResponseWithAppId(string appId)
- {
- var request = WebRequest.Create(this.testUrl);
-
- Dictionary headers = new Dictionary();
- headers.Add(RequestResponseHeaders.RequestContextHeader, this.GetCorrelationIdHeaderValue(appId));
-
- var returnObjectPassed = TestUtils.GenerateHttpWebResponse(HttpStatusCode.OK, headers);
-
- this.httpProcessingFramework.OnBeginHttpCallback(ClientServerDependencyTracker.GetIdForRequestObject(request), this.testUrl.OriginalString);
- this.httpProcessingFramework.OnRequestSend(request);
- this.httpProcessingFramework.OnResponseReceive(request, returnObjectPassed);
- this.httpProcessingFramework.OnEndHttpCallback(
- ClientServerDependencyTracker.GetIdForRequestObject(request),
- true,
- true,
- (int)HttpStatusCode.OK);
- }
-
- private string GetCorrelationIdValue(string appId)
- {
- return string.Format(CultureInfo.InvariantCulture, "cid-v1:{0}", appId);
- }
-
- private string GetCorrelationIdHeaderValue(string appId)
- {
- return string.Format(CultureInfo.InvariantCulture, "{0}=cid-v1:{1}", RequestResponseHeaders.RequestContextCorrelationTargetKey, appId);
- }
-
#endregion Helpers
}
}
diff --git a/Src/DependencyCollector/Shared/DependencyCollector.Shared.projitems b/Src/DependencyCollector/Shared/DependencyCollector.Shared.projitems
index 30e3f660b..49decabfa 100644
--- a/Src/DependencyCollector/Shared/DependencyCollector.Shared.projitems
+++ b/Src/DependencyCollector/Shared/DependencyCollector.Shared.projitems
@@ -15,6 +15,7 @@
+
diff --git a/Src/DependencyCollector/Shared/DependencyTrackingTelemetryModule.cs b/Src/DependencyCollector/Shared/DependencyTrackingTelemetryModule.cs
index 83e92ed4a..e54511eb1 100644
--- a/Src/DependencyCollector/Shared/DependencyTrackingTelemetryModule.cs
+++ b/Src/DependencyCollector/Shared/DependencyTrackingTelemetryModule.cs
@@ -221,9 +221,23 @@ protected virtual void Dispose(bool disposing)
///
private void InitializeForFrameworkEventSource()
{
+#if NET45
+ DesktopDiagnosticSourceHttpProcessing desktopHttpProcessing = new DesktopDiagnosticSourceHttpProcessing(
+ this.telemetryConfiguration,
+ DependencyTableStore.Instance.WebRequestConditionalHolder,
+ this.SetComponentCorrelationHttpHeaders,
+ this.ExcludeComponentCorrelationHttpHeadersOnDomains,
+ this.EffectiveProfileQueryEndpoint);
+ this.httpDesktopDiagnosticSourceListener = new HttpDesktopDiagnosticSourceListener(desktopHttpProcessing);
+#endif
+
#if !NET40
- FrameworkHttpProcessing frameworkHttpProcessing = new FrameworkHttpProcessing(this.telemetryConfiguration, DependencyTableStore.Instance.WebRequestCacheHolder, this.SetComponentCorrelationHttpHeaders, this.ExcludeComponentCorrelationHttpHeadersOnDomains, this.EffectiveProfileQueryEndpoint);
- this.httpDesktopDiagnosticSourceListener = new HttpDesktopDiagnosticSourceListener(frameworkHttpProcessing);
+ FrameworkHttpProcessing frameworkHttpProcessing = new FrameworkHttpProcessing(
+ this.telemetryConfiguration,
+ DependencyTableStore.Instance.WebRequestCacheHolder,
+ this.SetComponentCorrelationHttpHeaders,
+ this.ExcludeComponentCorrelationHttpHeadersOnDomains,
+ this.EffectiveProfileQueryEndpoint);
// In 4.5 EventListener has a race condition issue in constructor so we retry to create listeners
this.httpEventListener = RetryPolicy.Retry(
diff --git a/Src/DependencyCollector/Shared/Implementation/ClientServerDependencyTracker.cs b/Src/DependencyCollector/Shared/Implementation/ClientServerDependencyTracker.cs
index f91f219e2..b1bca3418 100644
--- a/Src/DependencyCollector/Shared/Implementation/ClientServerDependencyTracker.cs
+++ b/Src/DependencyCollector/Shared/Implementation/ClientServerDependencyTracker.cs
@@ -106,7 +106,7 @@ internal static Tuple GetTupleForWebDependencies(WebR
Tuple telemetryTuple = null;
- if (DependencyTableStore.Instance.IsProfilerActivated || PretendProfilerIsAttached)
+ if (DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated || DependencyTableStore.Instance.IsProfilerActivated || PretendProfilerIsAttached)
{
telemetryTuple = DependencyTableStore.Instance.WebRequestConditionalHolder.Get(webRequest);
}
@@ -139,7 +139,7 @@ internal static void AddTupleForWebDependencies(WebRequest webRequest, Dependenc
}
var telemetryTuple = new Tuple(telemetry, isCustomCreated);
- if (DependencyTableStore.Instance.IsProfilerActivated || PretendProfilerIsAttached)
+ if (DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated || DependencyTableStore.Instance.IsProfilerActivated || PretendProfilerIsAttached)
{
DependencyTableStore.Instance.WebRequestConditionalHolder.Store(webRequest, telemetryTuple);
}
@@ -165,7 +165,7 @@ internal static Tuple GetTupleForSqlDependencies(SqlC
Tuple telemetryTuple = null;
- if (DependencyTableStore.Instance.IsProfilerActivated || PretendProfilerIsAttached)
+ if (DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated || DependencyTableStore.Instance.IsProfilerActivated || PretendProfilerIsAttached)
{
telemetryTuple = DependencyTableStore.Instance.SqlRequestConditionalHolder.Get(sqlRequest);
}
@@ -198,7 +198,7 @@ internal static void AddTupleForSqlDependencies(SqlCommand sqlRequest, Dependenc
}
var telemetryTuple = new Tuple(telemetry, isCustomCreated);
- if (DependencyTableStore.Instance.IsProfilerActivated || PretendProfilerIsAttached)
+ if (DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated || DependencyTableStore.Instance.IsProfilerActivated || PretendProfilerIsAttached)
{
DependencyTableStore.Instance.SqlRequestConditionalHolder.Store(sqlRequest, telemetryTuple);
}
diff --git a/Src/DependencyCollector/Shared/Implementation/DependencyTableStore.cs b/Src/DependencyCollector/Shared/Implementation/DependencyTableStore.cs
index fe38c427d..c16fd2dcf 100644
--- a/Src/DependencyCollector/Shared/Implementation/DependencyTableStore.cs
+++ b/Src/DependencyCollector/Shared/Implementation/DependencyTableStore.cs
@@ -12,6 +12,7 @@ internal class DependencyTableStore : IDisposable
internal ObjectInstanceBasedOperationHolder SqlRequestConditionalHolder;
internal bool IsProfilerActivated = false;
+ internal bool IsDesktopHttpDiagnosticSourceActivated = false;
private static DependencyTableStore instance;
private DependencyTableStore()
diff --git a/Src/DependencyCollector/Shared/Implementation/DesktopDiagnosticSourceHttpProcessing.cs b/Src/DependencyCollector/Shared/Implementation/DesktopDiagnosticSourceHttpProcessing.cs
new file mode 100644
index 000000000..a052043c2
--- /dev/null
+++ b/Src/DependencyCollector/Shared/Implementation/DesktopDiagnosticSourceHttpProcessing.cs
@@ -0,0 +1,81 @@
+#if NET45
+namespace Microsoft.ApplicationInsights.DependencyCollector.Implementation
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Net;
+ using Microsoft.ApplicationInsights.DataContracts;
+ using Microsoft.ApplicationInsights.DependencyCollector.Implementation.Operation;
+ using Microsoft.ApplicationInsights.Extensibility;
+ using Microsoft.ApplicationInsights.Web.Implementation;
+
+ ///
+ /// Concrete class with all processing logic to generate RDD data from the callbacks received from HttpDesktopDiagnosticSourceListener.
+ ///
+ internal sealed class DesktopDiagnosticSourceHttpProcessing : HttpProcessing
+ {
+ internal ObjectInstanceBasedOperationHolder TelemetryTable;
+
+ internal DesktopDiagnosticSourceHttpProcessing(TelemetryConfiguration configuration, ObjectInstanceBasedOperationHolder telemetryTupleHolder, bool setCorrelationHeaders, ICollection correlationDomainExclusionList, string appIdEndpoint)
+ : base(configuration, SdkVersionUtils.GetSdkVersion("rdd" + RddSource.FrameworkAndDiagnostic + ":"), null, setCorrelationHeaders, correlationDomainExclusionList, appIdEndpoint)
+ {
+ if (telemetryTupleHolder == null)
+ {
+ throw new ArgumentNullException("telemetryTupleHolder");
+ }
+
+ this.TelemetryTable = telemetryTupleHolder;
+ }
+
+ ///
+ /// On request send callback from Http diagnostic source.
+ ///
+ /// The WebRequest object.
+ public void OnRequestSend(WebRequest request)
+ {
+ this.OnBegin(request, true);
+ }
+
+ ///
+ /// On request send callback from Http diagnostic source.
+ ///
+ /// The WebRequest object.
+ /// The WebResponse object.
+ public void OnResponseReceive(WebRequest request, HttpWebResponse response)
+ {
+ this.OnEnd(null, request, response);
+ }
+
+ ///
+ /// Implemented by the derived class for adding the tuple to its specific cache.
+ ///
+ /// The request which acts the key.
+ /// The dependency telemetry for the tuple.
+ /// Boolean value that tells if the current telemetry item is being added by the customer or not.
+ protected override void AddTupleForWebDependencies(WebRequest webRequest, DependencyTelemetry telemetry, bool isCustomCreated)
+ {
+ var telemetryTuple = new Tuple(telemetry, isCustomCreated);
+ this.TelemetryTable.Store(webRequest, telemetryTuple);
+ }
+
+ ///
+ /// Implemented by the derived class for getting the tuple from its specific cache.
+ ///
+ /// The request which acts as the key.
+ /// The tuple for the given request.
+ protected override Tuple GetTupleForWebDependencies(WebRequest webRequest)
+ {
+ return this.TelemetryTable.Get(webRequest);
+ }
+
+ ///
+ /// Implemented by the derived class for removing the tuple from its specific cache.
+ ///
+ /// The request which acts as the key.
+ protected override void RemoveTupleForWebDependencies(WebRequest webRequest)
+ {
+ this.TelemetryTable.Remove(webRequest);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Src/DependencyCollector/Shared/Implementation/FrameworkHttpProcessing.cs b/Src/DependencyCollector/Shared/Implementation/FrameworkHttpProcessing.cs
index 93e8ccaa4..f302b3642 100644
--- a/Src/DependencyCollector/Shared/Implementation/FrameworkHttpProcessing.cs
+++ b/Src/DependencyCollector/Shared/Implementation/FrameworkHttpProcessing.cs
@@ -12,15 +12,7 @@ namespace Microsoft.ApplicationInsights.DependencyCollector.Implementation
using Microsoft.ApplicationInsights.Web.Implementation;
///
- /// Concrete class with all processing logic to generate RDD data from the callbacks
- /// received from framework events for HTTP. This class receives and uses two types of events, which
- /// are EventSource from FrameworkHttpEventListener, and DiagnosticSource from
- /// HttpDiagnosticSourceListener. The challenge is, the diagnostic source events have the WebRequest
- /// object which we need for header injection, but the events can be fired multiple times. So you won't
- /// know if it's the first request, or if it's the last response. The event source events fire at the right
- /// locations and just once, but they don't have the rich information. This class coordinates both events,
- /// store information in DependencyTelemetry properly, and fire the telemetry only on the EventSource
- /// response receive to guarantee it's done just once and at the right time.
+ /// Concrete class with all processing logic to generate RDD data from the callbacks received from FrameworkHttpEventListener.
///
internal sealed class FrameworkHttpProcessing : HttpProcessing
{
@@ -49,6 +41,12 @@ public void OnBeginHttpCallback(long id, string resourceName)
try
{
DependencyCollectorEventSource.Log.BeginCallbackCalled(id, resourceName);
+ if (DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated)
+ {
+ // request is handled by Desktop DiagnosticSource Listener
+ DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
+ return;
+ }
if (string.IsNullOrEmpty(resourceName))
{
@@ -111,7 +109,6 @@ public void OnBeginHttpCallback(long id, string resourceName)
public void OnEndHttpCallback(long id, bool? success, bool synchronous, int? statusCode)
{
DependencyCollectorEventSource.Log.EndCallbackCalled(id.ToString(CultureInfo.InvariantCulture));
-
var telemetryTuple = this.TelemetryTable.Get(id);
if (telemetryTuple == null)
@@ -125,13 +122,6 @@ public void OnEndHttpCallback(long id, bool? success, bool synchronous, int? sta
this.TelemetryTable.Remove(id);
DependencyTelemetry telemetry = telemetryTuple.Item1;
- // If this telemetry was processed via the DiagnosticSource path, we should record that fact in the
- // SdkVersion field
- if (this.HasTouchedByDiagnosticSource(telemetry))
- {
- telemetry.Context.GetInternalContext().SdkVersion = SdkVersionUtils.GetSdkVersion("rdd" + RddSource.FrameworkAndDiagnostic + ":");
- }
-
if (statusCode.HasValue)
{
// We calculate success on the base of http code and do not use the 'success' method argument
@@ -152,44 +142,6 @@ public void OnEndHttpCallback(long id, bool? success, bool synchronous, int? sta
}
}
- ///
- /// On request send callback from Http diagnostic source.
- ///
- /// The WebRequest object.
- public void OnRequestSend(WebRequest request)
- {
- // At this point, we need to determine if this is the first time we are examining this request.
- // There are 3 possibilities
- // 1. This is the very first time
- // 2. This is the first time via OnRequestSend, but it's been processed by OnBeginHttpCallback already
- // 3. This is not the first time it's processed by OnRequestSend.
- // We need to determine which case. If the telemetry object is not found, then it's case 1. If the
- // telemetry object exists, but it's never processed via DiagnosticSource, then it's case 2.
- // Otherwise, it's case 3. In both case 1 and 2, we need OnBegin to add all properties.
- Tuple tuple = this.GetTupleForWebDependencies(request);
- DependencyTelemetry telemetry = tuple?.Item1;
-
- if (this.HasTouchedByDiagnosticSource(telemetry))
- {
- // This is case 3, so make sure we skip update if it already exists.
- this.OnBegin(request, true /*skipIfNotNew*/);
- }
- else
- {
- this.OnBegin(request, false /*skipIfNotNew*/);
- }
- }
-
- ///
- /// On request send callback from Http diagnostic source.
- ///
- /// The WebRequest object.
- /// The WebResponse object.
- public void OnResponseReceive(WebRequest request, HttpWebResponse response)
- {
- this.OnEnd(null, request, response, false);
- }
-
///
/// Implemented by the derived class for adding the tuple to its specific cache.
///
@@ -220,23 +172,6 @@ protected override void RemoveTupleForWebDependencies(WebRequest webRequest)
{
this.TelemetryTable.Remove(ClientServerDependencyTracker.GetIdForRequestObject(webRequest));
}
-
- ///
- /// Detects if the telemetry object has been processed via the DiagnosticSource path.
- ///
- /// The DependencyTelemetry object to examine.
- private bool HasTouchedByDiagnosticSource(DependencyTelemetry telemetry)
- {
- // If it was ever processed via the DiagnosticSource path, then telemetry.Name
- // must have the HTTP method name at the front, so first character is not a '/'.
- string name = telemetry?.Name;
- if (!string.IsNullOrEmpty(name) && !name.StartsWith("/", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
-
- return false;
- }
}
}
#endif
\ No newline at end of file
diff --git a/Src/DependencyCollector/Shared/Implementation/HttpDesktopDiagnosticSourceListener.cs b/Src/DependencyCollector/Shared/Implementation/HttpDesktopDiagnosticSourceListener.cs
index 84df22d90..b053fbdf8 100644
--- a/Src/DependencyCollector/Shared/Implementation/HttpDesktopDiagnosticSourceListener.cs
+++ b/Src/DependencyCollector/Shared/Implementation/HttpDesktopDiagnosticSourceListener.cs
@@ -1,4 +1,4 @@
-#if !NET40
+#if NET45
namespace Microsoft.ApplicationInsights.DependencyCollector.Implementation
{
using System;
@@ -10,14 +10,14 @@ namespace Microsoft.ApplicationInsights.DependencyCollector.Implementation
///
internal class HttpDesktopDiagnosticSourceListener : IObserver>, IDisposable
{
- private readonly FrameworkHttpProcessing httpProcessingFramework;
+ private readonly DesktopDiagnosticSourceHttpProcessing httpProcessingFramework;
private readonly HttpDesktopDiagnosticSourceSubscriber subscribeHelper;
private readonly PropertyFetcher requestFetcherRequestEvent;
private readonly PropertyFetcher requestFetcherResponseEvent;
private readonly PropertyFetcher responseFetcher;
private bool disposed = false;
- internal HttpDesktopDiagnosticSourceListener(FrameworkHttpProcessing httpProcessing)
+ internal HttpDesktopDiagnosticSourceListener(DesktopDiagnosticSourceHttpProcessing httpProcessing)
{
this.httpProcessingFramework = httpProcessing;
this.subscribeHelper = new HttpDesktopDiagnosticSourceSubscriber(this);
diff --git a/Src/DependencyCollector/Shared/Implementation/HttpDesktopDiagnosticSourceSubscriber.cs b/Src/DependencyCollector/Shared/Implementation/HttpDesktopDiagnosticSourceSubscriber.cs
index 9e044e11f..37dc4d15b 100644
--- a/Src/DependencyCollector/Shared/Implementation/HttpDesktopDiagnosticSourceSubscriber.cs
+++ b/Src/DependencyCollector/Shared/Implementation/HttpDesktopDiagnosticSourceSubscriber.cs
@@ -48,6 +48,7 @@ public void OnNext(DiagnosticListener value)
if (value.Name == "System.Net.Http.Desktop")
{
this.sourceSubscription = value.Subscribe(this.parent, (Predicate)null);
+ DependencyTableStore.Instance.IsDesktopHttpDiagnosticSourceActivated = true;
}
}
}
diff --git a/Src/DependencyCollector/Shared/Implementation/HttpProcessing.cs b/Src/DependencyCollector/Shared/Implementation/HttpProcessing.cs
index eabe369ad..e9b8eede5 100644
--- a/Src/DependencyCollector/Shared/Implementation/HttpProcessing.cs
+++ b/Src/DependencyCollector/Shared/Implementation/HttpProcessing.cs
@@ -249,8 +249,7 @@ internal object OnBegin(object thisObj, bool skipIfNotNew)
/// The exception object if any.
/// This object.
/// Return value of the function if any.
- /// Whether this method should end the tracking or not.
- internal void OnEnd(object exception, object thisObj, object returnValue, bool endTracking)
+ internal void OnEnd(object exception, object thisObj, object returnValue)
{
try
{
@@ -284,12 +283,7 @@ internal void OnEnd(object exception, object thisObj, object returnValue, bool e
// Not custom created
if (!telemetryTuple.Item2)
{
- // Remove it from the tracker only if the caller thinks tracking should end here. If not, the caller
- // may want to end tracking outside of this function
- if (endTracking)
- {
- this.RemoveTupleForWebDependencies(webRequest);
- }
+ this.RemoveTupleForWebDependencies(webRequest);
DependencyTelemetry telemetry = telemetryTuple.Item1;
@@ -385,10 +379,7 @@ internal void OnEnd(object exception, object thisObj, object returnValue, bool e
}
}
- if (endTracking)
- {
- ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
- }
+ ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
}
}
catch (Exception ex)
diff --git a/Src/DependencyCollector/Shared/Implementation/ProfilerHttpProcessing.cs b/Src/DependencyCollector/Shared/Implementation/ProfilerHttpProcessing.cs
index d32113ca7..ae7dfd82a 100644
--- a/Src/DependencyCollector/Shared/Implementation/ProfilerHttpProcessing.cs
+++ b/Src/DependencyCollector/Shared/Implementation/ProfilerHttpProcessing.cs
@@ -63,7 +63,7 @@ public object OnBeginForGetResponse(object thisObj)
/// The resulting return value.
public object OnEndForGetResponse(object context, object returnValue, object thisObj)
{
- this.OnEnd(null, thisObj, returnValue, true);
+ this.OnEnd(null, thisObj, returnValue);
return returnValue;
}
@@ -75,7 +75,7 @@ public object OnEndForGetResponse(object context, object returnValue, object thi
/// This object.
public void OnExceptionForGetResponse(object context, object exception, object thisObj)
{
- this.OnEnd(exception, thisObj, null, true);
+ this.OnEnd(exception, thisObj, null);
}
///
@@ -99,7 +99,7 @@ public object OnBeginForGetRequestStream(object thisObj, object transportContext
/// The transport context parameter.
public void OnExceptionForGetRequestStream(object context, object exception, object thisObj, object transportContext)
{
- this.OnEnd(exception, thisObj, null, true);
+ this.OnEnd(exception, thisObj, null);
}
///
@@ -124,7 +124,7 @@ public object OnBeginForBeginGetResponse(object thisObj, object callback, object
/// The return value passed.
public object OnEndForEndGetResponse(object context, object returnValue, object thisObj, object asyncResult)
{
- this.OnEnd(null, thisObj, returnValue, true);
+ this.OnEnd(null, thisObj, returnValue);
return returnValue;
}
@@ -137,7 +137,7 @@ public object OnEndForEndGetResponse(object context, object returnValue, object
/// The asyncResult parameter.
public void OnExceptionForEndGetResponse(object context, object exception, object thisObj, object asyncResult)
{
- this.OnEnd(exception, thisObj, null, true);
+ this.OnEnd(exception, thisObj, null);
}
///
@@ -163,7 +163,7 @@ public object OnBeginForBeginGetRequestStream(object thisObj, object callback, o
/// The transportContext parameter.
public void OnExceptionForEndGetRequestStream(object context, object exception, object thisObj, object asyncResult, object transportContext)
{
- this.OnEnd(exception, thisObj, null, true);
+ this.OnEnd(exception, thisObj, null);
}
#endregion // Http callbacks