in Nodejs/Product/LogConverter/LogParsing/LogConverter.cs [143:381]
public void Process()
{
string line;
uint methodToken = 0x06000001;
string filename = Path.Combine(Path.GetDirectoryName(_outputFile), Path.GetFileNameWithoutExtension(_outputFile));
Guid pdbSig;
uint pdbAge;
string dllPath = CreatePdbFile(out pdbSig, out pdbAge);
_allMethods.Clear();
int tickCount = 0;
using (var reader = new StreamReader(_filename))
{
var logCreationTime = DateTime.Now;
var logCreationTimeStamp = Stopwatch.GetTimestamp();
var log = TraceLog.Start(filename + ".etl", null);
try
{
EVENT_TRACE_HEADER header;
//////////////////////////////////////
header = NewHeader();
//header.TimeStamp = currentTimeStamp++;
header.Guid = TraceLog.ProcessEventGuid;
header.Version = 3;
header.Type = 3;
var processInfo = new ProcessInfo();
processInfo.UniqueProcessKey = 100;
processInfo.ProcessId = ProcessId;
processInfo.ParentId = 100;
log.Trace(header, processInfo, Encoding.ASCII.GetBytes("node.exe"), string.Empty);
//////////////////////////////////////
header = NewHeader();
header.Guid = TraceLog.ThreadEventGuid;
header.Version = 3;
header.Type = 3;
var threadInfo = new ThreadInfo();
threadInfo.ProcessId = ProcessId; // setup the thread as if it was a reasonable real thread
threadInfo.TThreadId = ThreadId;
threadInfo.Affinity = 0xFF;
threadInfo.Win32StartAddr = 0x8888;
threadInfo.UserStackBase = 0xF0000;
threadInfo.UserStackLimit = 0xF00200;
threadInfo.IoPriority = 2;
log.Trace(header, threadInfo);
//////////////////////////////////////
header = NewHeader();
//header.TimeStamp = currentTimeStamp++;
header.Guid = TraceLog.ImageEventGuid;
header.Version = 2;
header.Type = 3;
var imgLoad = new ImageLoad();
imgLoad.ImageBase = 0x10000;
imgLoad.ImageSize = 10000;
imgLoad.ProcessId = ProcessId;
log.Trace(header, imgLoad, dllPath);
//////////////////////////////////////
header = NewHeader();
header.Guid = TraceLog.LoaderEventGuid;
header.Version = 2;
header.Type = 33;
var moduleLoad = new ManagedModuleLoadUnload();
moduleLoad.AssemblyID = 1;
moduleLoad.ModuleID = JitModuleId;
log.Trace(header, moduleLoad, dllPath, dllPath,
(ushort)1, // clr instance ID
pdbSig, // pdb sig
pdbAge, // pdb age
dllPath.Substring(0, dllPath.Length - 4) + ".pdb", // path to PDB,
Guid.Empty,
0,
string.Empty
);
while ((line = reader.ReadLine()) != null)
{
var records = SplitRecord(line);
if (records.Length == 0)
{
continue;
}
switch (records[0])
{
case "shared-library":
if (records.Length < 4)
{
continue; // missing info?
}
break;
case "profiler":
break;
case "code-creation":
int shift = (_nodeVersion >= v012 ? 1 : 0);
if (records.Length < shift + 5)
{
continue; // missing info?
}
var startAddr = ParseAddress(records[shift + 2]);
header = NewMethodEventHeader();
var methodLoad = new MethodLoadUnload();
methodLoad.MethodID = methodToken;
methodLoad.ModuleID = JitModuleId;
methodLoad.MethodStartAddress = startAddr;
methodLoad.MethodSize = (uint)ParseAddress(records[shift + 3]);
methodLoad.MethodToken = methodToken;
methodLoad.MethodFlags = 8;
var funcInfo = ExtractNamespaceAndMethodName(records[shift + 4], records[1]);
string functionName = funcInfo.Function;
if (funcInfo.IsRecompilation)
{
functionName += " (recompiled)";
}
_codeAddresses[new AddressRange(startAddr, methodLoad.MethodSize)] = IsMyCode(funcInfo);
log.Trace(header, methodLoad, funcInfo.Namespace, functionName, string.Empty /* signature*/);
methodToken++;
break;
case "tick":
if (records.Length < 5)
{
continue;
}
var addr = ParseAddress(records[1]);
header = NewTickRecord();
var profileInfo = new SampledProfile();
profileInfo.InstructionPointer = (uint)addr;
profileInfo.ThreadId = ThreadId;
profileInfo.Count = 1;
log.Trace(header, profileInfo);
if (records.Length > 2)
{
header = NewStackWalkRecord();
var sw = new StackWalk();
// this timestamp is independent from the timestamp in our header,
// and this one is not filled in for us by ETW. So we need to fill
// it in here.
sw.TimeStamp = (ulong)Stopwatch.GetTimestamp();
sw.Process = ProcessId;
sw.Thread = ThreadId;
// tick, ip, esp, ? [always zero], ?, always zero[?], stack IPs...
const int nonStackFrames = 6; // count of records, including IP, which aren't stack addresses.
List<object> args = new List<object>();
args.Add(sw);
var ipAddr = ParseAddress(records[1]);
if (ipAddr != 0 && ShouldIncludeCode(ipAddr))
{
args.Add(ipAddr);
}
for (int i = nonStackFrames; i < records.Length; i++)
{
var callerAddr = ParseAddress(records[i]);
if (callerAddr != 0 && ShouldIncludeCode(callerAddr))
{
args.Add(callerAddr);
}
}
if ((records.Length - nonStackFrames) == 0)
{
// idle CPU time
sw.Process = 0;
}
tickCount++;
log.Trace(header, args.ToArray());
}
break;
default:
Console.WriteLine("Unknown record type: {0}", line);
break;
}
}
header = NewHeader();
header.Guid = TraceLog.ProcessEventGuid;
header.Version = 3;
header.Type = 4; // DCEnd
processInfo = new ProcessInfo();
processInfo.UniqueProcessKey = 100;
processInfo.ProcessId = ProcessId;
processInfo.ParentId = 100;
log.Trace(header, processInfo, Encoding.ASCII.GetBytes("node.exe"), string.Empty);
}
finally
{
log.Stop();
}
RelogTrace(_executionTime.Value, tickCount, filename + ".etl");
}
// save the VSPX file
using (var stream = new FileStream(filename + ".vspx", FileMode.Create, FileAccess.ReadWrite, FileShare.None))
{
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, false))
{
var entry = archive.CreateEntry("VSProfilingData\\" + Path.GetFileName(filename) + ".etl");
using (FileStream etlStream = new FileStream(filename + ".etl", FileMode.Open, FileAccess.Read))
{
using (var entryStream = entry.Open())
{
etlStream.CopyTo(entryStream);
}
}
}
}
}