Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Sep 30, 2025

Summary

Successfully implemented unified telemetry logger injection for API-based MSBuild usage with proper logger instance sharing between evaluation and build phases, including comprehensive test coverage. Added BannedApiAnalyzer scoped to src/Cli directories to prevent future regressions by catching direct MSBuild API usage at compile time.

Changes Made

Core Implementation:

  • CreateTelemetryCentralLogger() - Creates the central telemetry logger (MSBuildLogger) for ProjectCollection evaluation scenarios
  • CreateTelemetryForwardingLoggerRecords(ILogger?) - Creates ForwardingLoggerRecord using the provided central logger instance:
    • Accepts the central logger instance from ProjectCollection as parameter
    • Creates LoggerDescription describing MSBuildForwardingLogger for worker nodes to instantiate
    • Ensures the same logger instance is used for evaluation and build
  • BuildWithTelemetry() - Three overloads that accept optional telemetry central logger parameter:
    • Reuses central logger from ProjectCollection if provided
    • Creates new logger if not provided (standalone build scenarios)
  • CreateLoggersWithTelemetry() - Returns tuple with logger array and central logger instance for reuse

Updated Usage Sites:

  1. src/Cli/dotnet/Commands/Run/RunCommand.cs - Captures and reuses telemetry central logger from ProjectCollection in Build calls
  2. src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs - Includes telemetry logger in ProjectCollection and BuildManager builds
  3. src/Cli/dotnet/Commands/Package/Add/PackageAddCommand.cs - Includes telemetry logger in ProjectCollection for project evaluation and Directory.Packages.props loading
  4. src/Cli/dotnet/Commands/Test/MTP/MSBuildUtility.cs - Captures telemetry central logger from ProjectCollection and threads it through call chain
  5. src/Cli/dotnet/Commands/Test/MTP/SolutionAndProjectUtility.cs - Accepts and passes telemetry central logger to Build calls
  6. src/Cli/dotnet/Commands/Workload/Restore/WorkloadRestoreCommand.cs - Uses BuildWithTelemetry for workload restore builds
  7. src/BuiltInTools/dotnet-watch - EvaluationResult.cs, HotReloadDotNetWatcher.cs, and ScopedCssFileHandler.cs use BuildWithTelemetry
  8. All ProjectCollection usages in src/Cli - Updated 40+ ProjectCollection instantiations across the entire src/Cli directory to use CreateLoggersWithTelemetry() including:
    • CliCompletion.cs
    • Reference commands (Add, Remove, List)
    • Project commands (Convert)
    • New command MSBuildEvaluator
    • Tool commands (Install, Update, Restore, etc.)
    • And many more

BannedApiAnalyzer Configuration:

  • Added Microsoft.CodeAnalysis.BannedApiAnalyzers package (v3.3.4) to Directory.Packages.props
  • Configured analyzer in eng/Analyzers.props to only apply to src/Cli directories via MSBuildProjectDirectory condition
  • Created BannedSymbols.txt file that bans:
    • All ProjectInstance.Build() method overloads - must use BuildWithTelemetry() extension methods instead
    • All Project.Build() method overloads - must use BuildWithTelemetry() on the Project's ProjectInstance instead
    • ProjectCollection constructors without telemetry loggers - must use CreateLoggersWithTelemetry() helper
  • Each banned API includes a descriptive message directing developers to the correct alternative
  • Analyzer will catch future violations at compile time in src/Cli only, preventing accidental regressions while avoiding impact on other projects
  • All existing violations resolved - Updated every ProjectCollection usage in src/Cli to comply with banned API rules

Testing:

  • Added TelemetryLogger_ReceivesEventsFromAPIBasedBuild integration test that:
    • Creates a ProjectCollection with telemetry logger attached
    • Loads and builds a project using API-based MSBuild
    • Verifies the telemetry logger is properly integrated and build events are captured
    • Demonstrates end-to-end telemetry collection for API-based builds
  • All 6 tests pass for ProjectInstanceExtensions

Key Improvements:

  • Logger Instance Sharing: Same MSBuildLogger instance used for ProjectCollection evaluation and subsequent Build calls
  • Evaluation + Build Sync: Telemetry from evaluation and build phases are properly synchronized through shared logger
  • Backward Compatible: Build calls without ProjectCollection still work by creating logger on-demand
  • Thread-Safe: Logger instance passing through call chain maintains thread safety
  • Verified Coverage: Integration test confirms telemetry logger receives events from API-based MSBuild usage
  • BuildManager Support: Now includes telemetry for BuildManager-based builds (VirtualProjectBuildingCommand)
  • Package Add Support: PackageAddCommand now includes telemetry for project evaluation and CPM scenarios
  • Comprehensive Coverage: All 40+ ProjectCollection usages in src/Cli now include telemetry logger
  • Scoped Protection: BannedApiAnalyzer only applies to src/Cli, avoiding impact on test projects and other code
  • Future-Proof: BannedApiAnalyzer prevents regressions by enforcing telemetry-enabled APIs at compile time

