dotnet / dotnet/msbuild

[Feature Request]: Expose Static Graph to Central Loggers

Open
#8,662 3 comments 0 reactions 0 assignees View on GitHub
Area: Static Graph backlog Feature Request triaged
Dominant language
C#
Stars
5.5k
Forks
1.5k
Avg merge
1d 8h
Merged PRs (30d)
141

Description

### Summary

When building with `/graph`, MSBuild [constructs a dependency graph](https://learn.microsoft.com/en-us/visualstudio/msbuild/build-process-overview?view=vs-2022#graph-option) of the project tree before scheduling builds. This is a powerful concept that enables many new scenarios with MSBuild.

Today, while this [`ProjectGraph`](https://github.com/dotnet/msbuild/blob/cb5e760644d04def33c0cafcaef2a6f496fc68cc/src/Build/Graph/ProjectGraph.cs#L27) is available to the build engine, it is not exposed via the `ILogger`-based extensibility model. Currently, loggers are only delivered a textual status message, e.g. `"Static graph loaded in 0.906 seconds: 4 nodes, 3 edges"`.

Exposing the project graph up-front as a first-class concept to the logger would make it possible to do some very cool things (and do so easily), including:
- Implementing progress tracking and visualizing progress across the whole project tree
- Report telemetry on the shape and size of the project tree built by developers
- Apply architectural review and warn when undesired project references are introduced

Some of these are of course possible today via other means, even in the logger, but often this requires parsing status messages or project files directly. Exposing the `ProjectGraph` directly to loggers will help complete the Static Graph vision and enable new extensibility based on this capability.

### Background and Motivation

I began thinking about this problem when I started working on an MSBuild logger that would provide progress tracking and help developers understand the impact of their changes on incremental builds. I was hoping to better inform developers by visualizing what sub-trees of the project graph were getting rebuilt after a change.

Having the rich [`Microsoft.Build.Graph.ProjectGraph`](https://github.com/dotnet/msbuild/blob/cb5e760644d04def33c0cafcaef2a6f496fc68cc/src/Build/Graph/ProjectGraph.cs#L27) type available would have made this almost a trivial task.

### Proposed Feature

The high-level proposal is to introduce a new `StaticGraphLoadedEventHandler` on `IEventSource`, and deliver the `ProjectGraph` object to it.

### Proposed API

```diff
namespace Microsoft.Build.Framework
{
+ public class StaticGraphLoadedEventArgs : BuildEventArgs
+ {
+ public TimeSpan Duration { get; }
+ public object ProjectGraph { get; }
+ }

+ public delegate void StaticGraphLoadedEventHandler(object sender, StaticGraphLoadedEventArgs e);

public interface IEventSource
{
+ event StaticGraphLoadedEventHandler GraphLoaded;
}
}
```

Note that the `StaticGraphLoadedEventArgs.ProjectGraph` property is exposed as a `System.Object`, as the actual `ProjectGraph` type is in `Microsoft.Build.dll`. Ideally, the type could be exposed through `Microsoft.Build.Framework.dll` since it is fundamental to MSBuild, but I also think it's perfectly reasonable for logger _implementations_ to take a dependency on `Microsoft.Build.dll` without forcing the type directly onto `ILogger` in `Microsoft.Build.Framework.dll`.

I would also note that it probably makes the most sense for central loggers to register for the event (rather than distributed loggers). Such a logger would receive the event, cast the event argument to a `ProjectGraph`, and cache this for the lifetime of the logger. Then, any build events received by the logger could be evaluated in the context of that static graph.

Builds not opting-in to `/graph` would not receive this event; it is a "value-added" scenario for Static Graph users.

### Alternative Designs

_No response_

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.