private static void Convert(MSBuildLogFileFormat format, string fileToConvertFilePath, string outputFilePath, bool includeAllTasks) { switch (format) { case MSBuildLogFileFormat.Chromium: var buildEnumerator = new BinlogEnumerable(fileToConvertFilePath); ChromiumMSBuildLogWriter.WriteTo(buildEnumerator, outputFilePath, includeAllTasks); break; case MSBuildLogFileFormat.Speedscope: var build = Serialization.Read(fileToConvertFilePath); SpeedscopeMSBuildLogWriter.WriteTo(build, outputFilePath, includeAllTasks); break; default: // we should never get here throw new ArgumentException($"Invalid MSBuildLogFileFormat: {format}"); } }
internal static void WriteTo(BinlogEnumerable buildEnumerator, string outputFilePath, bool includeAllTasks) { var firstObservedTime = DateTime.MinValue.Ticks; var msbuildStartEvents = new Dictionary <int, TaskStartedEventArgs>(); using var fileStrem = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); using var jsonWriter = new Utf8JsonWriter(fileStrem, jsonWriterOptions); jsonWriter.WriteStartArray(); foreach (var buildEventArgs in buildEnumerator) { var ts = (uint)((buildEventArgs.Timestamp.Ticks - firstObservedTime) / TicksPerMicrosecond); switch (buildEventArgs) { case BuildStartedEventArgs buildStartedEventArgs: firstObservedTime = buildStartedEventArgs.Timestamp.Ticks; break; case ProjectStartedEventArgs projectStartedEventArgs: { writeEvent( jsonWriter: jsonWriter, name: $"Project \"{projectStartedEventArgs.ProjectFile}\" ({projectStartedEventArgs.TargetNames}) ({projectStartedEventArgs.BuildEventContext.ProjectInstanceId})", ts: ts, ph: ChromiumTraceEventPhases.DurationBegin, tid: projectStartedEventArgs.BuildEventContext.ProjectInstanceId, pid: projectStartedEventArgs.BuildEventContext.NodeId.ToString()); if (msbuildStartEvents.TryGetValue(projectStartedEventArgs.ParentProjectBuildEventContext.ProjectInstanceId, out var callingMsbuildTaskInvocation)) { writeEvent( jsonWriter: jsonWriter, cat: ChromiumTraceEventCategories.ProjectToProject, name: $"MSBuild \"{projectStartedEventArgs.ProjectFile}\" ({projectStartedEventArgs.TargetNames})", ph: ChromiumTraceEventPhases.FlowStart, ts: (uint)((callingMsbuildTaskInvocation.Timestamp.Ticks - firstObservedTime) / TicksPerMicrosecond) + 1, tid: projectStartedEventArgs.ParentProjectBuildEventContext.ProjectInstanceId, pid: projectStartedEventArgs.ParentProjectBuildEventContext.NodeId.ToString(), id: projectStartedEventArgs.BuildEventContext.BuildRequestId.ToString()); writeEvent( jsonWriter: jsonWriter, cat: ChromiumTraceEventCategories.ProjectToProject, name: $"MSBuild \"{projectStartedEventArgs.ProjectFile}\" ({projectStartedEventArgs.TargetNames})", ph: ChromiumTraceEventPhases.FlowEnd, ts: ts - 1, tid: projectStartedEventArgs.BuildEventContext.ProjectInstanceId, pid: projectStartedEventArgs.BuildEventContext.NodeId.ToString(), id: projectStartedEventArgs.BuildEventContext.BuildRequestId.ToString()); } } break; case ProjectFinishedEventArgs projectFinishedEventArgs: writeEvent( jsonWriter: jsonWriter, name: $"Project \"{projectFinishedEventArgs.ProjectFile}\" ({projectFinishedEventArgs.BuildEventContext.ProjectInstanceId})", ts: ts, ph: ChromiumTraceEventPhases.DurationEnd, tid: projectFinishedEventArgs.BuildEventContext.ProjectInstanceId, pid: projectFinishedEventArgs.BuildEventContext.NodeId.ToString()); break; case TargetStartedEventArgs targetStartedEventArgs: writeEvent( jsonWriter: jsonWriter, name: $"Target \"{targetStartedEventArgs.TargetName}\" in project \"{targetStartedEventArgs.ProjectFile}\" ({targetStartedEventArgs.BuildEventContext.ProjectInstanceId})", ts: ts, ph: ChromiumTraceEventPhases.DurationBegin, tid: targetStartedEventArgs.BuildEventContext.ProjectInstanceId, pid: targetStartedEventArgs.BuildEventContext.NodeId.ToString()); break; case TargetFinishedEventArgs targetFinishedEventArgs: writeEvent( jsonWriter: jsonWriter, name: $"Target \"{targetFinishedEventArgs.TargetName}\" in project \"{targetFinishedEventArgs.ProjectFile}\" ({targetFinishedEventArgs.BuildEventContext.ProjectInstanceId})", ts: ts, ph: ChromiumTraceEventPhases.DurationEnd, tid: targetFinishedEventArgs.BuildEventContext.ProjectInstanceId, pid: targetFinishedEventArgs.BuildEventContext.NodeId.ToString()); break; case TaskStartedEventArgs taskStartedEventArgs: { string name; if (taskStartedEventArgs.TaskName.EndsWith("MSBuild", StringComparison.Ordinal)) { name = $"MSBuild (yielded) in project \"{taskStartedEventArgs.ProjectFile}\" ({taskStartedEventArgs.BuildEventContext.ProjectInstanceId})"; } else { if (!includeAllTasks) { break; } name = $"Task \"{taskStartedEventArgs.TaskName}\" in project \"{taskStartedEventArgs.ProjectFile}\" ({taskStartedEventArgs.BuildEventContext.ProjectInstanceId})"; } msbuildStartEvents[taskStartedEventArgs.BuildEventContext.ProjectInstanceId] = taskStartedEventArgs; writeEvent( jsonWriter: jsonWriter, name: name, ts: ts, ph: ChromiumTraceEventPhases.DurationBegin, tid: taskStartedEventArgs.BuildEventContext.ProjectInstanceId, pid: taskStartedEventArgs.BuildEventContext.NodeId.ToString()); } break; case TaskFinishedEventArgs taskFinishedEventArgs: { string name; if (taskFinishedEventArgs.TaskName.EndsWith("MSBuild", StringComparison.Ordinal)) { name = $"MSBuild (yielded) in project \"{taskFinishedEventArgs.ProjectFile}\" ({taskFinishedEventArgs.BuildEventContext.ProjectInstanceId})"; } else { if (!includeAllTasks) { break; } name = $"Task \"{taskFinishedEventArgs.TaskName}\" in project \"{taskFinishedEventArgs.ProjectFile}\" ({taskFinishedEventArgs.BuildEventContext.ProjectInstanceId})"; } writeEvent( jsonWriter: jsonWriter, name: name, ts: ts, ph: ChromiumTraceEventPhases.DurationEnd, tid: taskFinishedEventArgs.BuildEventContext.ProjectInstanceId, pid: taskFinishedEventArgs.BuildEventContext.NodeId.ToString()); } break; case ProjectEvaluationStartedEventArgs projectEvaluationStartedEventArgs: writeEvent( jsonWriter: jsonWriter, name: $"Project \"{projectEvaluationStartedEventArgs.ProjectFile}\" ({projectEvaluationStartedEventArgs.BuildEventContext.ProjectInstanceId}) evaluation", ts: ts, ph: ChromiumTraceEventPhases.DurationBegin, tid: projectEvaluationStartedEventArgs.BuildEventContext.ProjectInstanceId, pid: projectEvaluationStartedEventArgs.BuildEventContext.NodeId == BuildEventContext.InvalidNodeId ? "Evaluation" : projectEvaluationStartedEventArgs.BuildEventContext.NodeId.ToString()); break; case ProjectEvaluationFinishedEventArgs projectEvaluationFinishedEventArgs: { var name = $"Project \"{projectEvaluationFinishedEventArgs.ProjectFile}\" ({projectEvaluationFinishedEventArgs.BuildEventContext.ProjectInstanceId}) evaluation"; var pid = projectEvaluationFinishedEventArgs.BuildEventContext.NodeId == BuildEventContext.InvalidNodeId ? "Evaluation" : projectEvaluationFinishedEventArgs.BuildEventContext.NodeId.ToString(); writeEvent( jsonWriter: jsonWriter, name: name, ts: ts, ph: ChromiumTraceEventPhases.DurationEnd, tid: projectEvaluationFinishedEventArgs.BuildEventContext.ProjectInstanceId, pid: pid ); writeEvent( jsonWriter: jsonWriter, name: name, ts: ts, ph: ChromiumTraceEventPhases.DurationEnd, tid: projectEvaluationFinishedEventArgs.BuildEventContext.ProjectInstanceId, pid: pid ); } break; } } jsonWriter.WriteEndArray();