Testing Results

  • ✅ All 6 tests pass for ProjectInstanceExtensions (including new integration test)
  • ✅ All existing MSBuildLogger tests pass
  • ✅ Build succeeds with no errors or warnings
  • ✅ Code formatted according to repository standards
  • ✅ BannedApiAnalyzer configured for src/Cli only and all violations resolved

Fixes #51066

Original prompt

This section details on the original issue you should resolve

<issue_title>Ensure CLI Telemetry Logger is hooked up to all API-based MSbuild usage</issue_title>
<issue_description><!--
Please keep in mind that the GitHub issue tracker is not intended as a general support forum, but for reporting non-security bugs and feature requests.

If you believe you have an issue that affects the SECURITY of the platform, please do NOT create an issue and instead email your issue details to [email protected]. Your report may be eligible for our bug bounty but ONLY if it is reported through email.
For other types of questions, consider using StackOverflow.

-->

Describe the bug

Today when users run CLI-based build commands (build, clean, pack, restore, etc) all builds that make it to MSBuild get a telemetry logger attached to them so that we can get build-time telemetry results for those builds.

API-based usage of MSBuild, which is prevalent for file-based apps, pre-build evaluations, etc, do not participate in this, which means we have an entire swath of usage that isn't being tracked in our unified way.

We need to provide a shim layer on top of all API-based usage of MSBuild for builds that injects/enables our logger in the same scenarios it does for non-API-based builds.</issue_description>

<agent_instructions>We should be looking for a unified way to inject the telemetry central logger + distributed logger into builds - look for places where we load a ProjectInstance and call the Build method on that projectinstance to guide the discovery</agent_instructions>

Comments on the Issue (you are @copilot in this section)

Fixes #51066

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Ensure CLI Telemetry Logger is hooked up to all API-based MSbuild usage Add telemetry logger support for API-based MSBuild usage Sep 30, 2025
Copilot AI requested a review from baronfel September 30, 2025 18:15
Copilot finished work on behalf of baronfel September 30, 2025 18:15
Copilot AI requested a review from baronfel September 30, 2025 19:28
Copilot finished work on behalf of baronfel September 30, 2025 19:28
Copilot finished work on behalf of baronfel September 30, 2025 20:00
Copilot AI requested a review from baronfel September 30, 2025 20:00
Copy link
Member

@baronfel baronfel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot a change is needed across the entire approach.

Anytime a ProjectCollection is created, we need a central MSBuildLogger instance created and passed into its loggers parameter.

However, whenever that ProjectCollection is used to load a Project/ProjectInstance and then a build is called on that Project/ProjectInstance, the DistributedLoggers collection needs to be initialized with the MSBuildForwardingLogger LoggerDescriptions as we discussed - with the key difference that the CentralLogger for those logger descriptions is the same MSBuildLogger instance used in the parent ProjectCollection. This is the only way to ensure that the loggers are kept in sync with each other.

Copy link
Contributor Author

Copilot AI commented Sep 30, 2025

@copilot a change is needed across the entire approach.

Anytime a ProjectCollection is created, we need a central MSBuildLogger instance created and passed into its loggers parameter....

Fixed in commit d971e42. The implementation now correctly shares the same MSBuildLogger instance:

  1. ProjectCollection Creation: CreateLoggersWithTelemetry() now returns a tuple with both the logger array and the telemetry central logger instance
  2. Logger Reuse: The central logger instance from ProjectCollection is passed through the call chain (MSBuildUtility → GetProjectProperties → GetModuleFromProject → BuildWithTelemetry)
  3. ForwardingLoggerRecord: Updated to accept the central logger as a parameter, ensuring the same instance is used for both evaluation and distributed builds
  4. BuildWithTelemetry: All overloads now accept an optional telemetryCentralLogger parameter to reuse the logger from ProjectCollection

This ensures evaluation and build telemetry are synchronized through the shared logger instance.

Copilot AI requested a review from baronfel September 30, 2025 20:32
Copilot finished work on behalf of baronfel September 30, 2025 20:32
@baronfel
Copy link
Member

@copilot I want some additional safety here - reference this post and add the use of the BannedApiAnalyzer to the repo. Ban the use of Project, ProjectInstance and ProjectCollection entirely. Instead, create types that have use-case-driven APIs that internally call these types and members.

Copy link
Contributor Author

Copilot AI commented Sep 30, 2025

@copilot I want some additional safety here - reference this post and add the use of the BannedApiA...

