From 8e35eb1b570925498f472e56e754591ff4a9dfd9 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Mon, 15 Jun 2026 15:59:03 +0200 Subject: [PATCH] feat(agent-v2): surface downloadPercent + streamingFinished in Office doSummary The office_install_completed doSummary paired aggregateFileSize next to totalBytesDownloaded with no context, making the (expected) gap look like a bug: the completed event fires at core-binary completion while background streaming of the remaining declared content is still in flight, so the peak DO sample shows downloaded < declared. aggregateFileSize is the sum of the DO jobs' declared target sizes at the peak instant, not a stable payload total. Mirror downloadPercent (from OfficeDoSample.DownloadPercent) and streamingFinished into the summary so the gap is self-explanatory. XML-doc now states why aggregate exceeds downloaded. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Monitoring/Office/OfficeInstallDetectorTests.cs | 4 ++++ .../Telemetry/Office/OfficeInstallDetector.cs | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Monitoring/Office/OfficeInstallDetectorTests.cs b/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Monitoring/Office/OfficeInstallDetectorTests.cs index 6193c5db..85fc2ca0 100644 --- a/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Monitoring/Office/OfficeInstallDetectorTests.cs +++ b/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Monitoring/Office/OfficeInstallDetectorTests.cs @@ -292,6 +292,8 @@ namespace AutopilotMonitor.Agent.V2.Core.Tests.Monitoring.Office Assert.Equal(0L, summary["bytesFromPeers"]); Assert.Equal(80, summary["percentFromCacheServer"]); Assert.Equal(20, summary["percentFromCdn"]); + Assert.Equal(83, summary["downloadPercent"]); // 1000 of 1200 declared + Assert.Equal(true, summary["streamingFinished"]); } [Fact] @@ -544,6 +546,8 @@ namespace AutopilotMonitor.Agent.V2.Core.Tests.Monitoring.Office Assert.Equal(1000L, summary["totalBytesDownloaded"]); Assert.Equal(800L, summary["bytesFromCacheServer"]); Assert.Equal(200L, summary["bytesFromCdn"]); + Assert.Equal(83, summary["downloadPercent"]); + Assert.Equal(true, summary["streamingFinished"]); Assert.Equal(OfficeInstallStateData.StateCompleted, rig.Persistence!.Load()!.State); } diff --git a/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/Office/OfficeInstallDetector.cs b/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/Office/OfficeInstallDetector.cs index f9147253..e9a5c52f 100644 --- a/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/Office/OfficeInstallDetector.cs +++ b/src/Agent/AutopilotMonitor.Agent.V2.Core/Monitoring/Telemetry/Office/OfficeInstallDetector.cs @@ -411,7 +411,7 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Telemetry.Office data["coreBinariesPresent"] = coreBinariesPresent; // One-time Delivery-Optimization summary (how Office was delivered) — far more useful than // a streaming download-% (which is noise under Connected-Cache + multi-job churn). - if (_peakDo != null) data["doSummary"] = BuildDoSummary(_peakDo); + if (_peakDo != null) data["doSummary"] = BuildDoSummary(_peakDo, snap.StreamingFinished); } var message = BuildMessage(eventType, snap); @@ -467,8 +467,14 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Telemetry.Office /// highest-bytes sample seen. Splits the bytes into Connected-Cache-Server / peer / pure-CDN: on /// MCC-enabled networks BytesFromHttp includes the cache-server bytes, so pure CDN is /// BytesFromHttp - BytesFromCacheServer (see project DO-telemetry notes). + /// + /// aggregateFileSize is the sum of the DO jobs' declared target sizes at the peak + /// instant — NOT a stable "total Office payload". It commonly exceeds totalBytesDownloaded + /// because the completed event fires at core-binary completion while background streaming of the + /// remaining declared content is still in flight (streamingFinished == false). The mirrored + /// downloadPercent + streamingFinished make that gap self-explanatory. /// - private static Dictionary BuildDoSummary(OfficeDoSample d) + private static Dictionary BuildDoSummary(OfficeDoSample d, bool streamingFinished) { long total = d.TotalBytesDownloaded; long cacheServer = d.BytesFromCacheServer; @@ -480,6 +486,8 @@ namespace AutopilotMonitor.Agent.V2.Core.Monitoring.Telemetry.Office { { "totalBytesDownloaded", total }, { "aggregateFileSize", d.FileSize }, + { "downloadPercent", (object?)d.DownloadPercent ?? 0 }, + { "streamingFinished", streamingFinished }, { "jobCount", d.JobCount }, { "bytesFromCacheServer", cacheServer }, { "bytesFromPeers", peers },