Skip to content

Reading binlog files programmatically

Kirill Osenkov edited this page May 4, 2023 · 6 revisions

Reading the binlog file

To read .binlog files programmatically add the NuGet package reference to: https://www.nuget.org/packages/MSBuild.StructuredLogger

There are two ways of reading .binlog files via an API:

ReadRecords is a lower-level API that provides you low-level access to the stream of all records in the .binlog. Most records are serialized BuildEventArgs, each representing an event that happened during the build. Here are all the types of records that MSBuild uses: https://github.com/dotnet/msbuild/blob/b1e1a581a11e60a31a61d80a5a8a790a0c8e1feb/src/Build/Logging/BinaryLogger/BuildEventArgsWriter.cs#L143-L175

ReadRecords sample

Here's a sample of using ReadRecords to read all .cs files passed to the Csc tasks: https://github.com/KirillOsenkov/MSBuildStructuredLog/blob/9eeca1191b31618906017c1ecdcc438c9094aa8b/src/StructuredLogger.Tests/CompilerInvocationTests.cs#L22-L42

ReadBuild is a higher level API that first reads the records and then composes a build tree, where projects contain other projects and targets, targets contain tasks, project evaluations contain properties and items, etc. This is the same tree data structure that is used by the MSBuild Structured Log Viewer. It does take longer to construct but provides a convenient overview of the build that you can search and query against.

BinlogTool

See some practical examples of reading .binlog files in the BinlogTool project: https://github.com/KirillOsenkov/MSBuildStructuredLog/tree/main/src/BinlogTool

It is published as a .NET global tool that you can install via dotnet tool install -g BinlogTool

It has examples such as save all files from the binlog, search the binlog from command-line and print results on the console, etc.

Examples: print all errors: binlogtool search msbuild.binlog $error

print all warnings: binlogtool search msbuild.binlog $warning

print all tasks: binlogtool search msbuild.binlog $task

AnalyzeBuild

After you call ReadBuild you should call AnalyzeBuild, like here for example: https://github.com/KirillOsenkov/MSBuildStructuredLog/blob/ddea3ae1d287ad199cc08b2d7465ba12af57ebfd/src/BinlogTool/Search.cs#L53. It does a few things:

  1. assign a unique numeric index (id) to each TimedNode. This is the id that you see when you right-click on a node in the viewer and choose "Search in subtree".
  2. compute relative durations of project evaluations (used by the evaluation profiler)
  3. sort all Property reassignments
  4. mark some nodes as "low-relevance" so they are displayed in light gray
  5. intern and deduplicate all the strings (the search algorithm relies on this)
  6. compute all double-writes and create the Double Writes folder (by scanning all file copy operations)
  7. analyze ResolveAssemblyReference tasks (adds more information)
  8. compute top 10 most expensive tasks
  9. compute Roslyn analyzer summaries
  10. compute entry targets and mark targets as low relevance
  11. display task command-line arguments and which assembly the task is from
  12. updates task durations
  13. various other small miscellaneous tree manipulations