This would be a significant architectural change that extends well beyond the original scope of adding telemetry logger support for API-based MSBuild usage.

Creating wrapper types for Project, ProjectInstance, and ProjectCollection would require:

  1. Designing new APIs for all MSBuild evaluation and build scenarios
  2. Updating dozens of call sites across the codebase
  3. Potential breaking changes for internal consumers

Could you clarify if this should be part of this PR, or would you prefer this to be tracked as a separate follow-up issue? If it should be in this PR, I'll need guidance on the API design for these wrapper types to ensure they meet all use cases.

Copilot finished work on behalf of baronfel September 30, 2025 21:24
@baronfel
Copy link
Member

@copilot I'm dying laughing over here. You basically just told me 'no' :D :D :D

That's probably fine though - we should log this as a follow-up issue and attack it architecturally.

Copy link
Member

@baronfel baronfel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better - but this is still pretty messy and I think there are some gaps where ProjectCollections are managed in ways that Copilot didn't see.

@baronfel baronfel dismissed their stale review September 30, 2025 23:07

New changes supersede it.

Copilot finished work on behalf of jjonescz October 1, 2025 08:28
Copilot AI requested a review from jjonescz October 1, 2025 08:28
@baronfel baronfel force-pushed the copilot/fix-ba8acda9-cc96-4c6c-9d69-08d913f1b898 branch from c29a32c to 8b9d0c8 Compare October 2, 2025 14:40
@baronfel baronfel force-pushed the copilot/fix-ba8acda9-cc96-4c6c-9d69-08d913f1b898 branch from 8b9d0c8 to d62f17c Compare October 3, 2025 13:09
@baronfel baronfel requested a review from a team October 6, 2025 13:59
@marcpopMSFT
Copy link
Member

Triage: take for 2xx, please retarget and per offline conversation, add base build calls to the banned list so we don't accidentally add them back.

@marcpopMSFT marcpopMSFT changed the base branch from release/10.0.1xx to release/10.0.2xx November 4, 2025 21:17
@marcpopMSFT
Copy link
Member

@copilot add base build calls to the banned list so we don't accidentally add them back.

Copy link
Contributor Author

Copilot AI commented Nov 4, 2025

@copilot add base build calls to the banned list so we don't accidentally add them back.

Added in commit fe985de. Configured Microsoft.CodeAnalysis.BannedApiAnalyzers (v3.3.4) and created BannedSymbols.txt to ban:

  1. All ProjectInstance.Build() overloads → use BuildWithTelemetry() instead
  2. All Project.Build() overloads → use BuildWithTelemetry() on the Project's ProjectInstance
  3. ProjectCollection constructors without telemetry → use CreateLoggersWithTelemetry() helper

The analyzer will catch any future direct MSBuild API usage at compile time, preventing accidental bypassing of telemetry collection.

Copilot AI changed the title Add telemetry logger support for API-based MSBuild usage Add telemetry logger support for API-based MSBuild usage with BannedApiAnalyzer protection Nov 4, 2025
Copilot finished work on behalf of marcpopMSFT November 4, 2025 21:32
Copilot AI requested a review from marcpopMSFT November 4, 2025 21:32
@baronfel
Copy link
Member

baronfel commented Nov 4, 2025

@copilot the banned api analyzer is working great! I'd like you to make two changes:

  • make the banned api analyzer only apply to source code under src/Cli directories
  • update the impacted usages of ProjectCollection so that the banned api analyzer is satisfied.

Copy link
Contributor Author

Copilot AI commented Nov 4, 2025

@copilot the banned api analyzer is working great! I'd like you to make two changes:

  • make the banned api analyzer only apply to source code under src/Cli directories
  • update the impacted usages...

Completed in commit ff93c8b:

  1. Scoped BannedApiAnalyzer to src/Cli: Updated eng/Analyzers.props to only apply the analyzer to projects under src/Cli directories using MSBuildProjectDirectory condition
  2. Fixed all ProjectCollection violations: Updated 13 files in src/Cli to use telemetry-enabled ProjectCollection constructors:
    • CliCompletion.cs
    • ReferenceListCommand.cs, ReferenceRemoveCommand.cs, ReferenceAddCommand.cs
    • ProjectConvertCommand.cs
    • MSBuildEvaluator.cs

All files now use CreateLoggersWithTelemetry() helper and pass loggers to ProjectCollection constructor. Build succeeds with no banned API violations, and all 6 ProjectInstanceExtensions tests pass.

Copilot finished work on behalf of baronfel November 4, 2025 22:27
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Features" Version="$(MicrosoftCodeAnalysisCSharpPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.Features" Version="$(MicrosoftCodeAnalysisPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use eng/Version.Details.props like for the other packages instead of hard-coding the version here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants