Skip to main content
May 9, 2019
PC

Announcing TraceProcessor Preview 0.1.0

Process ETW traces in .NET.

Background

Event Tracing for Windows (ETW) is a powerful trace collection system built-in to the Windows operating system. Windows has deep integration with ETW, including data on system behavior all the way down to the kernel for events like context switches, memory allocation, process create and exit, and many more. The system-wide data available from ETW makes it a good fit for end-to-end performance analysis or other questions that require looking at the interaction between by many components throughout the system.

Unlike text logging, ETW provides structured events designed for automated data processing. Microsoft has built powerful tools on top of these structured events, including Windows Performance Analyzer (WPA), which provides a graphical interface for visualizing and exploring the trace data captured in a ETW trace file (.etl).

Inside Microsoft, we heavily use ETW traces to measure the performance of new builds of Windows. Given the volume of data produced the Windows engineering system, automated analysis is essential. For our automated trace analysis, we heavily use C# and .NET, so we created a package that provides a .NET API for accessing many kinds of ETW trace data. This technology is also used inside Windows Performance Analyzer to power several of its tables. We are happy to release a preview of this package that we use to analyze Windows so that you can use it to analyze your own applications and systems as well.

Getting Started

This package is available from NuGet with the following package ID:

Microsoft.Windows.EventTracing.Processing.All

After installing this package, the following console application lists all the process command lines in a trace:

using Microsoft.Windows.EventTracing; 
using Microsoft.Windows.EventTracing.Processes; 
using System; 

class Program 
{ 
    static void Main(string[] args) 
    { 
        if (args.Length != 1) 
        { 
            Console.Error.WriteLine("Usage: <trace.etl>"); 
            return; 
        } 

        using (ITraceProcessor trace = TraceProcessor.Create(args[0])) 
        { 
            IPendingResult<IProcessDataSource> pendingProcessData = trace.UseProcesses(); 
            trace.Process(); 
            IProcessDataSource processData = pendingProcessData.Result; 

            foreach (IProcess process in processData.Processes) 
            { 
                Console.WriteLine(process.CommandLine); 
            } 
        } 
    } 
}

The core interface is ITraceProcessor, and using this interface follows a pattern of first, tell the processor what data you want to use from a trace; second, process the trace; and finally, access the results. Telling the processor what kinds of data you want up front means you do not need to spend time processing large volumes of all possible kinds of trace data. Instead, TraceProcessor just does the work needed to provide the specific kinds of data you request.

Data Sources

Process information is just one of many kinds of data that can be stored in an ETW trace. Note that which data is in an .etl file depends on what providers were enabled when the trace was captured. The following list shows the kinds of trace data available from TraceProcessor:

Code

Description

Related WPA Items

