-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathDotnetTraceDataProcessor.cs
More file actions
111 lines (92 loc) · 4.37 KB
/
DotnetTraceDataProcessor.cs
File metadata and controls
111 lines (92 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using DotNetEventPipe.Tables;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Performance.SDK.Processing;
using Microsoft.Diagnostics.Tracing.EventPipe;
using Microsoft.Diagnostics.Tracing.Etlx;
namespace DotNetEventPipe
{
public sealed class DotnetTraceDataProcessor
: CustomDataProcessor
{
private readonly string[] filePaths;
private IReadOnlyDictionary<string, TraceEventProcessor> fileContent;
private DataSourceInfo dataSourceInfo;
public DotnetTraceDataProcessor(
string[] filePaths,
ProcessorOptions options,
IApplicationEnvironment applicationEnvironment,
IProcessorEnvironment processorEnvironment)
: base(options, applicationEnvironment, processorEnvironment)
{
//
// Assign the files array to a readonly backing field.
//
this.filePaths = filePaths;
}
public override DataSourceInfo GetDataSourceInfo()
{
// The DataSourceInfo is used to tell analzyer the time range of the data(if applicable) and any other relevant data for rendering / synchronizing.
return this.dataSourceInfo;
}
protected override Task ProcessAsyncCore(
IProgress<int> progress,
CancellationToken cancellationToken)
{
var contentDictionary = new Dictionary<string, TraceEventProcessor>();
foreach (var path in this.filePaths)
{
var traceStartTime = DateTime.UtcNow.Date;
// EventPipeEventSource doesn't expose the callstacks - https://github.com/Microsoft/perfview/blob/main/src/TraceEvent/EventPipe/EventPipeFormat.md
// But currently it's SessionDuration, SessionStartTime are correct
// Can remove when when this is released - https://github.com/microsoft/perfview/pull/1635
var dotnetFileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
using (var traceSource = new EventPipeEventSource(dotnetFileStream))
{
traceSource.Process();
this.dataSourceInfo = new DataSourceInfo(0, traceSource.SessionDuration.Ticks * 100, traceSource.SessionStartTime.ToUniversalTime());
}
var tmpEtlx = Path.Combine(Path.GetTempPath(), Path.GetFileName(path) + ".etlx");
string traceLogPath = TraceLog.CreateFromEventPipeDataFile(path, tmpEtlx);
using (TraceLog traceLog = new TraceLog(traceLogPath))
{
TraceLogEventSource source = traceLog.Events.GetSource();
var traceEventProcessor = new TraceEventProcessor();
contentDictionary[path] = traceEventProcessor;
source.AllEvents += traceEventProcessor.ProcessTraceEvent;
source.Process();
// Below will work when this is released - https://github.com/microsoft/perfview/pull/1635
//this.dataSourceInfo = new DataSourceInfo(0, source.SessionDuration.Ticks * 100, source.SessionStartTime.ToUniversalTime());
}
File.Delete(tmpEtlx);
}
this.fileContent = new ReadOnlyDictionary<string, TraceEventProcessor>(contentDictionary);
return Task.CompletedTask;
}
protected override void BuildTableCore(
TableDescriptor tableDescriptor,
ITableBuilder tableBuilder)
{
//
// Instantiate the table, and pass the tableBuilder to it.
//
var table = this.InstantiateTable(tableDescriptor.Type);
table.Build(tableBuilder);
}
private TraceEventTableBase InstantiateTable(Type tableType)
{
//
// This private method is added to activate the given table type and pass in the file content.
//
var instance = Activator.CreateInstance(tableType, new[] { this.fileContent, });
return (TraceEventTableBase)instance;
}
}
}