Add compiler telemetry - #84725
Conversation
|
Azure Pipelines: Successfully started running 1 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Adds a generic telemetry transport from the compiler server back to the MSBuild Csc/Vbc tasks, and wires up the compilation output cache to emit a structured roslyn/compilercache event that the task forwards to the host via IBuildEngine5.LogTelemetry.
Changes:
- Extend the compiler server build protocol to include a list of telemetry events on
CompletedBuildResponse. - Add compiler-server-side telemetry infrastructure and emit compilation-cache metrics for C# and VB server compilations.
- Forward server-produced telemetry from
ManagedCompilerto MSBuild hosts and add unit coverage + design doc updates.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Compilers/Shared/BuildProtocol.cs | Adds BuildTelemetryEvent and serializes/deserializes telemetry on CompletedBuildResponse. |
| src/Compilers/Server/VBCSCompilerTests/CompilationCacheTests.cs | Adds tests for cache store result enums + telemetry mapping behavior. |
| src/Compilers/Server/VBCSCompilerTests/BuildProtocolTest.cs | Adds protocol round-trip test coverage for completed responses with telemetry. |
| src/Compilers/Server/VBCSCompiler/VisualBasicCompilerServer.cs | Implements telemetry provider and emits cache telemetry for VB server compiles. |
| src/Compilers/Server/VBCSCompiler/VBCSCompilerCommandLine.projitems | Includes new CompilerServerTelemetry.cs in the build. |
| src/Compilers/Server/VBCSCompiler/CSharpCompilerServer.cs | Implements telemetry provider and emits cache telemetry for C# server compiles. |
| src/Compilers/Server/VBCSCompiler/CompilerServerTelemetry.cs | Introduces telemetry provider interface + cache telemetry model/enums. |
| src/Compilers/Server/VBCSCompiler/CompilerRequestHandler.cs | Attaches telemetry events to CompletedBuildResponse. |
| src/Compilers/Server/VBCSCompiler/CompilationCacheUtilities.cs | Captures key/restore/store timings and cache status/store-result for telemetry. |
| src/Compilers/Server/VBCSCompiler/CompilationCache.cs | Changes cache store API to return a CompilationCacheStoreResult. |
| src/Compilers/Core/MSBuildTaskTests/ManagedCompilerTelemetryTests.cs | Adds unit tests validating telemetry forwarding behavior in the MSBuild task. |
| src/Compilers/Core/MSBuildTask/ManagedCompiler.cs | Forwards server telemetry events to the host via IBuildEngine5.LogTelemetry. |
| docs/compilers/Design/compiler-output-cache-experiment.md | Documents the new roslyn/compilercache telemetry event and its properties. |
Suppressed comments (1)
src/Compilers/Shared/BuildProtocol.cs:443
- CompletedBuildResponse.Create unconditionally reads TelemetryCount and assumes it is non-negative. If the response body is truncated/corrupt (or comes from an older writer that doesn't include telemetry), this will throw and force a tool fallback. Consider making this parse tolerant by treating missing/negative counts as 0.
var returnCode = reader.ReadInt32();
var utf8Output = reader.ReadBoolean();
var output = ReadLengthPrefixedString(reader);
var telemetryCount = reader.ReadInt32();
IReadOnlyList<BuildTelemetryEvent> telemetryEvents = telemetryCount == 0
? []
: readTelemetryEvents(reader, telemetryCount);
|
Azure Pipelines: Successfully started running 1 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/Compilers/Server/VBCSCompilerTests/CompilationCacheTests.cs:480
- Using a hard-coded absolute path ("/nonexistent/path/Util.dll") to simulate a missing assembly is brittle across platforms/environments (rooted path semantics differ on Windows, and the path could theoretically exist). Prefer constructing a guaranteed-missing path under a temp directory created for the test.
var outputFiles = new CompilationOutputFiles { AssemblyPath = "/nonexistent/path/Util.dll" };
Assert.Equal(CompilationCacheStoreResult.Failed, cache.TryStoreResult("Util.dll", "hash", outputFiles, "key", _logger));
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/Compilers/Shared/BuildProtocol.cs:409
- The response-body field list in this doc comment is now out of sync with the actual serialization:
CompletedBuildResponsereads/writes aUtf8Outputboolean betweenReturnCodeandOutput, but the table doesn’t mention it. This makes the protocol documentation misleading for future maintainers.
/// Length UInteger 4
/// ReturnCode Integer 4
/// Output String Variable
/// TelemetryCount Integer 4
/// TelemetryEvents Variable Variable
|
@dotnet/roslyn-compiler for reviews, thanks |
| | `cachestatus` | `hit` or `miss` | | ||
| | `storeresult` | `none`, `stored`, `skippedrace`, `skippedexists`, or `failed` | | ||
| | `language` | the compiler language (`C#` / `Visual Basic`) | |
There was a problem hiding this comment.
Are these optional or always present?
| /// generic <see cref="BuildTelemetryEvent"/>. This is the first contributor to the compiler | ||
| /// server telemetry channel; additional contributors can be added independently. |
There was a problem hiding this comment.
| /// generic <see cref="BuildTelemetryEvent"/>. This is the first contributor to the compiler | |
| /// server telemetry channel; additional contributors can be added independently. | |
| /// generic <see cref="BuildTelemetryEvent"/>. |
| namespace Microsoft.CodeAnalysis.CompilerServer | ||
| { | ||
| /// <summary> | ||
| /// Implemented by server compilers that can produce telemetry for a build request. The request |
There was a problem hiding this comment.
Existing wording is awkward, maybe this?
| /// Implemented by server compilers that can produce telemetry for a build request. The request | |
| /// Implemented by compiler hosts that can produce telemetry for a build request. The request |
| /// <remarks> | ||
| /// This is intentionally generic: the transport (protocol + task) has no knowledge of any | ||
| /// particular event, so new server-side telemetry can be added by producing additional | ||
| /// <see cref="BuildTelemetryEvent"/> instances without changing the protocol or the task. | ||
| /// </remarks> |
| { | ||
| private readonly Func<string, MetadataReferenceProperties, PortableExecutableReference> _metadataProvider; | ||
| private readonly CompilationCache? _cache; | ||
| private readonly CompilationCacheTelemetry _cacheTelemetry = new(); |
There was a problem hiding this comment.
Please don't use target-typed new in the compiler codebase.
| { | ||
| private readonly Func<string, MetadataReferenceProperties, PortableExecutableReference> _metadataProvider; | ||
| private readonly CompilationCache? _cache; | ||
| private readonly CompilationCacheTelemetry _cacheTelemetry = new(); |
|
|
||
| var dllName = arguments.OutputFileName; | ||
| var outputTimestampUtc = DateTime.UtcNow; | ||
| var keyStopwatch = Stopwatch.StartNew(); |
There was a problem hiding this comment.
Rather than having the telemetry type manage one timer, and this method manage another, consider just having the telemetry object manage both timers, and share the timer between them.
SDK counterpart: dotnet/sdk#55572
Microsoft Reviewers: Open in CodeFlow