From 7bf139ecbe0b13dc3269b38adf191a54fc27cb98 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 06:32:10 +0000 Subject: [PATCH] Migrate IngestEvents, RegisterSession, DeleteSession, services to DAL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - IngestEventsFunction → ISessionRepository + IMetricsRepository + IMaintenanceRepository - RegisterSessionFunction → ISessionRepository + IMetricsRepository - DeleteSessionFunction → ISessionRepository + IMaintenanceRepository - SubmitSessionReportFunction → IMaintenanceRepository - RuleEngine → IRuleRepository - UsageMetricsService → IMetricsRepository + IMaintenanceRepository + ISessionRepository - PlatformMetricsService → IMetricsRepository + IMaintenanceRepository - Add StoreEventsBatchAsync to ISessionRepository + TableSessionRepository https://claude.ai/code/session_01NHWJfPaa8TQHuPzMD7gG63 --- .../TableStorage/TableSessionRepository.cs | 8 +++++++ .../UpdateAdminConfigurationFunction.cs | 1 + .../Ingest/IngestEventsFunction.Processing.cs | 11 +++++----- .../Functions/Ingest/IngestEventsFunction.cs | 19 ++++++++++++++--- .../Reports/SubmitSessionReportFunction.cs | 9 ++++---- .../Sessions/DeleteSessionFunction.cs | 21 +++++++++++-------- .../Sessions/RegisterSessionFunction.cs | 15 +++++++------ .../Services/MaintenanceService.cs | 1 + .../Services/PlatformMetricsService.cs | 11 +++++----- .../Services/RuleEngine.cs | 13 +++++++----- .../Services/UsageMetricsService.cs | 20 +++++++++++------- .../DataAccess/ISessionRepository.cs | 1 + 12 files changed, 85 insertions(+), 45 deletions(-) diff --git a/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableSessionRepository.cs b/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableSessionRepository.cs index 30910d6c..4c53a597 100644 --- a/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableSessionRepository.cs +++ b/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableSessionRepository.cs @@ -78,6 +78,14 @@ namespace AutopilotMonitor.Functions.DataAccess.TableStorage return result; } + public async Task> StoreEventsBatchAsync(List events) + { + var result = await _storage.StoreEventsBatchAsync(events); + if (result.Count > 0 && events.Count > 0) + await _publisher.PublishAsync("events.ingested", new { count = result.Count }, events[0].TenantId); + return result; + } + public Task> GetSessionEventsAsync(string tenantId, string sessionId, int maxResults = 1000) => _storage.GetSessionEventsAsync(tenantId, sessionId, maxResults); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateAdminConfigurationFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateAdminConfigurationFunction.cs index 671d6ecc..18b318e1 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateAdminConfigurationFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateAdminConfigurationFunction.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using System.Collections.Generic; using AutopilotMonitor.Functions.Helpers; using AutopilotMonitor.Functions.Services; +using AutopilotMonitor.Shared.DataAccess; using AutopilotMonitor.Shared.Models; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Ingest/IngestEventsFunction.Processing.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Ingest/IngestEventsFunction.Processing.cs index 961c7ad6..05fcf7ac 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Ingest/IngestEventsFunction.Processing.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Ingest/IngestEventsFunction.Processing.cs @@ -4,6 +4,7 @@ using AutopilotMonitor.Functions.Security; using AutopilotMonitor.Functions.Services; using AutopilotMonitor.Functions.Services.Notifications; using AutopilotMonitor.Functions.Services.Vulnerability; +using AutopilotMonitor.Shared.DataAccess; using AutopilotMonitor.Shared.Models; using AutopilotMonitor.Shared.Models.Notifications; using Microsoft.Azure.Functions.Worker.Http; @@ -128,7 +129,7 @@ namespace AutopilotMonitor.Functions.Functions.Ingest StampServerFields(request.Events, request.TenantId, request.SessionId, receivedAt); // Store events in Azure Table Storage (batch write for efficiency) - var storedEvents = await _storageService.StoreEventsBatchAsync(request.Events); + var storedEvents = await _sessionRepo.StoreEventsBatchAsync(request.Events); int processedCount = storedEvents.Count; // Update EventTypeIndex and DeviceSnapshot indexes (fire-and-forget, non-blocking) @@ -136,10 +137,10 @@ namespace AutopilotMonitor.Functions.Functions.Ingest var indexSessionId = request.SessionId; var indexEvents = storedEvents.ToList(); _ = Task.WhenAll( - _storageService.UpsertEventTypeIndexBatchAsync( + _sessionRepo.UpsertEventTypeIndexBatchAsync( indexTenantId, indexSessionId, indexEvents.Select(e => e.EventType).Distinct()), - _storageService.UpsertDeviceSnapshotAsync( + _sessionRepo.UpsertDeviceSnapshotAsync( indexTenantId, indexSessionId, indexEvents) ).ContinueWith(t => _logger.LogWarning(t.Exception?.InnerException, "Index update failed (non-fatal)"), TaskContinuationOptions.OnlyOnFaulted); @@ -152,7 +153,7 @@ namespace AutopilotMonitor.Functions.Functions.Ingest var imeVersion = imeVersionEvent.Data["agentVersion"]?.ToString(); if (!string.IsNullOrEmpty(imeVersion)) { - _ = _storageService.UpdateSessionImeAgentVersionAsync(request.TenantId, request.SessionId, imeVersion) + _ = _sessionRepo.UpdateSessionImeAgentVersionAsync(request.TenantId, request.SessionId, imeVersion) .ContinueWith(t => _logger.LogWarning(t.Exception?.InnerException, "ImeAgentVersion update failed (non-fatal)"), TaskContinuationOptions.OnlyOnFaulted); } @@ -164,7 +165,7 @@ namespace AutopilotMonitor.Functions.Functions.Ingest // Store app install summaries foreach (var summary in classification.AppInstallUpdates.Values) { - await _storageService.StoreAppInstallSummaryAsync(summary.Summary); + await _metricsRepo.StoreAppInstallSummaryAsync(summary.Summary); } // Extract geo-location data and merge into session row (fire-and-forget — diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Ingest/IngestEventsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Ingest/IngestEventsFunction.cs index c1575685..286720c3 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Ingest/IngestEventsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Ingest/IngestEventsFunction.cs @@ -3,6 +3,7 @@ using AutopilotMonitor.Functions.Security; using AutopilotMonitor.Functions.Services; using AutopilotMonitor.Functions.Services.Notifications; using AutopilotMonitor.Functions.Services.Vulnerability; +using AutopilotMonitor.Shared.DataAccess; using AutopilotMonitor.Shared.Models; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; @@ -14,7 +15,11 @@ namespace AutopilotMonitor.Functions.Functions.Ingest public partial class IngestEventsFunction { private readonly ILogger _logger; - private readonly TableStorageService _storageService; + private readonly ISessionRepository _sessionRepo; + private readonly IMetricsRepository _metricsRepo; + private readonly IMaintenanceRepository _maintenanceRepo; + private readonly IRuleRepository _ruleRepo; + private readonly IVulnerabilityRepository _vulnRepo; private readonly TenantConfigurationService _configService; private readonly RateLimitService _rateLimitService; private readonly AutopilotDeviceValidator _autopilotDeviceValidator; @@ -30,7 +35,11 @@ namespace AutopilotMonitor.Functions.Functions.Ingest public IngestEventsFunction( ILogger logger, - TableStorageService storageService, + ISessionRepository sessionRepo, + IMetricsRepository metricsRepo, + IMaintenanceRepository maintenanceRepo, + IRuleRepository ruleRepo, + IVulnerabilityRepository vulnRepo, TenantConfigurationService configService, RateLimitService rateLimitService, AutopilotDeviceValidator autopilotDeviceValidator, @@ -45,7 +54,11 @@ namespace AutopilotMonitor.Functions.Functions.Ingest SignalRNotificationService signalRNotification) { _logger = logger; - _storageService = storageService; + _sessionRepo = sessionRepo; + _metricsRepo = metricsRepo; + _maintenanceRepo = maintenanceRepo; + _ruleRepo = ruleRepo; + _vulnRepo = vulnRepo; _configService = configService; _rateLimitService = rateLimitService; _autopilotDeviceValidator = autopilotDeviceValidator; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs index fa0cb6ae..2846a200 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs @@ -1,6 +1,7 @@ using System.Net; using AutopilotMonitor.Functions.Helpers; using AutopilotMonitor.Functions.Services; +using AutopilotMonitor.Shared.DataAccess; using AutopilotMonitor.Shared.Models; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; @@ -12,7 +13,7 @@ namespace AutopilotMonitor.Functions.Functions.Reports { private readonly ILogger _logger; private readonly SessionReportService _sessionReportService; - private readonly TableStorageService _storageService; + private readonly IMaintenanceRepository _maintenanceRepo; private readonly GlobalAdminService _globalAdminService; private readonly TelegramNotificationService _telegramNotificationService; private readonly GlobalNotificationService _globalNotificationService; @@ -20,14 +21,14 @@ namespace AutopilotMonitor.Functions.Functions.Reports public SubmitSessionReportFunction( ILogger logger, SessionReportService sessionReportService, - TableStorageService storageService, + IMaintenanceRepository maintenanceRepo, GlobalAdminService globalAdminService, TelegramNotificationService telegramNotificationService, GlobalNotificationService globalNotificationService) { _logger = logger; _sessionReportService = sessionReportService; - _storageService = storageService; + _maintenanceRepo = maintenanceRepo; _globalAdminService = globalAdminService; _telegramNotificationService = telegramNotificationService; _globalNotificationService = globalNotificationService; @@ -85,7 +86,7 @@ namespace AutopilotMonitor.Functions.Functions.Reports // Log audit entry — skip for Global Admins if (!isGlobalAdmin) { - await _storageService.LogAuditEntryAsync( + await _maintenanceRepo.LogAuditEntryAsync( request.TenantId, "CREATE", "SessionReport", diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/DeleteSessionFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/DeleteSessionFunction.cs index 9f239f4d..bd76848c 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/DeleteSessionFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/DeleteSessionFunction.cs @@ -1,6 +1,6 @@ using System.Net; using AutopilotMonitor.Functions.Helpers; -using AutopilotMonitor.Functions.Services; +using AutopilotMonitor.Shared.DataAccess; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; @@ -10,14 +10,17 @@ namespace AutopilotMonitor.Functions.Functions.Sessions public class DeleteSessionFunction { private readonly ILogger _logger; - private readonly TableStorageService _storageService; + private readonly ISessionRepository _sessionRepo; + private readonly IMaintenanceRepository _maintenanceRepo; public DeleteSessionFunction( ILogger logger, - TableStorageService storageService) + ISessionRepository sessionRepo, + IMaintenanceRepository maintenanceRepo) { _logger = logger; - _storageService = storageService; + _sessionRepo = sessionRepo; + _maintenanceRepo = maintenanceRepo; } [Function("DeleteSession")] @@ -36,22 +39,22 @@ namespace AutopilotMonitor.Functions.Functions.Sessions _logger.LogInformation($"Deleting session {sessionId} for tenant {tenantId} by user {userIdentifier}"); // Delete all related data for this session - var eventsDeleted = await _storageService.DeleteSessionEventsAsync(tenantId, sessionId); + var eventsDeleted = await _maintenanceRepo.DeleteSessionEventsAsync(tenantId, sessionId); _logger.LogInformation($"Deleted {eventsDeleted} events for session {sessionId}"); - var ruleResultsDeleted = await _storageService.DeleteSessionRuleResultsAsync(tenantId, sessionId); + var ruleResultsDeleted = await _maintenanceRepo.DeleteSessionRuleResultsAsync(tenantId, sessionId); _logger.LogInformation($"Deleted {ruleResultsDeleted} rule results for session {sessionId}"); - var appSummariesDeleted = await _storageService.DeleteSessionAppInstallSummariesAsync(tenantId, sessionId); + var appSummariesDeleted = await _maintenanceRepo.DeleteSessionAppInstallSummariesAsync(tenantId, sessionId); _logger.LogInformation($"Deleted {appSummariesDeleted} app install summaries for session {sessionId}"); // Delete the session itself - var sessionDeleted = await _storageService.DeleteSessionAsync(tenantId, sessionId); + var sessionDeleted = await _sessionRepo.DeleteSessionAsync(tenantId, sessionId); if (sessionDeleted) { // Log audit entry with actual user identifier - await _storageService.LogAuditEntryAsync( + await _maintenanceRepo.LogAuditEntryAsync( tenantId, "DELETE", "Session", diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/RegisterSessionFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/RegisterSessionFunction.cs index 51d70804..5d62893d 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/RegisterSessionFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/RegisterSessionFunction.cs @@ -14,7 +14,8 @@ namespace AutopilotMonitor.Functions.Functions.Sessions public class RegisterSessionFunction { private readonly ILogger _logger; - private readonly TableStorageService _storageService; + private readonly ISessionRepository _sessionRepo; + private readonly IMetricsRepository _metricsRepo; private readonly TenantConfigurationService _configService; private readonly RateLimitService _rateLimitService; private readonly AutopilotDeviceValidator _autopilotDeviceValidator; @@ -23,7 +24,8 @@ namespace AutopilotMonitor.Functions.Functions.Sessions public RegisterSessionFunction( ILogger logger, - TableStorageService storageService, + ISessionRepository sessionRepo, + IMetricsRepository metricsRepo, TenantConfigurationService configService, RateLimitService rateLimitService, AutopilotDeviceValidator autopilotDeviceValidator, @@ -31,7 +33,8 @@ namespace AutopilotMonitor.Functions.Functions.Sessions BootstrapSessionService bootstrapSessionService) { _logger = logger; - _storageService = storageService; + _sessionRepo = sessionRepo; + _metricsRepo = metricsRepo; _configService = configService; _rateLimitService = rateLimitService; _autopilotDeviceValidator = autopilotDeviceValidator; @@ -102,7 +105,7 @@ namespace AutopilotMonitor.Functions.Functions.Sessions _logger.LogInformation($"Registering session {registration.SessionId} for tenant {registration.TenantId} (Device: {validation.CertificateThumbprint})"); // Store session in Azure Table Storage - var stored = await _storageService.StoreSessionAsync(registration); + var stored = await _sessionRepo.StoreSessionAsync(registration); if (!stored) { @@ -111,11 +114,11 @@ namespace AutopilotMonitor.Functions.Functions.Sessions } // Increment platform stats (fire-and-forget, non-blocking) - _ = _storageService.IncrementPlatformStatAsync("TotalEnrollments") + _ = _metricsRepo.IncrementPlatformStatAsync("TotalEnrollments") .ContinueWith(t => _logger.LogWarning(t.Exception?.InnerException, "Fire-and-forget IncrementPlatformStatAsync failed"), TaskContinuationOptions.OnlyOnFaulted); // Retrieve the stored session to include full data in SignalR message - var session = await _storageService.GetSessionAsync(registration.TenantId, registration.SessionId); + var session = await _sessionRepo.GetSessionAsync(registration.TenantId, registration.SessionId); // Check if admin has already marked this session as terminal (e.g., agent restarted after admin override) string? adminAction = null; diff --git a/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.cs b/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.cs index 72f20da5..0491fe7f 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/MaintenanceService.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using AutopilotMonitor.Shared.DataAccess; using AutopilotMonitor.Shared.Models; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; diff --git a/src/Backend/AutopilotMonitor.Functions/Services/PlatformMetricsService.cs b/src/Backend/AutopilotMonitor.Functions/Services/PlatformMetricsService.cs index cb498c1a..dcc47963 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/PlatformMetricsService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/PlatformMetricsService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using AutopilotMonitor.Shared.DataAccess; using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Services @@ -13,7 +14,7 @@ namespace AutopilotMonitor.Functions.Services /// public class PlatformMetricsService { - private readonly TableStorageService _storageService; + private readonly ISessionRepository _sessionRepo; private readonly ILogger _logger; // In-memory cache (same pattern as UsageMetricsService) @@ -23,10 +24,10 @@ namespace AutopilotMonitor.Functions.Services private static readonly object _cacheLock = new object(); public PlatformMetricsService( - TableStorageService storageService, + ISessionRepository sessionRepo, ILogger logger) { - _storageService = storageService; + _sessionRepo = sessionRepo; _logger = logger; } @@ -73,7 +74,7 @@ namespace AutopilotMonitor.Functions.Services private async Task ComputePlatformMetricsInternalAsync() { // 1. Fetch the 100 most recent sessions across all tenants - var page = await _storageService.GetAllSessionsAsync(maxResults: 100); + var page = await _sessionRepo.GetAllSessionsAsync(maxResults: 100); var allSessions = page.Sessions; if (allSessions.Count == 0) @@ -88,7 +89,7 @@ namespace AutopilotMonitor.Functions.Services { try { - var events = await _storageService.GetSessionEventsAsync(session.TenantId, session.SessionId); + var events = await _sessionRepo.GetSessionEventsAsync(session.TenantId, session.SessionId); var snapshots = events .Where(e => e.EventType == "agent_metrics_snapshot" && e.Data != null) .Select(e => e.Data) diff --git a/src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.cs b/src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.cs index 1fe2d4b9..b47350d9 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/RuleEngine.cs @@ -1,4 +1,5 @@ using System.Text.RegularExpressions; +using AutopilotMonitor.Shared.DataAccess; using AutopilotMonitor.Shared.Models; using Microsoft.Extensions.Logging; @@ -12,13 +13,15 @@ namespace AutopilotMonitor.Functions.Services public partial class RuleEngine { private readonly AnalyzeRuleService _ruleService; - private readonly TableStorageService _storageService; + private readonly IRuleRepository _ruleRepo; + private readonly ISessionRepository _sessionRepo; private readonly ILogger _logger; - public RuleEngine(AnalyzeRuleService ruleService, TableStorageService storageService, ILogger logger) + public RuleEngine(AnalyzeRuleService ruleService, IRuleRepository ruleRepo, ISessionRepository sessionRepo, ILogger logger) { _ruleService = ruleService; - _storageService = storageService; + _ruleRepo = ruleRepo; + _sessionRepo = sessionRepo; _logger = logger; } @@ -34,7 +37,7 @@ namespace AutopilotMonitor.Functions.Services try { var activeRules = await _ruleService.GetActiveRulesForTenantAsync(tenantId); - var allEvents = await _storageService.GetSessionEventsAsync(tenantId, sessionId); + var allEvents = await _sessionRepo.GetSessionEventsAsync(tenantId, sessionId); if (allEvents.Count == 0) { @@ -51,7 +54,7 @@ namespace AutopilotMonitor.Functions.Services } else { - var existingResults = await _storageService.GetRuleResultsAsync(tenantId, sessionId); + var existingResults = await _ruleRepo.GetRuleResultsAsync(tenantId, sessionId); existingRuleIds = new HashSet(existingResults.Select(r => r.RuleId)); } diff --git a/src/Backend/AutopilotMonitor.Functions/Services/UsageMetricsService.cs b/src/Backend/AutopilotMonitor.Functions/Services/UsageMetricsService.cs index fc23469b..f1e5aa3a 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/UsageMetricsService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/UsageMetricsService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using AutopilotMonitor.Shared.DataAccess; using AutopilotMonitor.Shared.Models; using Microsoft.Extensions.Logging; @@ -13,7 +14,8 @@ namespace AutopilotMonitor.Functions.Services /// public class UsageMetricsService { - private readonly TableStorageService _storageService; + private readonly IMetricsRepository _metricsRepo; + private readonly IMaintenanceRepository _maintenanceRepo; private readonly ILogger _logger; // In-memory cache @@ -23,10 +25,12 @@ namespace AutopilotMonitor.Functions.Services private static readonly object _cacheLock = new object(); public UsageMetricsService( - TableStorageService storageService, + IMetricsRepository metricsRepo, + IMaintenanceRepository maintenanceRepo, ILogger logger) { - _storageService = storageService; + _metricsRepo = metricsRepo; + _maintenanceRepo = maintenanceRepo; _logger = logger; } @@ -95,7 +99,7 @@ namespace AutopilotMonitor.Functions.Services // Query sessions from the last 90 days only — covers all displayed metrics (today/7d/30d) // with a generous margin. Avoids loading the entire table into memory. // "Total" counters use PlatformStats (cumulative, already tracked separately). - var allSessions = await _storageService.GetSessionsByDateRangeAsync(DateTime.UtcNow.AddDays(-90), DateTime.UtcNow.AddDays(1)); + var allSessions = await _maintenanceRepo.GetSessionsByDateRangeAsync(DateTime.UtcNow.AddDays(-90), DateTime.UtcNow.AddDays(1)); var now = DateTime.UtcNow; var today = now.Date; @@ -132,7 +136,7 @@ namespace AutopilotMonitor.Functions.Services }; // User Metrics (from UserActivity table) - var userActivity = await _storageService.GetAllUserActivityMetricsAsync(); + var userActivity = await _metricsRepo.GetAllUserActivityMetricsAsync(); var userMetrics = new UserMetrics { Total = userActivity.TotalUniqueUsers, @@ -196,7 +200,7 @@ namespace AutopilotMonitor.Functions.Services }; // Platform Stats (cumulative since release) - var platformStats = await _storageService.GetPlatformStatsAsync(); + var platformStats = await _metricsRepo.GetPlatformStatsAsync(); return new PlatformUsageMetrics { @@ -223,7 +227,7 @@ namespace AutopilotMonitor.Functions.Services private async Task ComputeTenantUsageMetricsInternalAsync(string tenantId) { // Query sessions for specific tenant only — last 90 days - var tenantSessions = await _storageService.GetSessionsByDateRangeAsync(DateTime.UtcNow.AddDays(-90), DateTime.UtcNow.AddDays(1), tenantId); + var tenantSessions = await _maintenanceRepo.GetSessionsByDateRangeAsync(DateTime.UtcNow.AddDays(-90), DateTime.UtcNow.AddDays(1), tenantId); var now = DateTime.UtcNow; var today = now.Date; @@ -252,7 +256,7 @@ namespace AutopilotMonitor.Functions.Services }; // User Metrics (from UserActivity table) - var userActivity = await _storageService.GetUserActivityMetricsAsync(tenantId); + var userActivity = await _metricsRepo.GetUserActivityMetricsAsync(tenantId); var userMetrics = new UserMetrics { Total = userActivity.TotalUniqueUsers, diff --git a/src/Shared/AutopilotMonitor.Shared/DataAccess/ISessionRepository.cs b/src/Shared/AutopilotMonitor.Shared/DataAccess/ISessionRepository.cs index bfdcaea6..3227cffe 100644 --- a/src/Shared/AutopilotMonitor.Shared/DataAccess/ISessionRepository.cs +++ b/src/Shared/AutopilotMonitor.Shared/DataAccess/ISessionRepository.cs @@ -35,6 +35,7 @@ namespace AutopilotMonitor.Shared.DataAccess // --- Events --- Task StoreEventAsync(EnrollmentEvent evt); + Task> StoreEventsBatchAsync(List events); Task> GetSessionEventsAsync(string tenantId, string sessionId, int maxResults = 1000); // --- Search ---