diff --git a/src/Microsoft.AspNet.TelemetryCorrelation/ActivityHelper.cs b/src/Microsoft.AspNet.TelemetryCorrelation/ActivityHelper.cs index 73cdba5..5423f1d 100644 --- a/src/Microsoft.AspNet.TelemetryCorrelation/ActivityHelper.cs +++ b/src/Microsoft.AspNet.TelemetryCorrelation/ActivityHelper.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections; using System.Diagnostics; using System.Web; @@ -27,53 +28,35 @@ internal static class ActivityHelper public const string AspNetActivityStartName = "Microsoft.AspNet.HttpReqIn.Start"; /// - /// Event name for the activity stop event. + /// Event name for the lost activity stop event. /// public const string AspNetActivityLostStopName = "Microsoft.AspNet.HttpReqIn.ActivityLost.Stop"; + /// + /// Event name for the restored activity stop event. + /// + public const string AspNetActivityRestoredStopName = "Microsoft.AspNet.HttpReqIn.ActivityRestored.Stop"; + /// /// Key to store the activity in HttpContext. /// public const string ActivityKey = "__AspnetActivity__"; - private const int MaxActivityStackSize = 128; - private static readonly DiagnosticListener AspNetListener = new DiagnosticListener(AspNetListenerName); - /// - /// It's possible that a request is executed in both native threads and managed threads, - /// in such case Activity.Current will be lost during native thread and managed thread switch. - /// This method is intended to restore the current activity in order to correlate the child - /// activities with the root activity of the request. + /// Key to store the restored activity in HttpContext. /// - /// Root activity id for the current request. - /// If it returns an activity, it will be silently stopped with the parent activity - public static Activity RestoreCurrentActivity(Activity root) - { - Debug.Assert(root != null); - - // workaround to restore the root activity, because we don't - // have a way to change the Activity.Current - var childActivity = new Activity(root.OperationName); - childActivity.SetParentId(root.Id); - childActivity.SetStartTime(root.StartTimeUtc); - foreach (var item in root.Baggage) - { - childActivity.AddBaggage(item.Key, item.Value); - } + public const string RestoredActivityKey = "__AspnetActivityRestored__"; - childActivity.Start(); - - AspNetTelemetryCorrelationEventSource.Log.ActivityStarted(childActivity.Id); - return childActivity; - } + private const int MaxActivityStackSize = 128; + private static readonly DiagnosticListener AspNetListener = new DiagnosticListener(AspNetListenerName); /// /// Stops the activity and notifies listeners about it. /// /// Activity to stop. - /// Current HttpContext. + /// HttpContext.Items. /// True if activity was found in the stack, false otherwise. - public static bool StopAspNetActivity(Activity activity, HttpContext context) + public static bool StopAspNetActivity(Activity activity, IDictionary contextItems) { var currentActivity = Activity.Current; if (activity != null && currentActivity != null) @@ -87,11 +70,11 @@ public static bool StopAspNetActivity(Activity activity, HttpContext context) if (newCurrentActivity == null) { - break; + return false; } // there could be a case when request or any child activity is stopped - // from the child execution context. In this case, Activity is present in the Current Stack, + // from the child execution context. In this case, Activity is present in the Current Stack, // but is finished, i.e. stopping it has no effect on the Current. if (newCurrentActivity == currentActivity) { @@ -116,13 +99,11 @@ public static bool StopAspNetActivity(Activity activity, HttpContext context) } // if activity is in the stack, stop it with Stop event - if (Activity.Current != null) - { - AspNetListener.StopActivity(Activity.Current, new { }); - RemoveCurrentActivity(context); - AspNetTelemetryCorrelationEventSource.Log.ActivityStopped(activity.Id); - return true; - } + AspNetListener.StopActivity(currentActivity, new { }); + contextItems[ActivityKey] = null; + + AspNetTelemetryCorrelationEventSource.Log.ActivityStopped(currentActivity.Id, currentActivity.OperationName); + return true; } return false; @@ -135,12 +116,21 @@ public static bool StopAspNetActivity(Activity activity, HttpContext context) /// Current HttpContext. public static void StopLostActivity(Activity activity, HttpContext context) { - if (activity != null) - { - AspNetListener.Write(AspNetActivityLostStopName, new { activity }); - RemoveCurrentActivity(context); - AspNetTelemetryCorrelationEventSource.Log.ActivityStopped(activity.Id, true); - } + context.Items[ActivityKey] = null; + AspNetListener.Write(AspNetActivityLostStopName, new { activity }); + AspNetTelemetryCorrelationEventSource.Log.ActivityStopped(activity.Id, AspNetActivityLostStopName); + } + + /// + /// Notifies listeners that there the lost activity was lost during execution and there was an intermediate activity. + /// + /// Activity to notify about. + /// Current HttpContext. + public static void StopRestoredActivity(Activity activity, HttpContext context) + { + context.Items[RestoredActivityKey] = null; + AspNetListener.Write(AspNetActivityRestoredStopName, new { Activity = activity }); + AspNetTelemetryCorrelationEventSource.Log.ActivityStopped(activity.Id, AspNetActivityRestoredStopName); } /// @@ -152,12 +142,12 @@ public static Activity CreateRootActivity(HttpContext context) { if (AspNetListener.IsEnabled() && AspNetListener.IsEnabled(AspNetActivityName)) { - var rootActivity = new Activity(ActivityHelper.AspNetActivityName); + var rootActivity = new Activity(AspNetActivityName); rootActivity.Extract(context.Request.Unvalidated.Headers); if (StartAspNetActivity(rootActivity)) { - SaveCurrentActivity(context, rootActivity); + context.Items[ActivityKey] = rootActivity; AspNetTelemetryCorrelationEventSource.Log.ActivityStarted(rootActivity.Id); return rootActivity; } @@ -167,16 +157,56 @@ public static Activity CreateRootActivity(HttpContext context) } /// - /// This should be called after the Activity starts and only for root activity of a request. + /// Saves activity in the HttpContext.Items. /// - /// Context to save context to. + /// Context to save context to. + /// Slot name. /// Activity to save. - internal static void SaveCurrentActivity(HttpContext context, Activity activity) + internal static void SaveCurrentActivity(IDictionary contextItems, string key, Activity activity) { - Debug.Assert(context != null); + Debug.Assert(contextItems != null); Debug.Assert(activity != null); - context.Items[ActivityKey] = activity; + contextItems[key] = activity; + } + + /// + /// It's possible that a request is executed in both native threads and managed threads, + /// in such case Activity.Current will be lost during native thread and managed thread switch. + /// This method is intended to restore the current activity in order to correlate the child + /// activities with the root activity of the request. + /// + /// HttpContext.Items dictionary. + internal static void RestoreActivityIfNeeded(IDictionary contextItems) + { + if (Activity.Current == null) + { + var rootActivity = (Activity)contextItems[ActivityKey]; + if (rootActivity != null && !contextItems.Contains(RestoredActivityKey)) + { + contextItems[RestoredActivityKey] = RestoreActivity(rootActivity); + } + } + } + + private static Activity RestoreActivity(Activity root) + { + Debug.Assert(root != null); + + // workaround to restore the root activity, because we don't + // have a way to change the Activity.Current + var childActivity = new Activity(root.OperationName); + childActivity.SetParentId(root.Id); + childActivity.SetStartTime(root.StartTimeUtc); + foreach (var item in root.Baggage) + { + childActivity.AddBaggage(item.Key, item.Value); + } + + childActivity.Start(); + + AspNetTelemetryCorrelationEventSource.Log.ActivityRestored(childActivity.Id); + return childActivity; } private static bool StartAspNetActivity(Activity activity) @@ -197,11 +227,5 @@ private static bool StartAspNetActivity(Activity activity) return false; } - - private static void RemoveCurrentActivity(HttpContext context) - { - Debug.Assert(context != null); - context.Items[ActivityKey] = null; - } } } diff --git a/src/Microsoft.AspNet.TelemetryCorrelation/AspNetTelemetryCorrelationEventSource.cs b/src/Microsoft.AspNet.TelemetryCorrelation/AspNetTelemetryCorrelationEventSource.cs index 8b6591f..5f5fb94 100644 --- a/src/Microsoft.AspNet.TelemetryCorrelation/AspNetTelemetryCorrelationEventSource.cs +++ b/src/Microsoft.AspNet.TelemetryCorrelation/AspNetTelemetryCorrelationEventSource.cs @@ -29,10 +29,10 @@ public void ActivityStarted(string id) WriteEvent(2, id); } - [Event(3, Message = "Activity stopped, Id='{0}', lost {1}", Level = EventLevel.Verbose)] - public void ActivityStopped(string id, bool lost = false) + [Event(3, Message = "Activity stopped, Id='{0}', Name='{1}'", Level = EventLevel.Verbose)] + public void ActivityStopped(string id, string eventName) { - WriteEvent(3, id, lost); + WriteEvent(3, id, eventName); } [Event(4, Message = "Failed to parse header '{0}', value: '{1}'", Level = EventLevel.Informational)] @@ -58,6 +58,12 @@ public void ActivityStackIsTooDeep(string id, string name) { WriteEvent(7, id, name); } + + [Event(8, Message = "Activity restored, Id='{0}'", Level = EventLevel.Informational)] + public void ActivityRestored(string id) + { + WriteEvent(8, id); + } } } #pragma warning restore SA1600 // Elements must be documented \ No newline at end of file diff --git a/src/Microsoft.AspNet.TelemetryCorrelation/TelemetryCorrelationHttpModule.cs b/src/Microsoft.AspNet.TelemetryCorrelation/TelemetryCorrelationHttpModule.cs index 25c3063..de4e480 100644 --- a/src/Microsoft.AspNet.TelemetryCorrelation/TelemetryCorrelationHttpModule.cs +++ b/src/Microsoft.AspNet.TelemetryCorrelation/TelemetryCorrelationHttpModule.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Reflection; using System.Web; namespace Microsoft.AspNet.TelemetryCorrelation @@ -13,6 +14,12 @@ namespace Microsoft.AspNet.TelemetryCorrelation public class TelemetryCorrelationHttpModule : IHttpModule { private const string BeginCalledFlag = "Microsoft.AspNet.TelemetryCorrelation.BeginCalled"; + private static MethodInfo onStepMethodInfo = null; + + static TelemetryCorrelationHttpModule() + { + onStepMethodInfo = typeof(HttpApplication).GetMethod("OnExecuteRequestStep"); + } /// public void Dispose() @@ -24,7 +31,40 @@ public void Init(HttpApplication context) { context.BeginRequest += Application_BeginRequest; context.EndRequest += Application_EndRequest; - context.PreRequestHandlerExecute += Application_PreRequestHandlerExecute; + + // OnExecuteRequestStep is availabile starting with 4.7.1 + // If this is executed in 4.7.1 runtime (regardless of targeted .NET version), + // we will use it to restore lost activity, otherwise keep PreRequestHandlerExecute + if (onStepMethodInfo != null) + { + onStepMethodInfo.Invoke(context, new object[] { (Action)OnExecuteRequestStep }); + } + else + { + context.PreRequestHandlerExecute += Application_PreRequestHandlerExecute; + } + } + + /// + /// Restores Activity before each pipeline step if it was lost. + /// + /// HttpContext instance. + /// Step to be executed. + internal void OnExecuteRequestStep(HttpContextBase context, Action step) + { + // Once we have public Activity.Current setter (https://github.com/dotnet/corefx/issues/29207) this method will be + // simplified to just assign Current if is was lost. + // In the mean time, we are creating child Activity to restore the context. We have to send + // event with this Activity to tracing system. It created a lot of issues for listeners as + // we may potentially have a lot of them for different stages. + // To reduce amount of events, we only care about ExecuteRequestHandler stage - restore activity here and + // stop/report it to tracing system in EndRequest. + if (context.CurrentNotification == RequestNotification.ExecuteRequestHandler && !context.IsPostNotification) + { + ActivityHelper.RestoreActivityIfNeeded(context.Items); + } + + step(); } private void Application_BeginRequest(object sender, EventArgs e) @@ -38,13 +78,7 @@ private void Application_BeginRequest(object sender, EventArgs e) private void Application_PreRequestHandlerExecute(object sender, EventArgs e) { AspNetTelemetryCorrelationEventSource.Log.TraceCallback("Application_PreRequestHandlerExecute"); - var context = ((HttpApplication)sender).Context; - - var rootActivity = (Activity)context.Items[ActivityHelper.ActivityKey]; - if (Activity.Current == null && rootActivity != null) - { - ActivityHelper.RestoreCurrentActivity(rootActivity); - } + ActivityHelper.RestoreActivityIfNeeded(((HttpApplication)sender).Context.Items); } private void Application_EndRequest(object sender, EventArgs e) @@ -59,16 +93,25 @@ private void Application_EndRequest(object sender, EventArgs e) { // Activity has never been started var activity = ActivityHelper.CreateRootActivity(context); - ActivityHelper.StopAspNetActivity(activity, context); + ActivityHelper.StopAspNetActivity(activity, context.Items); } else { var activity = (Activity)context.Items[ActivityHelper.ActivityKey]; // try to stop activity if it's in the Current stack - if (!ActivityHelper.StopAspNetActivity(activity, context)) + // stop all running Activities on the way + if (!ActivityHelper.StopAspNetActivity(activity, context.Items)) { - // Activity we created was lost, let's report it + // perhaps we attempted to restore the Activity before + var restoredActivity = (Activity)context.Items[ActivityHelper.RestoredActivityKey]; + if (restoredActivity != null) + { + // if so, report it + ActivityHelper.StopRestoredActivity(restoredActivity, context); + } + + // Activity we created was lost let's report it if (activity != null) { ActivityHelper.StopLostActivity(activity, context); diff --git a/test/Microsoft.AspNet.TelemetryCorrelation.Tests/ActivityHelperTest.cs b/test/Microsoft.AspNet.TelemetryCorrelation.Tests/ActivityHelperTest.cs index 7a6c94f..89ecbb4 100644 --- a/test/Microsoft.AspNet.TelemetryCorrelation.Tests/ActivityHelperTest.cs +++ b/test/Microsoft.AspNet.TelemetryCorrelation.Tests/ActivityHelperTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; @@ -15,11 +16,13 @@ namespace Microsoft.AspNet.TelemetryCorrelation.Tests { - public class ActivityHelperTest + public class ActivityHelperTest : IDisposable { private const string TestActivityName = "Activity.Test"; private readonly List> _baggageItems; private readonly string _baggageInHeader; + private IDisposable subscriptionAllListeners; + private IDisposable subscriptionAspNetListener; public ActivityHelperTest() { @@ -38,9 +41,15 @@ public ActivityHelperTest() var aspnetListenerField = typeof(ActivityHelper). GetField("AspNetListener", BindingFlags.Static | BindingFlags.NonPublic); aspnetListenerField.SetValue(null, new DiagnosticListener(ActivityHelper.AspNetListenerName)); - } + } + + public void Dispose() + { + subscriptionAspNetListener?.Dispose(); + subscriptionAllListeners?.Dispose(); + } - #region RestoreCurrentActivity tests + #region RestoreActivity tests [Fact] public async Task Can_Restore_Activity() { @@ -53,15 +62,84 @@ await Task.Run(() => }); Assert.Null(Activity.Current); - var restoredActivity = ActivityHelper.RestoreCurrentActivity(rootActivity); + ActivityHelper.RestoreActivityIfNeeded(context.Items); - Assert.NotNull(restoredActivity); - Assert.True(rootActivity.Id == restoredActivity.ParentId); - Assert.True(!string.IsNullOrEmpty(restoredActivity.Id)); - var expectedBaggage = _baggageItems.OrderBy(item => item.Value); - var actualBaggage = rootActivity.Baggage.OrderBy(item => item.Value); - Assert.Equal(expectedBaggage, actualBaggage); + AssertIsRestoredActivity(rootActivity, Activity.Current); + } + + + [Fact] + public void Do_Not_Restore_Activity_When_There_Is_No_Activity_In_Context() + { + ActivityHelper.RestoreActivityIfNeeded(HttpContextHelper.GetFakeHttpContext().Items); + + Assert.Null(Activity.Current); + } + + [Fact] + public void Do_Not_Restore_Activity_When_It_Is_Not_Lost() + { + var root = new Activity("root").Start(); + + var context = HttpContextHelper.GetFakeHttpContext(); + context.Items[ActivityHelper.ActivityKey] = root; + + var module = new TelemetryCorrelationHttpModule(); + + ActivityHelper.RestoreActivityIfNeeded(context.Items); + + Assert.Equal(root, Activity.Current); } + + [Fact] + public async Task Stop_Restored_Activity_Deletes_It_From_Items() + { + var context = HttpContextHelper.GetFakeHttpContext(); + var root = new Activity("root"); + + await Task.Run(() => + { + root.Start(); + context.Items[ActivityHelper.ActivityKey] = root; + }); + + ActivityHelper.RestoreActivityIfNeeded(context.Items); + + var child = Activity.Current; + + ActivityHelper.StopRestoredActivity(child, context); + Assert.NotNull(context.Items[ActivityHelper.ActivityKey]); + Assert.Null(context.Items[ActivityHelper.RestoredActivityKey]); + } + + [Fact] + public async Task Stop_Restored_Activity_Fires_Event() + { + var context = HttpContextHelper.GetFakeHttpContext(); + var root = new Activity("root"); + + await Task.Run(() => + { + root.Start(); + context.Items[ActivityHelper.ActivityKey] = root; + }); + + ActivityHelper.RestoreActivityIfNeeded(context.Items); + Activity restored = Activity.Current; + + var events = new ConcurrentQueue>(); + EnableAll((kvp) => events.Enqueue(kvp)); + + ActivityHelper.StopRestoredActivity(restored, context); + + Assert.Single(events); + string eventName = events.Single().Key; + object eventPayload = events.Single().Value; + + Assert.Equal(ActivityHelper.AspNetActivityRestoredStopName, eventName); + Assert.Same(restored, eventPayload.GetProperty("Activity")); + } + #endregion #region StopAspNetActivity tests @@ -72,7 +150,7 @@ public void Can_Stop_Activity_Without_AspNetListener_Enabled() var rootActivity = CreateActivity(); rootActivity.Start(); Thread.Sleep(100); - ActivityHelper.StopAspNetActivity(rootActivity, context); + ActivityHelper.StopAspNetActivity(rootActivity, context.Items); Assert.True(rootActivity.Duration != TimeSpan.Zero); Assert.Null(rootActivity.Parent); @@ -87,7 +165,7 @@ public void Can_Stop_Activity_With_AspNetListener_Enabled() rootActivity.Start(); Thread.Sleep(100); EnableAspNetListenerOnly(); - ActivityHelper.StopAspNetActivity(rootActivity, context); + ActivityHelper.StopAspNetActivity(rootActivity, context.Items); Assert.True(rootActivity.Duration != TimeSpan.Zero); Assert.Null(rootActivity.Parent); @@ -104,7 +182,7 @@ public void Can_Stop_Root_Activity_With_All_Children() new Activity("child").Start(); new Activity("grandchild").Start(); - ActivityHelper.StopAspNetActivity(rootActivity, context); + ActivityHelper.StopAspNetActivity(rootActivity, context.Items); Assert.True(rootActivity.Duration != TimeSpan.Zero); Assert.Null(rootActivity.Parent); @@ -120,7 +198,7 @@ public void Can_Stop_Child_Activity_With_All_Children() var child = new Activity("child").Start(); new Activity("grandchild").Start(); - ActivityHelper.StopAspNetActivity(child, context); + ActivityHelper.StopAspNetActivity(child, context.Items); Assert.True(child.Duration != TimeSpan.Zero); Assert.Equal(rootActivity, Activity.Current); @@ -132,8 +210,7 @@ public async Task Can_Stop_Root_Activity_If_It_Is_Broken() { var context = HttpContextHelper.GetFakeHttpContext(); var root = new Activity("root").Start(); - ActivityHelper.SaveCurrentActivity(context, root); - + context.Items[ActivityHelper.ActivityKey] = root; new Activity("child").Start(); for (int i = 0; i < 2; i++) @@ -151,7 +228,7 @@ await Task.Run(() => // do not affect 'parent' context in which Task.Run is called. // But 'child' Activity is stopped, thus consequent calls to Stop will // not update Current - Assert.False(ActivityHelper.StopAspNetActivity(root, context)); + Assert.False(ActivityHelper.StopAspNetActivity(root, context.Items)); Assert.NotNull(context.Items[ActivityHelper.ActivityKey]); Assert.Null(Activity.Current); } @@ -161,7 +238,7 @@ public void Stop_Root_Activity_With_129_Nesting_Depth() { var context = HttpContextHelper.GetFakeHttpContext(); var root = new Activity("root").Start(); - ActivityHelper.SaveCurrentActivity(context, root); + context.Items[ActivityHelper.ActivityKey] = root; for (int i = 0; i < 129; i++) { @@ -170,12 +247,11 @@ public void Stop_Root_Activity_With_129_Nesting_Depth() // we do not allow more than 128 nested activities here // only to protect from hypothetical cycles in Activity stack - Assert.False(ActivityHelper.StopAspNetActivity(root, context)); + Assert.False(ActivityHelper.StopAspNetActivity(root, context.Items)); Assert.NotNull(context.Items[ActivityHelper.ActivityKey]); Assert.Null(Activity.Current); } - #endregion #region CreateRootActivity tests @@ -252,6 +328,19 @@ public void Can_Create_RootActivity_And_Saved_In_HttContext() #endregion #region Helper methods + + private void AssertIsRestoredActivity(Activity original, Activity restored) + { + Assert.NotNull(restored); + Assert.Equal(original.RootId, restored.RootId); + Assert.Equal(original.Id, restored.ParentId); + Assert.Equal(original.StartTimeUtc, restored.StartTimeUtc); + Assert.False(string.IsNullOrEmpty(restored.Id)); + var expectedBaggage = original.Baggage.OrderBy(item => item.Value); + var actualBaggage = restored.Baggage.OrderBy(item => item.Value); + Assert.Equal(expectedBaggage, actualBaggage); + } + private Activity CreateActivity() { var activity = new Activity(TestActivityName); @@ -260,15 +349,27 @@ private Activity CreateActivity() return activity; } + private void EnableAll(Action> onNext = null) + { + subscriptionAllListeners = DiagnosticListener.AllListeners.Subscribe(listener => + { + // if AspNetListener has subscription, then it is enabled + if (listener.Name == ActivityHelper.AspNetListenerName) + { + subscriptionAspNetListener = listener.Subscribe(new TestDiagnosticListener(onNext), (name) => true); + } + }); + } + private void EnableAspNetListenerAndDisableActivity(Action> onNext = null, string ActivityName = ActivityHelper.AspNetActivityName) { - DiagnosticListener.AllListeners.Subscribe(listener => + subscriptionAllListeners = DiagnosticListener.AllListeners.Subscribe(listener => { // if AspNetListener has subscription, then it is enabled if (listener.Name == ActivityHelper.AspNetListenerName) { - listener.Subscribe(new TestDiagnosticListener(onNext), + subscriptionAspNetListener = listener.Subscribe(new TestDiagnosticListener(onNext), (name, arg1, arg2) => name == ActivityName && arg1 == null); } }); @@ -277,12 +378,12 @@ private void EnableAspNetListenerAndDisableActivity(Action> onNext = null, string ActivityName = ActivityHelper.AspNetActivityName) { - DiagnosticListener.AllListeners.Subscribe(listener => + subscriptionAllListeners = DiagnosticListener.AllListeners.Subscribe(listener => { // if AspNetListener has subscription, then it is enabled if (listener.Name == ActivityHelper.AspNetListenerName) { - listener.Subscribe(new TestDiagnosticListener(onNext), + subscriptionAspNetListener = listener.Subscribe(new TestDiagnosticListener(onNext), (name, arg1, arg2) => name == ActivityName); } }); @@ -290,42 +391,20 @@ private void EnableAspNetListenerAndActivity(Action private void EnableAspNetListenerOnly(Action> onNext = null) { - DiagnosticListener.AllListeners.Subscribe(listener => + subscriptionAllListeners = DiagnosticListener.AllListeners.Subscribe(listener => { // if AspNetListener has subscription, then it is enabled if (listener.Name == ActivityHelper.AspNetListenerName) { - listener.Subscribe(new TestDiagnosticListener(onNext), + subscriptionAspNetListener = listener.Subscribe(new TestDiagnosticListener(onNext), activityName => false); } }); } + #endregion #region Helper Class - private class TestDiagnosticListener : IObserver> - { - Action> _onNextCallBack; - - public TestDiagnosticListener(Action> onNext) - { - _onNextCallBack = onNext; - } - - public void OnCompleted() - { - } - - public void OnError(Exception error) - { - } - - public void OnNext(KeyValuePair value) - { - _onNextCallBack?.Invoke(value); - } - } - private class TestHttpRequest : HttpRequestBase { NameValueCollection _headers = new NameValueCollection(); diff --git a/test/Microsoft.AspNet.TelemetryCorrelation.Tests/HttpContextHelper.cs b/test/Microsoft.AspNet.TelemetryCorrelation.Tests/HttpContextHelper.cs index 19121b7..3024d14 100644 --- a/test/Microsoft.AspNet.TelemetryCorrelation.Tests/HttpContextHelper.cs +++ b/test/Microsoft.AspNet.TelemetryCorrelation.Tests/HttpContextHelper.cs @@ -18,12 +18,17 @@ public static HttpContext GetFakeHttpContext(string page = "/page", string query Thread.GetDomain().SetData(".appVPath", string.Empty); var workerRequest = new SimpleWorkerRequestWithHeaders(page, query, new StringWriter(CultureInfo.InvariantCulture), headers); - var context = new HttpContext(workerRequest); HttpContext.Current = context; return context; } + public static HttpContextBase GetFakeHttpContextBase(string page = "/page", string query = "", IDictionary headers = null) + { + var context = GetFakeHttpContext(page, query, headers); + return new HttpContextWrapper(context); + } + private class SimpleWorkerRequestWithHeaders : SimpleWorkerRequest { private readonly IDictionary headers; diff --git a/test/Microsoft.AspNet.TelemetryCorrelation.Tests/Microsoft.AspNet.TelemetryCorrelation.Tests.csproj b/test/Microsoft.AspNet.TelemetryCorrelation.Tests/Microsoft.AspNet.TelemetryCorrelation.Tests.csproj index c0b2d93..b40fc87 100644 --- a/test/Microsoft.AspNet.TelemetryCorrelation.Tests/Microsoft.AspNet.TelemetryCorrelation.Tests.csproj +++ b/test/Microsoft.AspNet.TelemetryCorrelation.Tests/Microsoft.AspNet.TelemetryCorrelation.Tests.csproj @@ -1,7 +1,8 @@  + + - @@ -67,17 +68,14 @@ ..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll - True + + ..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll - - ..\..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll - True + + ..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll - - ..\..\packages\xunit.extensibility.execution.2.2.0\lib\net452\xunit.execution.desktop.dll - True + + ..\..\packages\xunit.extensibility.execution.2.3.1\lib\net452\xunit.execution.desktop.dll @@ -85,6 +83,7 @@ + @@ -107,6 +106,9 @@ + + +