/// <summary>
/// Indicates diagnostics messages from DiagnosticSourceEventSource should be included.
/// </summary>
- public const EventKeywords Messages = (EventKeywords)1;
+ public const EventKeywords Messages = (EventKeywords)0x1;
/// <summary>
/// Indicates that all events from all diagnostic sources should be forwarded to the EventSource using the 'Event' event.
/// </summary>
- public const EventKeywords Events = (EventKeywords)2;
+ public const EventKeywords Events = (EventKeywords)0x2;
+
+ // Some ETW logic does not support passing arguments to the EventProvider. To get around
+ // this in common cases, we define some keywords that basically stand in for particular common argumnents
+ // That way at least the common cases can be used by everyone (and it also compresses things).
+ // We start these keywords at 0x1000. See below for the values these keywords represent
+ // Because we want all keywords on to still mean 'dump everything by default' we have another keyword
+ // IgnoreShorcutKeywords which must be OFF in order for the shortcuts to work thus the all 1s keyword
+ // still means what you expect.
+ public const EventKeywords IgnoreShortCutKeywords = (EventKeywords)0x0800;
+ public const EventKeywords AspNetCoreHosting = (EventKeywords)0x1000;
+ public const EventKeywords EntityFrameworkCoreCommands = (EventKeywords)0x2000;
};
+ // Setting AspNetCoreHosting is like having this in the FilterAndPayloadSpecs string
+ // It turns on basic hostig events.
+ private readonly string AspNetCoreHostingKeywordValue =
+ "Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.BeginRequest@Activity1Start:-" +
+ "httpContext.Request.Method;" +
+ "httpContext.Request.Host;" +
+ "httpContext.Request.Path;" +
+ "httpContext.Request.QueryString" +
+ "\r\n" +
+ "Microsoft.AspNetCore/Microsoft.AspNetCore.Hosting.EndRequest@Activity1Stop:-";
+
+ // Setting EntityFrameworkCoreCommands is like having this in the FilterAndPayloadSpecs string
+ // It turns on basic SQL commands.
+ private readonly string EntityFrameworkCoreCommandsKeywordValue =
+ "Microsoft.EntityFrameworkCore/Microsoft.EntityFrameworkCore.BeforeExecuteCommand@Activity2Start:-" +
+ "Command.Connection.DataSource;" +
+ "Command.Connection.Database;" +
+ "Command.CommandText" +
+ "\r\n" +
+ "Microsoft.EntityFrameworkCore/Microsoft.EntityFrameworkCore.AfterExecuteCommand@Activity2Stop:-";
+
/// <summary>
/// Used to send ad-hoc diagnostics to humans.
/// </summary>
{
string filterAndPayloadSpecs;
command.Arguments.TryGetValue("FilterAndPayloadSpecs", out filterAndPayloadSpecs);
+
+ if (!IsEnabled(EventLevel.Informational, Keywords.IgnoreShortCutKeywords))
+ {
+ if (IsEnabled(EventLevel.Informational, Keywords.AspNetCoreHosting))
+ filterAndPayloadSpecs = NewLineSeparate(filterAndPayloadSpecs, AspNetCoreHostingKeywordValue);
+ if (IsEnabled(EventLevel.Informational, Keywords.EntityFrameworkCoreCommands))
+ filterAndPayloadSpecs = NewLineSeparate(filterAndPayloadSpecs, EntityFrameworkCoreCommandsKeywordValue);
+ }
FilterAndTransform.CreateFilterAndTransformList(ref _specs, filterAndPayloadSpecs, this);
}
else if (command.Command == EventCommand.Update || command.Command == EventCommand.Disable)
}
}
+ private static string NewLineSeparate(string str1, string str2)
+ {
+ if (string.IsNullOrEmpty(str1))
+ return str2;
+ return str1 + "\r\n" + str2;
+ }
+
#region debugger hooks
private volatile bool _false; // A value that is always false but the compiler does not know this.
{
listenerNameFilter = filterAndPayloadSpec.Substring(startIdx, slashIdx - startIdx);
- var atIdx = filterAndPayloadSpec.IndexOf('@', slashIdx+1, endEventNameIdx - slashIdx - 1);
+ var atIdx = filterAndPayloadSpec.IndexOf('@', slashIdx + 1, endEventNameIdx - slashIdx - 1);
if (0 <= atIdx)
{
activityName = filterAndPayloadSpec.Substring(atIdx + 1, endEventNameIdx - atIdx - 1);
Assert.Equal(0, eventSourceListener.EventCount);
eventSourceListener.Enable(
"TestActivitiesSource/TestActivity1Start@Activity1Start\r\n" +
- "TestActivitiesSource/TestActivity1Stop@Activity1Stop\r\n" +
+ "TestActivitiesSource/TestActivity1Stop@Activity1Stop\r\n" +
"TestActivitiesSource/TestActivity2Start@Activity2Start\r\n" +
- "TestActivitiesSource/TestActivity2Stop@Activity2Stop\r\n" +
+ "TestActivitiesSource/TestActivity2Stop@Activity2Stop\r\n" +
"TestActivitiesSource/TestEvent\r\n"
);
eventSourceListener.ResetEventCountAndLastEvent();
}
}
+
+ /// <summary>
+ /// Tests that keywords that define shortcuts work.
+ /// </summary>
+ [Fact]
+ public void TestShortcutKeywords()
+ {
+ using (var eventSourceListener = new TestDiagnosticSourceEventListener())
+ // These are look-alikes for the real ones.
+ using (var aspNetCoreSource = new DiagnosticListener("Microsoft.AspNetCore"))
+ using (var entityFrameworkCoreSource = new DiagnosticListener("Microsoft.EntityFrameworkCore"))
+ {
+ // These are from DiagnosticSourceEventListener.
+ var Messages = (EventKeywords)0x1;
+ var Events = (EventKeywords)0x2;
+ var AspNetCoreHosting = (EventKeywords)0x1000;
+ var EntityFrameworkCoreCommands = (EventKeywords)0x2000;
+
+ // Turn on listener using just the keywords
+ eventSourceListener.Enable(null, Messages | Events | AspNetCoreHosting | EntityFrameworkCoreCommands);
+
+ Assert.Equal(0, eventSourceListener.EventCount);
+
+ // Start a ASP.NET Request
+ aspNetCoreSource.Write("Microsoft.AspNetCore.Hosting.BeginRequest",
+ new
+ {
+ httpContext = new
+ {
+ Request = new
+ {
+ Method = "Get",
+ Host = "MyHost",
+ Path = "MyPath",
+ QueryString = "MyQuery"
+ }
+ }
+ });
+ // Check that the morphs work as expected.
+ Assert.Equal(1, eventSourceListener.EventCount); // Exactly one more event has been emitted.
+ Assert.Equal("Activity1Start", eventSourceListener.LastEvent.EventSourceEventName);
+ Assert.Equal("Microsoft.AspNetCore", eventSourceListener.LastEvent.SourceName);
+ Assert.Equal("Microsoft.AspNetCore.Hosting.BeginRequest", eventSourceListener.LastEvent.EventName);
+ Assert.True(4 <= eventSourceListener.LastEvent.Arguments.Count);
+ Debug.WriteLine("Arg Keys = " + string.Join(" ", eventSourceListener.LastEvent.Arguments.Keys));
+ Debug.WriteLine("Arg Values = " + string.Join(" ", eventSourceListener.LastEvent.Arguments.Values));
+ Assert.Equal("Get", eventSourceListener.LastEvent.Arguments["Method"]);
+ Assert.Equal("MyHost", eventSourceListener.LastEvent.Arguments["Host"]);
+ Assert.Equal("MyPath", eventSourceListener.LastEvent.Arguments["Path"]);
+ Assert.Equal("MyQuery", eventSourceListener.LastEvent.Arguments["QueryString"]);
+ eventSourceListener.ResetEventCountAndLastEvent();
+
+ // Start a SQL command
+ entityFrameworkCoreSource.Write("Microsoft.EntityFrameworkCore.BeforeExecuteCommand",
+ new
+ {
+ Command = new
+ {
+ Connection = new
+ {
+ DataSource = "MyDataSource",
+ Database = "MyDatabase",
+ },
+ CommandText = "MyCommand"
+ }
+ });
+ Assert.Equal(1, eventSourceListener.EventCount); // Exactly one more event has been emitted.
+ Assert.Equal("Activity2Start", eventSourceListener.LastEvent.EventSourceEventName);
+ Assert.Equal("Microsoft.EntityFrameworkCore", eventSourceListener.LastEvent.SourceName);
+ Assert.Equal("Microsoft.EntityFrameworkCore.BeforeExecuteCommand", eventSourceListener.LastEvent.EventName);
+ Assert.True(3 <= eventSourceListener.LastEvent.Arguments.Count);
+ Assert.Equal("MyDataSource", eventSourceListener.LastEvent.Arguments["DataSource"]);
+ Assert.Equal("MyDatabase", eventSourceListener.LastEvent.Arguments["Database"]);
+ Assert.Equal("MyCommand", eventSourceListener.LastEvent.Arguments["CommandText"]);
+ eventSourceListener.ResetEventCountAndLastEvent();
+
+ // Stop the SQL command
+ entityFrameworkCoreSource.Write("Microsoft.EntityFrameworkCore.AfterExecuteCommand", null);
+ Assert.Equal(1, eventSourceListener.EventCount); // Exactly one more event has been emitted.
+ Assert.Equal("Activity2Stop", eventSourceListener.LastEvent.EventSourceEventName);
+ Assert.Equal("Microsoft.EntityFrameworkCore", eventSourceListener.LastEvent.SourceName);
+ Assert.Equal("Microsoft.EntityFrameworkCore.AfterExecuteCommand", eventSourceListener.LastEvent.EventName);
+ eventSourceListener.ResetEventCountAndLastEvent();
+
+ // Stop the ASP.NET reqeust.
+ aspNetCoreSource.Write("Microsoft.AspNetCore.Hosting.EndRequest", null);
+ Assert.Equal(1, eventSourceListener.EventCount); // Exactly one more event has been emitted.
+ Assert.Equal("Activity1Stop", eventSourceListener.LastEvent.EventSourceEventName);
+ Assert.Equal("Microsoft.AspNetCore", eventSourceListener.LastEvent.SourceName);
+ Assert.Equal("Microsoft.AspNetCore.Hosting.EndRequest", eventSourceListener.LastEvent.EventName);
+ eventSourceListener.ResetEventCountAndLastEvent();
+ }
+ }
}
/****************************************************************************/
public DiagnosticSourceEvent LastEvent;
#if DEBUG
// Here just for debugging. Lets you see the last 3 events that were sent.
- public DiagnosticSourceEvent SecondLast;
+ public DiagnosticSourceEvent SecondLast;
public DiagnosticSourceEvent ThirdLast;
#endif
/// </summary>
public event Action<EventWrittenEventArgs> OtherEventWritten;
- public void Enable(string filterAndPayloadSpecs)
+ public void Enable(string filterAndPayloadSpecs, EventKeywords keywords = EventKeywords.All)
{
var args = new Dictionary<string, string>();
- args.Add("FilterAndPayloadSpecs", filterAndPayloadSpecs);
- EnableEvents(_diagnosticSourceEventSource, EventLevel.Verbose, EventKeywords.All, args);
+ if (filterAndPayloadSpecs != null)
+ args.Add("FilterAndPayloadSpecs", filterAndPayloadSpecs);
+ EnableEvents(_diagnosticSourceEventSource, EventLevel.Verbose, keywords, args);
}
public void Disable()
wroteEvent = true;
}
}
-
- if (eventData.EventName == "EventSourceMessage" && 0 < eventData.Payload.Count)
+
+ if (eventData.EventName == "EventSourceMessage" && 0 < eventData.Payload.Count)
System.Diagnostics.Debug.WriteLine("EventSourceMessage: " + eventData.Payload[0].ToString());
var otherEventWritten = OtherEventWritten;