trace.UseClassicEvents() Provides classic ETW events from a trace, which do not include schema information. Generic Events table (when Event Type is Classic or WPP)
trace.UseConnectedStandbyData() Provides data from a trace about the system entering and exiting connected standby. CS Summary table
trace.UseCpuIdleStates() Provides data from a trace about CPU C-states. CPU Idle States table (when Type is Actual)
trace.UseCpuSamplingData() Provides data from a trace about CPU usage based on periodic sampling of the instruction pointer. CPU Usage (Sampled) table
trace.UseCpuSchedulingData() Provides data from a trace about CPU thread scheduling, including context switches and ready thread events. CPU Usage (Precise) table
trace.UseDevicePowerData() Provides data from a trace about device D-states. Device DState table
trace.UseDirectXData() Provides data from a trace about DirectX activity. GPU Utilization table
traceUseDiskIOData() Provides data from a trace about Disk I/O activity. Disk Usage table
trace.UseEnergyEstimationData() Provides data from a trace about estimated per-process energy usage from Energy Estimation Engine. Energy Estimation Engine Summary (by Process) table
trace.UseEnergyMeterData() Provides data from a trace about measured energy usage from Energy Meter Interface (EMI). Energy Estimation Engine (by Emi) table
trace.UseFileIOData() Provides data from a trace about File I/O activity. File I/O table
trace.UseGenericEvents() Provides manifested and TraceLogging events from a trace. Generic Events table (when Event Type is Manifested or TraceLogging)
trace.UseHandles() Provides partial data from a trace about active kernel handles. Handles table
trace.UseHardFaults() Provides data from a trace about hard page faults. Hard Faults table
trace.UseHeapSnapshots() Provides data from a trace about process heap usage. Heap Snapshot table
trace.UseHypercalls() Provides data about Hyper-V hypercalls that occured during a trace.
trace.UseImageSections() Provides data from a trace about the sections of an image. Section Name column of the CPU Usage (Sampled) table
trace.UseInterruptHandlingData() Provides data from a trace about Interrupt Service Routine (ISR) and Deferred Procedure Call (DPC) activity. DPC/ISR table
trace.UseMarks() Provides the marks (labeled timestamps) from a trace. Marks table
trace.UseMemoryUtilizationData() Provides data from a trace about total system memory utilization. Memory Utilization table
trace.UseMetadata() Provides trace metadata available without further processing. System Configuration, Traces and General
trace.UsePlatformIdleStates() Provides data from a trace about the target and actual platform idle states of a system. Platform Idle State table
trace.UsePoolAllocations() Provides data from a trace about kernel pool memory usage. Pool Summary table
trace.UsePowerConfigurationData() Provides data from a trace about system power configuration. System Configuration, Power Settings
trace.UsePowerDependencyCoordinatorData() Provides data from a trace about active power dependency coordinator phases. Notification Phase Summary table
trace.UseProcesses() Provides data about processes active during a trace as well as their images and PDBs. Processes table
Images table
Symbols Hub
trace.UseProcessorCounters() Provides data from a trace about processor performance counter values from Processor Counter Monitor (PCM).
trace.UseProcessorFrequencyData() Provides data from a trace about the frequency at which processors ran. Processor Frequency table (when Type is Actual)
trace.UseProcessorProfileData() Provides data from a trace about the active processor power profile. Processor Profiles table
trace.UseProcessorParkingData() Provides data from a trace about which processors were parked or unparked. Processor Parking State table
trace.UseProcessorParkingLimits() Provides data from a trace about the maximum allowed number of unparked processors. Core Parking Cap State table
trace.UseProcessorQualityOfServiceData() Provides data from a trace about the quality of service level for each processor. Processor Qos Class table
trace.UseProcessorThrottlingData() Provides data from a trace about processor maximum frequency throttling. Processor Constraints table
trace.UseReadyBootData() Provides data from a trace about boot prefetching activity from Ready Boot. Ready Boot Events table
trace.UseReferenceSetData() Provides data from a trace about pages of virtual memory used by each process. Reference Set table
trace.UseRegionsOfInterest() Provides named regions of interest intervals from a trace as specified in an xml configuration file. Regions of Interest table
trace.UseRegistryData() Provides data about registry activity during a trace. Registry table
trace.UseResidentSetData() Provides data from a trace about the pages of virtual memory for each process that were resident in physical memory. Resident Set table
trace.UseRundownData() Provides data from a trace about intervals during which trace rundown data collection occurred. Shaded regions in the graph timeline
trace.UseScheduledTasks() Provides data about scheduled tasks that ran during a trace. Scheduled Tasks table
trace.UseServices() Provides data about services that were active or had their state captured during a trace. Services table
System Configuration, Services
trace.UseStacks() Provides data about stacks recorded during a trace. Stacks table
trace.UseStackEvents() Provides data about events associated with stacks recorded during a trace. Stacks table
trace.UseStackTags() Provides a mapper that groups stacks from a trace into stack tags as specified in an XML configuration file. Columns such as Stack Tag and Stack (Frame Tags)
trace.UseSymbols() Provides the ability to load symbols for a trace. Configure Symbol Paths
Load Symbols
trace.UseSyscalls() Provides data about syscalls that occurred during a trace. Syscalls table
trace.UseSystemMetadata() Provides general, system-wide metadata from a trace. System Configuration
trace.UseSystemPowerSourceData() Provides data from a trace about the active system power source (AC vs DC). System Power Source table
trace.UseSystemSleepData() Provides data from a trace about overall system power state. Power Transition table
trace.UseTargetCpuIdleStates() Provides data from a trace about target CPU C-states. CPU Idle States table (when Type is Target)
trace.UseTargetProcessorFrequencyData() Provides data from a trace about target processor frequencies. Processor Frequency table (when Type is Target)
trace.UseThreads() Provides data about threads active during a trace. Thread Lifetimes table
trace.UseTraceStatistics() Provides statistics about the events in a trace. System Configuration, Trace Statistics
trace.UseUtcData() Provides data from a trace about Microsoft telemetry activity using Universal Telemetry Client (UTC). Utc table
trace.UseWindowInFocus() Provides data from a trace about changes to the active UI window in focus. Window in Focus table
trace.UseWindowsTracePreprocessorEvents() Provides Windows software trace preprocessor (WPP) events from a trace. WPP Trace table
Generic Events table (when Event Type is WPP)
trace.UseWinINetData() Provides data from a trace about internet activity via Windows Internet (WinINet). Download Details table
trace.UseWorkingSetData() Provides data from a trace about pages of virtual memory that were in the working set for each process or kernel category. Virtual Memory Snapshots table

Extensibility

Many kinds of trace data have built-in support in TraceProcessor, but if you have your other providers that you would like to analyze (including your own custom providers), that data is also available from the trace live while processing occurs.

For example, here is a simple way to get the list of providers IDs in a trace:

HashSet<Guid> providerIds = new HashSet<Guid>(); 
trace.Use((e) => providerIds.Add(e.ProviderId)); 
trace.Process(); 

foreach (Guid providerId in providerIds) 
{ 
    Console.WriteLine(providerId); 
}

The following example shows a simplified custom data source:

CustomDataSource customDataSource = new CustomDataSource(); 
trace.Use(customDataSource); 
trace.Process(); 
Console.WriteLine(customDataSource.Count); 

… 

class CustomDataSource : IFilteredEventConsumer 
{ 
    public IReadOnlyList<Guid> ProviderIds { get; } = new Guid[] { new Guid("your provider ID") }; 

    public int Count { get; private set; } 


    public void Process(EventContext eventContext) 
    { 
        ++Count; 
    } 
}

Feedback

The documentation for TraceProcessor is currently limited to partial IntelliSense support, though we would like to add more reference documentation as well as samples. (Documentation is a work-in-progress).

This release is a preview to gauge interest, so if this package is useful to you, please let us know. We would also appreciate feedback on what areas we invest in further, such as:

  • Expanding IntelliSense documentation
  • Adding TraceProcessor API reference documentation to docs.microsoft.com
  • Adding samples
  • Removing the requirement for msis in the bin directory
  • Adding additional data to TraceProcessor that is currently present in WPA
  • Stabilizing on a GA/v1 release

For questions using this package, you can post on StackOverflow with the tag .net-traceprocessing, and feedback can also be sent via email to [email protected].