Benutzer:MovGP0/Performance/Event Tracing
Zur Navigation springen
Zur Suche springen
MovGP0 | Über mich | Hilfen | Artikel | Weblinks | Literatur | Zitate | Notizen | Programmierung | MSCert | Physik |
Event Tracing for Windows (ETW)[Bearbeiten | Quelltext bearbeiten]
Advantages[Bearbeiten | Quelltext bearbeiten]
Install[Bearbeiten | Quelltext bearbeiten].NET 4.5[Bearbeiten | Quelltext bearbeiten]Namespace: using System.Diagnostics.Tracing;
.NET 4.5 does not support Channels. Use the .NET 4.0[Bearbeiten | Quelltext bearbeiten]Namespace: using Microsoft.Diagnostics.Tracing;
NuGet Packages: Install-Package Microsoft.Diagnostics.Tracing.EventSource
Install-Package Microsoft.Diagnostics.Tracing.TraceEvent
Optional Packages[Bearbeiten | Quelltext bearbeiten]Install-Package EventSourceProxy # .NET 4.5
Install-Package EventSourceProxy.NuGet # .NET 4.0
Install-Package Microsoft.Diagnostics.Tracing.EventRegister # EventRegister.exe extracts Manifest files from binary
Defining Event[Bearbeiten | Quelltext bearbeiten]using System.Diagnostic.Tracing;
namespace EtlDemo
{
[EventSource(Name="Company-Department-Application-UniqueEventSourceName")]
internal sealed class Events : EventSource
{
// Singleton Instance to where the Events are written to.
public static readonly Lazy<Events> _log = new Lazy<Events>();
// private constructor
private Events ()
{
}
public static Log
{
get { return _log.Value; }
}
// define Tasks, Opcodes, and Keywords classes
// values can be Int32 or Int64
// use values that allow concatenation with binary-AND (&) operations
public class Keywords
{
public const EventKeywords General = (EventKeywords) 0x0001;
public const EventKeywords PrimeOutput = (EventKeywords) 0x0002;
}
public class Opcodes
{
public const EventOpcode Start = (EventOpcode) 0x0001;
public const EventOpcode Stop = (EventOpcode) 0x0002;
}
public class Tasks
{
public const EventTask Start = (EventTask) 0x0001;
public const EventTask Stop = (EventTask) 0x0002;
}
// IDs are needed to preserve the order of methods
internal const int ProcessingStartId = 1;
internal const int ProcessingFinishId = 2;
internal const int FoundPrimeId = 3;
[Event(ProcessingStartId, Level = EventLevel.Informational, Keywords = Keywords.General)]
public void ProcessingStart()
{
if(IsEnabled())
{
WriteEvent(ProcessingStartId);
}
}
[Event(ProcessingFinishId, Level = EventLevel.Informational, Keywords = Keywords.General)]
public void ProcessingFinish()
{
if(IsEnabled())
{
WriteEvent(ProcessingFinishId);
}
}
[Event(FoundPrimeId, Level = EventLevel.Informational, Keywords = Keywords.PrimeOutput, Message = "The prime number is {0}")]
public void FoundPrime(long primeNumber)
{
if(IsEnabled())
{
WriteEvent(FoundPrimeId, primeNumber);
}
}
// mark overloaded methods and generic methods that call an event method with [NonEventAttribute]
}
}
Usage: Events.Log.FoundPrime(5L);
Create ETW Event Listener[Bearbeiten | Quelltext bearbeiten]///<summary>Stores information about which event should get captured by the listener</summary>
class SourceConfig
{
public string Name { get; set; }
public EventLevel Level {get; set; }
public EventKeywords Keywords { get; set; }
}
abstract class BaseListener : EventListener
{
var configs = new List<SourceConfig>();
protected BaseListener(IEnumerable<SourceConfig> sources)
{
configs.AddRange(sources);
foreach(var source in configs)
{
var eventSource = FindEventSource(source.Name);
if(eventSource != null)
{
EnableEvents(eventSource, source.Level, source.Keywords);
}
}
}
private static EventSource FindEventSource(string name)
{
foreach(var eventSource in EventSource.GetSources())
{
if(string.Equals(eventSource.Name, name))
{
return eventSource;
}
}
return null;
}
///<summary>Find Event Sources that are created after the program has started</summary>
protected override void OnEventSourceCreated(EventSource evnetSource)
{
base.OnEventSourceCreated(eventSource);
foreach(var source in configs)
{
if(string.Equals(source.Name, eventSource.Name))
{
EnableEvents(eventSource, source.Level, source.Keywords);
}
}
}
///<summary>Gets called every time an event is written by the sources for the current listener</summary>
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
WriteEvent(eventData); // relay to abstract method
}
protected abstract void WriteEvent(EventWrittenEventArgs eventData;)
}
Console Listener[Bearbeiten | Quelltext bearbeiten]class ConsoleListener : BaseListener
{
public ConsoleListener(IEnumerable<SourceConfig> sources) : base(sources)
{
}
protected override void WriteEvent(EventWrittenEventArgs eventData)
{
string outputString;
switch(eventData.EventId)
{
case Events.ProcessingStartId:
outputString = string.Format("ProcessingStart ({0})", eventData.EventId);
break;
case Events.ProcessingFinishId:
outputString = string.Format("ProcessingFinish ({0})", eventData.EventId);
break;
case Events.FoundPrimeId:
outputString = string.Format("FoundPrime ({0}): {1}", eventData.EventId, (long)eventData.Payload[0]);
break;
default:
throw new InvalidOperationException("Unknown event");
}
Console.WriteLine(outputString);
}
}
File Listener[Bearbeiten | Quelltext bearbeiten]class ConsoleListener : BaseListener
{
private StreamWriter writer;
public ConsoleListener(IEnumerable<SourceConfig> sources) : base(sources)
{
writer = new StreamWriter(outputFile);
}
protected override void WriteEvent(EventWrittenEventArgs eventData)
{
var output = new StringBuilder();
var time = DateTime.UtcNow;
output.AppendFormat("{0:yyyy-MM-dd-HH:mm:ss.fff} - {1} - ", time, eventData.Level);
switch(eventData.EventId)
{
case Events.ProcessingStartId:
output.Append("ProcessingStart");
break;
case Events.ProcessingFinishId:
output.Append("ProcessingFinish");
break;
case Events.FoundPrimeId:
output.Append("FoundPrime - {0:No}", eventData.Payload[0]);
break;
default:
throw new InvalidOperationException("Unknown event");
}
writer.WriteLine(output.ToString());
}
public override void Dispose()
{
writer.Close();
base.Dispose();
}
}
Register ETW Events in EventLog[Bearbeiten | Quelltext bearbeiten]The build creates the binary (.dll) and an Manifest (.man). Those are registered using wevtutil: # run as admin
wevtutil install-manifest PROJECTNAME.man /mf:"PROJECTNAME.dll" /rf:"PROJECTNAME.dll"
Events should now be visible in Event Viewer. Semantic Logging Application Block (SLAB)[Bearbeiten | Quelltext bearbeiten]In-Process[Bearbeiten | Quelltext bearbeiten]Create a separate Project that is only referenced in Debug. public sealed class SemanticLoggingManager : IDisposable
{
private static readonly ObservableEventListener _listener = new ObservableEventListener();
public static IDisposable AppendListenerToEventSource([NotNull]EventSource eventSource)
{
listener.EnableEvents(eventSource, EventLevet.LogAlways, Keywords.All);
listener.LogToConsole();
// listener.LogToConsole(new JsonEventTextFormatter(EventTextFormatting.Indentend), colorMapper);
// listener.LogToConsole(new XmlEventTextFormatter(), colorMapper);
Disposable.CreateNew(() =>
{
listener.DisableEvents(eventSource);
// eventSource.Dispose();
});
}
public void Dispose()
{
_listener.Dispose();
}
}
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AppendListenerToEventSource();
}
private IDisposable _eventSourceListener;
[Conditional("DEBUG")]
private void AppendListenerToEventSource()
{
_eventSourceListener = SemanticLoggingManager.AppendListenerToEventSource(MyEventSource.Log);
}
public override OnExit(ExitEventArgs e)
{
DisposeListener();
base.OnExit(e);
}
[Conditional("DEBUG")]
private void DisposeListener()
{
_eventSourceListener.Dispose();
MyEventSource.Log.Dispose();
}
}
Out-Of-Process[Bearbeiten | Quelltext bearbeiten]
NuGet Libraries[Bearbeiten | Quelltext bearbeiten]
Tools[Bearbeiten | Quelltext bearbeiten]LogMan[Bearbeiten | Quelltext bearbeiten]logman -query providers > providers.txt # List all installed Providers
PerfView[Bearbeiten | Quelltext bearbeiten]
Windows Performance Recorder (WPR) and Windows Performance Analyzer (WPA)[Bearbeiten | Quelltext bearbeiten]
Guidelines[Bearbeiten | Quelltext bearbeiten]
Severity Level[Bearbeiten | Quelltext bearbeiten]
Defined Keywords[Bearbeiten | Quelltext bearbeiten]
Opcodes[Bearbeiten | Quelltext bearbeiten]
Dependency Injection[Bearbeiten | Quelltext bearbeiten]
Internetquellen[Bearbeiten | Quelltext bearbeiten]
|