-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathDotnetTraceDataProcessor.cs
More file actions
119 lines (102 loc) · 4.23 KB
/
DotnetTraceDataProcessor.cs
File metadata and controls
119 lines (102 loc) · 4.23 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
112
113
114
115
116
117
118
119
// 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)
{
const string ReadPastEndOfStreamExceptionMessage = "Read past end of stream."; // Trace can be partially written but still have data - https://github.com/microsoft/perfview/issues/1637
var contentDictionary = new Dictionary<string, TraceEventProcessor>();
foreach (var path in this.filePaths)
{
var traceStartTime = DateTime.UtcNow.Date;
var tmpEtlx = Path.Combine(Path.GetTempPath(), Path.GetFileName(path) + ".etlx");
var traceEventProcessor = new TraceEventProcessor();
try
{
string traceLogPath = TraceLog.CreateFromEventPipeDataFile(path, tmpEtlx);
using (TraceLog traceLog = new TraceLog(traceLogPath))
{
TraceLogEventSource source = traceLog.Events.GetSource();
contentDictionary[path] = traceEventProcessor;
source.AllEvents += traceEventProcessor.ProcessTraceEvent;
source.Process();
this.dataSourceInfo = new DataSourceInfo(0, source.SessionDuration.Ticks * 100, source.SessionStartTime.ToUniversalTime());
}
}
catch (Exception e)
{
if (e.Message != ReadPastEndOfStreamExceptionMessage || !traceEventProcessor.HasTraceData())
{
throw;
}
}
finally
{
try
{
File.Delete(tmpEtlx);
}
catch (Exception)
{
}
}
}
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;
}
}
}