From d9ae3e00f6ee7d7dc7db267a23d7a215496b9f91 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Thu, 12 Feb 2026 18:28:59 +0100 Subject: [PATCH] fix duration - startedAt now correct --- .../Functions/IngestEventsFunction.cs | 16 +++++++++++++--- .../Services/TableStorageService.cs | 12 +++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/IngestEventsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/IngestEventsFunction.cs index 6c5989ea..e64bedff 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/IngestEventsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/IngestEventsFunction.cs @@ -119,12 +119,19 @@ namespace AutopilotMonitor.Functions.Functions EnrollmentEvent? lastPhaseChangeEvent = null; EnrollmentEvent? completionEvent = null; EnrollmentEvent? failureEvent = null; + DateTime? earliestEventTimestamp = null; // Track app install events for AppInstallSummary aggregation var appInstallUpdates = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var evt in storedEvents) { + // Track earliest event timestamp for accurate session StartedAt + if (!earliestEventTimestamp.HasValue || evt.Timestamp < earliestEventTimestamp.Value) + { + earliestEventTimestamp = evt.Timestamp; + } + // Track special events for session status updates if (evt.EventType == "phase_changed" || evt.EventType == "esp_phase_changed") { @@ -158,7 +165,8 @@ namespace AutopilotMonitor.Functions.Functions request.SessionId, SessionStatus.Succeeded, completionEvent.Phase, - completedAt: completionEvent.Timestamp + completedAt: completionEvent.Timestamp, + earliestEventTimestamp: earliestEventTimestamp ); _logger.LogInformation($"{sessionPrefix} Status: Succeeded"); } @@ -175,7 +183,8 @@ namespace AutopilotMonitor.Functions.Functions SessionStatus.Failed, failureEvent.Phase, failureReason, - completedAt: failureEvent.Timestamp + completedAt: failureEvent.Timestamp, + earliestEventTimestamp: earliestEventTimestamp ); _logger.LogWarning($"{sessionPrefix} Status: Failed - {failureReason}"); } @@ -186,7 +195,8 @@ namespace AutopilotMonitor.Functions.Functions request.TenantId, request.SessionId, SessionStatus.InProgress, - lastPhaseChangeEvent.Phase + lastPhaseChangeEvent.Phase, + earliestEventTimestamp: earliestEventTimestamp ); } else if (processedCount > 0) diff --git a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.cs b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.cs index 7acaecdb..d8dce317 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.cs @@ -340,7 +340,7 @@ namespace AutopilotMonitor.Functions.Services /// /// Updates the session status and current phase /// - public async Task UpdateSessionStatusAsync(string tenantId, string sessionId, SessionStatus status, EnrollmentPhase? currentPhase = null, string? failureReason = null, DateTime? completedAt = null) + public async Task UpdateSessionStatusAsync(string tenantId, string sessionId, SessionStatus status, EnrollmentPhase? currentPhase = null, string? failureReason = null, DateTime? completedAt = null, DateTime? earliestEventTimestamp = null) { SecurityValidator.EnsureValidGuid(tenantId, nameof(tenantId)); SecurityValidator.EnsureValidGuid(sessionId, nameof(sessionId)); @@ -367,6 +367,16 @@ namespace AutopilotMonitor.Functions.Services session["CurrentPhase"] = (int)currentPhase.Value; } + // Update StartedAt if an earlier event timestamp is provided + if (earliestEventTimestamp.HasValue) + { + var currentStartedAt = session.GetDateTimeOffset("StartedAt")?.UtcDateTime ?? DateTime.MaxValue; + if (earliestEventTimestamp.Value < currentStartedAt) + { + session["StartedAt"] = earliestEventTimestamp.Value; + } + } + // Set completion time if succeeded or failed if (status == SessionStatus.Succeeded || status == SessionStatus.Failed) {