forked from gavz/ETWSplitter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
154 lines (121 loc) · 5.16 KB
/
Program.cs
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// So I had this 4GB ETL trace that I wanted to open in Message Analyzer.
// Message Analyzer couldn't handle it. Crapped out. Because of a hard-coded
// limit on the size of .NET dictionary or something like that. It's 2017...
// a 4GB file isn't that big anymore. I should be able to open a 4GB file when
// I have 32GB of free RAM.
//
//
// This code uses the Microsoft.Diagnostics.Tracing.TraceEvent which is downloadable as a NuGet package.
// This code itself is scrap. It's the TraceEvent library where the magic really is.
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Diagnostics;
using Microsoft.Diagnostics.Tracing;
namespace ETWSplitter
{
class ETWSplitter
{
static void Main(string[] args)
{
if (args.Count() < 3 || args.Count() > 4)
{
Console.WriteLine("\nUsage: ETWSplitter.exe <InputFile.etl> <OutputFile.etl> <#_of_Files> [compress]\n");
return;
}
string inputFileName = args[0];
string outFileName = args[1];
if (!File.Exists(inputFileName))
{
Console.WriteLine("ERROR: Input file {0} was not found!", inputFileName);
return;
}
if (inputFileName.Equals(outFileName, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("ERROR: Input file and output file have the same name!");
return;
}
if (outFileName.EndsWith(".etl", StringComparison.OrdinalIgnoreCase))
{
outFileName = outFileName.Remove(outFileName.Length - 4);
}
if (!int.TryParse(args[2], out int numberOfFiles))
{
Console.WriteLine("ERROR: {0} is not an integer!", args[2]);
return;
}
if (numberOfFiles < 2 || numberOfFiles > 1024)
{
Console.WriteLine("ERROR: {0} is outside of range!", numberOfFiles);
return;
}
bool compress = false;
if (args.Count() > 3)
{
if (args[3].StartsWith("c", StringComparison.OrdinalIgnoreCase))
{
compress = true;
Console.WriteLine("Compression enabled.");
}
}
if (compress == false)
{
Console.WriteLine("Compression disabled.");
}
Int64 totalNumberOfEvents = 0;
using (var etwReader = new ETWTraceEventSource(inputFileName))
{
etwReader.AllEvents += delegate (TraceEvent data)
{
Interlocked.Increment(ref totalNumberOfEvents);
};
etwReader.Process();
}
if (totalNumberOfEvents < 2)
{
Console.WriteLine("ERROR: Did not detect any ETW events in the input file!");
return;
}
Console.WriteLine("{0} total events found.", totalNumberOfEvents);
Int64 numberOfEventsPerFile = totalNumberOfEvents / numberOfFiles;
Console.WriteLine("Writing {0} files with {1} events each...", numberOfFiles, numberOfEventsPerFile);
Int64 totalEventsWritten = 0;
for (int fileNum = 0; fileNum < numberOfFiles; fileNum++)
{
Stopwatch fileTimer = new Stopwatch();
string splitFileName = outFileName + fileNum + ".etl";
Int64 thisFileStartIndex = numberOfEventsPerFile * fileNum;
Int64 thisFileEventsWritten = 0;
Int64 currentEvent = 0;
fileTimer.Start();
Console.Write("{0}...", splitFileName);
using (var relogger = new ETWReloggerTraceEventSource(inputFileName, splitFileName))
{
if (compress)
{
relogger.OutputUsesCompressedFormat = true;
}
else
{
relogger.OutputUsesCompressedFormat = false;
}
relogger.AllEvents += delegate (TraceEvent data)
{
if ((currentEvent >= thisFileStartIndex) && (currentEvent < (thisFileStartIndex + numberOfEventsPerFile)))
{
relogger.WriteEvent(data);
Interlocked.Increment(ref thisFileEventsWritten);
Interlocked.Increment(ref totalEventsWritten);
}
Interlocked.Increment(ref currentEvent);
};
relogger.Process();
};
fileTimer.Stop();
TimeSpan timeElapsed = fileTimer.Elapsed;
Console.WriteLine(" Done in {0:00}h:{1:00}m:{2:00}s. Wrote: {3} Filesize: {4}MB", timeElapsed.Hours, timeElapsed.Minutes, timeElapsed.Seconds, thisFileEventsWritten, (new FileInfo(splitFileName).Length) / 1024 / 1024);
}
}
}
}