Skip to content

Instantly share code, notes, and snippets.

@andy-uq
Created June 1, 2017 03:58
Show Gist options
  • Save andy-uq/6e7228f10e409bd87adbff2665a103da to your computer and use it in GitHub Desktop.
Save andy-uq/6e7228f10e409bd87adbff2665a103da to your computer and use it in GitHub Desktop.
Reads ETW events from Microsoft.Extensions.Logging
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net462</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="1.0.41" />
</ItemGroup>
</Project>
using System;
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Text;
using Microsoft.Diagnostics.Tracing.Parsers.MicrosoftExtensionsLogging;
using Address = System.UInt64;
#pragma warning disable 1591 // disable warnings on XML comments not being present
// This code was automatically generated by the TraceParserGen tool, which converts
// an ETW event manifest into strongly typed C# classes.
namespace Microsoft.Diagnostics.Tracing.Parsers
{
[GeneratedCode("traceparsergen", "2.0")]
public sealed class MicrosoftExtensionsLoggingTraceEventParser : TraceEventParser
{
public enum Keywords : long
{
Meta = 0x1,
Message = 0x2,
FormattedMessage = 0x4,
JsonMessage = 0x8,
}
public static string ProviderName = "Microsoft-Extensions-Logging";
public static Guid ProviderGuid = new Guid(0x3ac73b97, unchecked((short) 0xaf73), 0x50e9, 0x08, 0x22, 0x5d, 0xa4, 0x36, 0x79, 0x20, 0xd0);
public MicrosoftExtensionsLoggingTraceEventParser(TraceEventSource source) : base(source)
{
}
public event Action<ActivityStartArgs> ActivityStart
{
add => source.RegisterEventTemplate(ActivityStartTemplate(value));
remove => source.UnregisterEventTemplate(value, 3, ProviderGuid);
}
public event Action<ActivityStopArgs> ActivityStop
{
add => source.RegisterEventTemplate(ActivityStopTemplate(value));
remove => source.UnregisterEventTemplate(value, 4, ProviderGuid);
}
public event Action<ActivityJsonStartArgs> ActivityJsonStart
{
add => source.RegisterEventTemplate(ActivityJsonStartTemplate(value));
remove => source.UnregisterEventTemplate(value, 6, ProviderGuid);
}
public event Action<ActivityJsonStopArgs> ActivityJsonStop
{
add => source.RegisterEventTemplate(ActivityJsonStopTemplate(value));
remove => source.UnregisterEventTemplate(value, 7, ProviderGuid);
}
public event Action<EventSourceMessageArgs> EventSourceMessage
{
add => source.RegisterEventTemplate(EventSourceMessageTemplate(value));
remove => source.UnregisterEventTemplate(value, 0, ProviderGuid);
}
public event Action<FormattedMessageArgs> FormattedMessage
{
add => source.RegisterEventTemplate(FormattedMessageTemplate(value));
remove => source.UnregisterEventTemplate(value, 1, ProviderGuid);
}
public event Action<MessageJsonArgs> MessageJson
{
add => source.RegisterEventTemplate(MessageJsonTemplate(value));
remove => source.UnregisterEventTemplate(value, 5, ProviderGuid);
}
#region private
protected override string GetProviderName()
{
return ProviderName;
}
private static ActivityStartArgs ActivityStartTemplate(Action<ActivityStartArgs> action)
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new ActivityStartArgs(action, 3, 65531, "Activity", Guid.Empty, 0, "", ProviderGuid, ProviderName);
}
private static ActivityStopArgs ActivityStopTemplate(Action<ActivityStopArgs> action)
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new ActivityStopArgs(action, 4, 65531, "Activity", Guid.Empty, 0, "", ProviderGuid, ProviderName);
}
private static ActivityJsonStartArgs ActivityJsonStartTemplate(Action<ActivityJsonStartArgs> action)
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new ActivityJsonStartArgs(action, 6, 65528, "ActivityJson", Guid.Empty, 0, "", ProviderGuid, ProviderName);
}
private static ActivityJsonStopArgs ActivityJsonStopTemplate(Action<ActivityJsonStopArgs> action)
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new ActivityJsonStopArgs(action, 7, 65528, "ActivityJson", Guid.Empty, 0, "", ProviderGuid, ProviderName);
}
private static EventSourceMessageArgs EventSourceMessageTemplate(Action<EventSourceMessageArgs> action)
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new EventSourceMessageArgs(action, 0, 65534, "EventSourceMessage", Guid.Empty, 0, "", ProviderGuid, ProviderName);
}
private static FormattedMessageArgs FormattedMessageTemplate(Action<FormattedMessageArgs> action)
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new FormattedMessageArgs(action, 1, 65533, "FormattedMessage", Guid.Empty, 0, "", ProviderGuid, ProviderName);
}
private static MessageJsonArgs MessageJsonTemplate(Action<MessageJsonArgs> action)
{
// action, eventid, taskid, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName
return new MessageJsonArgs(action, 5, 65529, "MessageJson", Guid.Empty, 0, "", ProviderGuid, ProviderName);
}
private static volatile TraceEvent[] s_templates;
protected override void EnumerateTemplates(Func<string, string, EventFilterResponse> eventsToObserve, Action<TraceEvent> callback)
{
if (s_templates == null)
{
var templates = new TraceEvent[7];
templates[0] = EventSourceMessageTemplate(null);
templates[1] = FormattedMessageTemplate(null);
templates[2] = ActivityStartTemplate(null);
templates[3] = ActivityStartTemplate(null);
templates[4] = MessageJsonTemplate(null);
templates[5] = ActivityJsonStartTemplate(null);
templates[6] = ActivityJsonStartTemplate(null);
s_templates = templates;
}
foreach (var template in s_templates)
if (eventsToObserve == null || eventsToObserve(template.ProviderName, template.EventName) == EventFilterResponse.AcceptEvent)
callback(template);
}
#endregion
}
}
namespace Microsoft.Diagnostics.Tracing.Parsers.MicrosoftExtensionsLogging
{
public sealed class ActivityStartArgs : TraceEvent
{
public int ID => GetInt32At(0);
public int FactoryID => GetInt32At(4);
public string LoggerName => GetUnicodeStringAt(8);
#region Private
internal ActivityStartArgs(Action<ActivityStartArgs> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected override void Dispatch()
{
m_target(this);
}
protected override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != SkipUnicodeString(8)));
Debug.Assert(!(Version > 0 && EventDataLength < SkipUnicodeString(8)));
}
protected override Delegate Target
{
get => m_target;
set => m_target = (Action<ActivityStartArgs>) value;
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "ID", ID);
XmlAttrib(sb, "FactoryID", FactoryID);
XmlAttrib(sb, "LoggerName", LoggerName);
sb.Append("/>");
return sb;
}
public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new[] {"ID", "FactoryID", "LoggerName"};
return payloadNames;
}
}
public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return ID;
case 1:
return FactoryID;
case 2:
return LoggerName;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}
private event Action<ActivityStartArgs> m_target;
#endregion
}
public sealed class ActivityStopArgs : TraceEvent
{
public int ID => GetInt32At(0);
public int FactoryID => GetInt32At(4);
public string LoggerName => GetUnicodeStringAt(8);
#region Private
internal ActivityStopArgs(Action<ActivityStopArgs> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected override void Dispatch()
{
m_target(this);
}
protected override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != SkipUnicodeString(8)));
Debug.Assert(!(Version > 0 && EventDataLength < SkipUnicodeString(8)));
}
protected override Delegate Target
{
get => m_target;
set => m_target = (Action<ActivityStopArgs>) value;
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "ID", ID);
XmlAttrib(sb, "FactoryID", FactoryID);
XmlAttrib(sb, "LoggerName", LoggerName);
sb.Append("/>");
return sb;
}
public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new[] {"ID", "FactoryID", "LoggerName"};
return payloadNames;
}
}
public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return ID;
case 1:
return FactoryID;
case 2:
return LoggerName;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}
private event Action<ActivityStopArgs> m_target;
#endregion
}
public sealed class ActivityJsonStartArgs : TraceEvent
{
public int ID => GetInt32At(0);
public int FactoryID => GetInt32At(4);
public string LoggerName => GetUnicodeStringAt(8);
public string ArgumentsJson => GetUnicodeStringAt(SkipUnicodeString(8));
#region Private
internal ActivityJsonStartArgs(Action<ActivityJsonStartArgs> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected override void Dispatch()
{
m_target(this);
}
protected override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != SkipUnicodeString(SkipUnicodeString(8))));
Debug.Assert(!(Version > 0 && EventDataLength < SkipUnicodeString(SkipUnicodeString(8))));
}
protected override Delegate Target
{
get => m_target;
set => m_target = (Action<ActivityJsonStartArgs>) value;
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "ID", ID);
XmlAttrib(sb, "FactoryID", FactoryID);
XmlAttrib(sb, "LoggerName", LoggerName);
XmlAttrib(sb, "ArgumentsJson", ArgumentsJson);
sb.Append("/>");
return sb;
}
public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new[] {"ID", "FactoryID", "LoggerName", "ArgumentsJson"};
return payloadNames;
}
}
public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return ID;
case 1:
return FactoryID;
case 2:
return LoggerName;
case 3:
return ArgumentsJson;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}
private event Action<ActivityJsonStartArgs> m_target;
#endregion
}
public sealed class ActivityJsonStopArgs : TraceEvent
{
public int ID => GetInt32At(0);
public int FactoryID => GetInt32At(4);
public string LoggerName => GetUnicodeStringAt(8);
#region Private
internal ActivityJsonStopArgs(Action<ActivityJsonStopArgs> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected override void Dispatch()
{
m_target(this);
}
protected override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != SkipUnicodeString(8)));
Debug.Assert(!(Version > 0 && EventDataLength < SkipUnicodeString(8)));
}
protected override Delegate Target
{
get => m_target;
set => m_target = (Action<ActivityJsonStopArgs>) value;
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "ID", ID);
XmlAttrib(sb, "FactoryID", FactoryID);
XmlAttrib(sb, "LoggerName", LoggerName);
sb.Append("/>");
return sb;
}
public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new[] {"ID", "FactoryID", "LoggerName"};
return payloadNames;
}
}
public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return ID;
case 1:
return FactoryID;
case 2:
return LoggerName;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}
private event Action<ActivityJsonStopArgs> m_target;
#endregion
}
public sealed class EventSourceMessageArgs : TraceEvent
{
public string message => GetUnicodeStringAt(0);
#region Private
internal EventSourceMessageArgs(Action<EventSourceMessageArgs> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected override void Dispatch()
{
m_target(this);
}
protected override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != SkipUnicodeString(0)));
Debug.Assert(!(Version > 0 && EventDataLength < SkipUnicodeString(0)));
}
protected override Delegate Target
{
get => m_target;
set => m_target = (Action<EventSourceMessageArgs>) value;
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "message", message);
sb.Append("/>");
return sb;
}
public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new[] {"message"};
return payloadNames;
}
}
public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return message;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}
private event Action<EventSourceMessageArgs> m_target;
#endregion
}
public sealed class FormattedMessageArgs : TraceEvent
{
public LogLevel Level => (LogLevel) GetInt32At(0);
public int FactoryID => GetInt32At(4);
public string LoggerName => GetUnicodeStringAt(8);
public string EventId => GetUnicodeStringAt(SkipUnicodeString(8));
public string FormattedMessage => GetUnicodeStringAt(SkipUnicodeString(SkipUnicodeString(8)));
#region Private
internal FormattedMessageArgs(Action<FormattedMessageArgs> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected override void Dispatch()
{
m_target(this);
}
protected override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != SkipUnicodeString(SkipUnicodeString(SkipUnicodeString(8)))));
Debug.Assert(!(Version > 0 && EventDataLength < SkipUnicodeString(SkipUnicodeString(SkipUnicodeString(8)))));
}
protected override Delegate Target
{
get => m_target;
set => m_target = (Action<FormattedMessageArgs>) value;
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "Level", Level);
XmlAttrib(sb, "FactoryID", FactoryID);
XmlAttrib(sb, "LoggerName", LoggerName);
XmlAttrib(sb, "EventId", EventId);
XmlAttrib(sb, "FormattedMessage", FormattedMessage);
sb.Append("/>");
return sb;
}
public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new[] {"Level", "FactoryID", "LoggerName", "EventId", "FormattedMessage"};
return payloadNames;
}
}
public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return Level;
case 1:
return FactoryID;
case 2:
return LoggerName;
case 3:
return EventId;
case 4:
return FormattedMessage;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}
private event Action<FormattedMessageArgs> m_target;
#endregion
}
public sealed class MessageJsonArgs : TraceEvent
{
public LogLevel Level => (LogLevel) GetInt32At(0);
public int FactoryID => GetInt32At(4);
public string LoggerName => GetUnicodeStringAt(8);
public string EventId => GetUnicodeStringAt(SkipUnicodeString(8));
public string ExceptionJson => GetUnicodeStringAt(SkipUnicodeString(SkipUnicodeString(8)));
public string ArgumentsJson => GetUnicodeStringAt(SkipUnicodeString(SkipUnicodeString(SkipUnicodeString(8))));
#region Private
internal MessageJsonArgs(Action<MessageJsonArgs> target, int eventID, int task, string taskName, Guid taskGuid, int opcode, string opcodeName, Guid providerGuid, string providerName)
: base(eventID, task, taskName, taskGuid, opcode, opcodeName, providerGuid, providerName)
{
m_target = target;
}
protected override void Dispatch()
{
m_target(this);
}
protected override void Validate()
{
Debug.Assert(!(Version == 0 && EventDataLength != SkipUnicodeString(SkipUnicodeString(SkipUnicodeString(SkipUnicodeString(8))))));
Debug.Assert(!(Version > 0 && EventDataLength < SkipUnicodeString(SkipUnicodeString(SkipUnicodeString(SkipUnicodeString(8))))));
}
protected override Delegate Target
{
get => m_target;
set => m_target = (Action<MessageJsonArgs>) value;
}
public override StringBuilder ToXml(StringBuilder sb)
{
Prefix(sb);
XmlAttrib(sb, "Level", Level);
XmlAttrib(sb, "FactoryID", FactoryID);
XmlAttrib(sb, "LoggerName", LoggerName);
XmlAttrib(sb, "EventId", EventId);
XmlAttrib(sb, "ExceptionJson", ExceptionJson);
XmlAttrib(sb, "ArgumentsJson", ArgumentsJson);
sb.Append("/>");
return sb;
}
public override string[] PayloadNames
{
get
{
if (payloadNames == null)
payloadNames = new[] {"Level", "FactoryID", "LoggerName", "EventId", "ExceptionJson", "ArgumentsJson"};
return payloadNames;
}
}
public override object PayloadValue(int index)
{
switch (index)
{
case 0:
return Level;
case 1:
return FactoryID;
case 2:
return LoggerName;
case 3:
return EventId;
case 4:
return ExceptionJson;
case 5:
return ArgumentsJson;
default:
Debug.Assert(false, "Bad field index");
return null;
}
}
private event Action<MessageJsonArgs> m_target;
#endregion
}
public enum LogLevel
{
Trace = 0x0,
Debug = 0x1,
Information = 0x2,
Warning = 0x3,
Error = 0x4,
Critical = 0x5,
None = 0x6
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session;
namespace reader
{
public static class Program
{
private static TraceEventSession _session;
public static void Main()
{
_session = new TraceEventSession("LogReader");
_session.EnableProvider(
MicrosoftExtensionsLoggingTraceEventParser.ProviderGuid,
TraceEventLevel.Verbose,
(ulong )MicrosoftExtensionsLoggingTraceEventParser.Keywords.FormattedMessage);
// The ETW collection thread starts receiving all events immediately, but we filter on the Process Id
var processingTask = Task.Factory.StartNew(StartProcessingEvents, TaskCreationOptions.LongRunning);
Console.CancelKeyPress += (sender, e) =>
{
Console.WriteLine("\nConsole being killed, tidying up\n");
_session.Dispose();
Console.WriteLine();
};
while (true)
{
var cki = Console.ReadKey();
if (cki.Key == ConsoleKey.Enter ||
cki.Key == ConsoleKey.Escape ||
cki.Key == ConsoleKey.Q)
{
break;
}
}
// Flush the session before we finish, so that we get all the events possible
_session.Flush();
// wait a little while for all events to come through (Flush() doesn't seem to do this?)
Thread.Sleep(3000);
// Now kill the session completely
_session.Dispose();
var completed = processingTask.Wait(millisecondsTimeout: 3000);
if (!completed)
Console.WriteLine("\nWait timed out, the Processing Task is still running");
Console.WriteLine();
}
private static void StartProcessingEvents()
{
var parser = new MicrosoftExtensionsLoggingTraceEventParser(_session.Source);
parser.FormattedMessage += e => Console.WriteLine(e.FormattedMessage);
_session.Source.Process();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment