fix(backend): enable diagnostics upload for Hosted-destination tenants

DiagnosticsUploadEnabled was gated solely on the per-tenant
DiagnosticsBlobSasUrl. Hosted-destination tenants have no such URL
(the platform owns the storage), so the agent received
DiagnosticsUploadEnabled=false and silently skipped every upload —
even with DiagnosticsUploadMode=Always. No diagnostics_collecting /
_uploaded / _upload_failed events were ever emitted.

Extract the gate into ResolveDiagnosticsUploadEnabled and enable when
a customer SAS is set OR the destination is Hosted. Config-only change,
no ConfigVersion bump; applies on next agent config poll after deploy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Oliver Kieselbach
2026-06-18 18:04:07 +02:00
parent ecd8036dc0
commit b515db07d7
2 changed files with 38 additions and 1 deletions
@@ -31,4 +31,27 @@ public class GetAgentConfigFunctionTests
var actual = GetAgentConfigFunction.ParseAgentMajor(agentVersion);
Assert.Equal(expectedMajor, actual);
}
[Theory]
// CustomerSas: gated on the per-tenant SAS URL being present.
[InlineData("https://acct.blob.core.windows.net/c?sv=...", "CustomerSas", true)]
[InlineData(null, "CustomerSas", false)]
[InlineData("", "CustomerSas", false)]
// Hosted: platform owns the storage, no per-tenant SAS URL — must still enable uploads.
// Regression guard for the bug where Hosted-destination tenants silently never uploaded.
[InlineData(null, "Hosted", true)]
[InlineData("", "Hosted", true)]
[InlineData(null, "hosted", true)] // case-insensitive
// Hosted with a SAS also set (belt-and-braces) stays enabled.
[InlineData("https://acct.blob.core.windows.net/c?sv=...", "Hosted", true)]
// Unknown/empty destination with no SAS → disabled (no silent uploads to nowhere).
[InlineData(null, null, false)]
[InlineData(null, "", false)]
[InlineData(null, "Bogus", false)]
public void ResolveDiagnosticsUploadEnabled_GatesOnSasOrHosted(
string? diagnosticsBlobSasUrl, string? destination, bool expected)
{
var actual = GetAgentConfigFunction.ResolveDiagnosticsUploadEnabled(diagnosticsBlobSasUrl, destination);
Assert.Equal(expected, actual);
}
}
@@ -117,6 +117,19 @@ namespace AutopilotMonitor.Functions.Functions.Config
return int.TryParse(majorStr, out var major) ? major : 1;
}
/// <summary>
/// Decides whether the agent should perform diagnostics uploads at all.
/// The CustomerSas destination is gated on a per-tenant SAS URL being present, but the
/// Hosted destination has no such URL (the platform owns the storage) — so gating purely
/// on the SAS URL silently disabled uploads for every Hosted-destination tenant. Enable
/// when either a customer SAS is configured OR the destination is Hosted.
/// </summary>
internal static bool ResolveDiagnosticsUploadEnabled(string? diagnosticsBlobSasUrl, string? destination)
{
return !string.IsNullOrEmpty(diagnosticsBlobSasUrl)
|| string.Equals(destination, "Hosted", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Returns the (ZipSha256, ExeSha256) pair appropriate for the calling agent.
/// Reads the X-Agent-Version header, parses the major, and dispatches to the
@@ -197,7 +210,8 @@ namespace AutopilotMonitor.Functions.Functions.Config
EnrollmentSummaryBrandingImageUrl = tenantConfig.EnrollmentSummaryBrandingImageUrl,
EnrollmentSummaryLaunchRetrySeconds = tenantConfig.EnrollmentSummaryLaunchRetrySeconds ?? 120,
MaxBatchSize = tenantConfig.MaxBatchSize ?? 100,
DiagnosticsUploadEnabled = !string.IsNullOrEmpty(tenantConfig.DiagnosticsBlobSasUrl),
DiagnosticsUploadEnabled = ResolveDiagnosticsUploadEnabled(
tenantConfig.DiagnosticsBlobSasUrl, tenantConfig.DiagnosticsUploadDestination),
DiagnosticsUploadMode = tenantConfig.DiagnosticsUploadMode ?? "Off",
DiagnosticsLogPaths = diagLogPaths,
Collectors = collectors,