From c9375568a3a64bf429b8598395b5b39411065d37 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Tue, 18 Oct 2022 16:46:06 -0700 Subject: [PATCH 1/2] [Dotnet Monitor] Standardize DiagnosticFilterString, No Longer Assume TraceEvent Arg Ordering (#3425) * Set AspNetTriggerSourceConfiguration's DiagnosticFilterString to be the same as the one in HttpRequestSourceConfiguration. * Updated diagnostic filter string; getting arguments by name (instead of index) * Small tweaks * Spacing * Update src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/HttpRequestSourceConfiguration.cs Co-authored-by: Justin Anderson * Tweaks for Wiktor Co-authored-by: Justin Anderson --- .../AspNetTriggerSourceConfiguration.cs | 23 +-------- .../HttpRequestSourceConfiguration.cs | 10 ++-- .../Triggers/AspNet/AspNetTrigger.cs | 50 ++++++++++++------- 3 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/AspNetTriggerSourceConfiguration.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/AspNetTriggerSourceConfiguration.cs index 99d9bc4231..6f27d28ef2 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/AspNetTriggerSourceConfiguration.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/AspNetTriggerSourceConfiguration.cs @@ -23,27 +23,6 @@ public AspNetTriggerSourceConfiguration(float? heartbeatIntervalSeconds = null) _heartbeatIntervalSeconds = heartbeatIntervalSeconds; } - /// - /// Filter string for trigger data. Note that even though some triggers use start OR stop, - /// collecting just one causes unusual behavior in data collection. - /// - /// - /// IMPORTANT! We rely on these transformations to make sure we can access relevant data - /// by index. The order must match the data extracted in the triggers. - /// - private const string DiagnosticFilterString = - "Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.HttpRequestIn.Start@Activity1Start:-" + - "ActivityId=*Activity.Id" + - ";Request.Path" + - ";ActivityStartTime=*Activity.StartTimeUtc.Ticks" + - "\r\n" + - "Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop@Activity1Stop:-" + - "ActivityId=*Activity.Id" + - ";Request.Path" + - ";Response.StatusCode" + - ";ActivityDuration=*Activity.Duration.Ticks" + - "\r\n"; - public override IList GetProviders() { if (_heartbeatIntervalSeconds.HasValue) @@ -62,7 +41,7 @@ public override IList GetProviders() eventLevel: EventLevel.Verbose, arguments: new Dictionary { - { "FilterAndPayloadSpecs", DiagnosticFilterString } + { "FilterAndPayloadSpecs", HttpRequestSourceConfiguration.DiagnosticFilterString } }) }; } diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/HttpRequestSourceConfiguration.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/HttpRequestSourceConfiguration.cs index ef58ab5b6e..f592a532ae 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/HttpRequestSourceConfiguration.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/HttpRequestSourceConfiguration.cs @@ -16,7 +16,10 @@ public HttpRequestSourceConfiguration() RequestRundown = true; } - private const string DiagnosticFilterString = + // This string is shared between HttpRequestSourceConfiguration and AspNetTriggerSourceConfiguration + // due to an issue that causes the FilterAndPayloadSpecs to be overwritten but never reverted. + // This caused http traces to interfere with AspNet* triggers due to having different arguments. + internal const string DiagnosticFilterString = "Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.HttpRequestIn.Start@Activity1Start:-" + "Request.Scheme" + ";Request.Host" + @@ -33,9 +36,10 @@ public HttpRequestSourceConfiguration() ";ActivityIdFormat=*Activity.IdFormat" + "\r\n" + "Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop@Activity1Stop:-" + - "Response.StatusCode" + + "ActivityId=*Activity.Id" + + ";Request.Path" + + ";Response.StatusCode" + ";ActivityDuration=*Activity.Duration.Ticks" + - ";ActivityId=*Activity.Id" + "\r\n" + "HttpHandlerDiagnosticListener/System.Net.Http.HttpRequestOut@Event:-" + "\r\n" + diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Triggers/AspNet/AspNetTrigger.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Triggers/AspNet/AspNetTrigger.cs index 1bf45559d5..9e13c35231 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Triggers/AspNet/AspNetTrigger.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Triggers/AspNet/AspNetTrigger.cs @@ -5,7 +5,6 @@ using Microsoft.Diagnostics.Tracing; using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Linq; @@ -17,6 +16,10 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.AspNet /// internal abstract class AspNetTrigger : ITraceEventTrigger where TSettings : AspNetTriggerSettings { + private const string ActivityId = "activityid"; + private const string Path = "path"; + private const string StatusCode = "statuscode"; + private const string ActivityDuration = "activityduration"; private const string Activity1Start = "Activity1/Start"; private const string Activity1Stop = "Activity1/Stop"; private static readonly Guid MicrosoftAspNetCoreHostingGuid = new Guid("{adb401e1-5296-51f8-c125-5fda75826144}"); @@ -61,16 +64,41 @@ public bool HasSatisfiedCondition(TraceEvent traceEvent) { int? statusCode = null; long? duration = null; + string activityId = string.Empty; + string path = string.Empty; + AspnetTriggerEventType eventType = AspnetTriggerEventType.Start; System.Collections.IList arguments = (System.Collections.IList)traceEvent.PayloadValue(2); - string activityId = ExtractByIndex(arguments, 0); - string path = ExtractByIndex(arguments, 1); + + foreach (var argument in arguments) + { + if (argument is IEnumerable> argumentsEnumerable) + { + string key = (string)argumentsEnumerable.First().Value; + string value = (string)argumentsEnumerable.Last().Value; + + if (key.Equals(ActivityId, StringComparison.OrdinalIgnoreCase)) + { + activityId = value; + } + else if (key.Equals(Path, StringComparison.OrdinalIgnoreCase)) + { + path = value; + } + else if (key.Equals(StatusCode, StringComparison.OrdinalIgnoreCase)) + { + statusCode = int.Parse(value); + } + else if (key.Equals(ActivityDuration, StringComparison.OrdinalIgnoreCase)) + { + duration = long.Parse(value); + } + } + } if (traceEvent.EventName == Activity1Stop) { - statusCode = int.Parse(ExtractByIndex(arguments, 2)); - duration = long.Parse(ExtractByIndex(arguments, 3)); eventType = AspnetTriggerEventType.Stop; Debug.Assert(statusCode != null, "Status code cannot be null."); @@ -82,7 +110,6 @@ public bool HasSatisfiedCondition(TraceEvent traceEvent) //Heartbeat only return HasSatisfiedCondition(timeStamp, eventType: AspnetTriggerEventType.Heartbeat, activityId: null, path: null, statusCode: null, duration: null); - } /// @@ -111,17 +138,6 @@ internal bool HasSatisfiedCondition(DateTime timestamp, AspnetTriggerEventType e } return false; } - - private static string ExtractByIndex(System.Collections.IList arguments, int index) - { - IEnumerable> values = (IEnumerable>)arguments[index]; - //The data is internally organized as two KeyValuePair entries, - //The first entry is { Key, "KeyValue"} - //The second is { Value, "Value"} - //e.g. - //{{ Key:"StatusCode", Value:"200" }} - return (string)values.Last().Value; - } } internal enum AspnetTriggerEventType From 499e9f3bed179815eea269c4c97db42f41ddee76 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Tue, 18 Oct 2022 20:46:33 -0700 Subject: [PATCH 2/2] Revert TraceEvent version to 2.0.64 (#3473) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 27395c7504..439ea5d2b3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -47,7 +47,7 @@ 1.1.0 2.2.332302 16.9.0-beta1.21055.5 - 2.0.76 + 2.0.64 2.1.1