public async Task ClearUnresolvedGapReportData(int serverId, GapActivityType gapActivityType) { using (var conn = this.connectionFactory.GetEddsPerformanceConnection()) { await conn.ExecuteAsync(Resources.Reports_Gap_ClearUnresolvedActivityType, new { ActivityType = gapActivityType, serverId }); } }
public async Task CreateGapReport <TGap>( Hour hour, Server server, IList <TGap> gaps, GapActivityType gapType) where TGap : Gap { // Add new resolved gaps of gapsize greater than the threshold window await gaps.Select(g => new GapReportEntry { DatabaseId = g.DatabaseId, ActivityType = (int)g.ActivityType, LastActivity = g.Start, GapResolutionDate = g.End, GapSize = g.Duration.Value }) .Select(g => this.recoverabilityIntegrityReportRepository.CreateGapReportData(g)) .WhenAllStreamed(1); // Clear unresolved gaps of report type await this.recoverabilityIntegrityReportRepository.ClearUnresolvedGapReportData(server.ServerId, gapType); // Get unresolved gaps var unresolvedGaps = await this.databaseService.ReadUnresolvedGapsAsync(hour, server, gapType); // Get 'Now' for unresolved gaps var now = hour.GetNextHour(); var unresolvedGapReports = unresolvedGaps.Select(g => new GapReportEntry { DatabaseId = g.DatabaseId, ActivityType = (int)g.ActivityType, LastActivity = g.Start, GapResolutionDate = null, GapSize = (int)(now - g.Start).TotalSeconds }); // Add unresolved gaps await unresolvedGapReports.Select(g => this.recoverabilityIntegrityReportRepository.CreateGapReportData(g)) .WhenAllStreamed(1); }
public async Task <CoverageMetricData> CaptureCoverageData <TGap>(Hour hour, Server server, GapActivityType activityType) where TGap : Gap { var windowInDays = RiDefaults.WindowInDays; var windowInSeconds = (int)TimeSpan.FromDays(windowInDays).TotalSeconds; var windowExceededByDate = hour.HourTimeStamp.AddDays(-windowInDays); // Get databases exceeding the window for unresolved gaps var databaseCount = await this.databaseRepository.ReadCountByServerAsync(server); var databasesExceedingWindowUnresolved = await this.databaseRepository.ReadOutOfDateDatabasesAsync(server, windowExceededByDate, activityType); // Get databases exceeding the window for gaps recorded for the hour // Since the query is already filtering on gaps with duration greater than the window any database associated with any gap returned is in violation var largestGaps = await this.databaseGapsRepository.ReadGapsLargerThanForHourAsync <TGap>(server, hour, activityType, windowInSeconds); // Union the databases exceeding the window together by db Id and distinct them var databasesExceedingWindow = largestGaps .Select(g => g.DatabaseId) .Union(databasesExceedingWindowUnresolved.Select(db => db.Id)) .Distinct() .ToList(); var databasesCovered = databaseCount - databasesExceedingWindow.Count; // Write gaps exceeding to report table await this.gapReporter.CreateGapReport(hour, server, largestGaps, activityType); return(new CoverageMetricData { TotalDatabases = databaseCount, DatabasesCovered = databasesCovered }); }
public async Task <IList <Database> > ReadOutOfDateDatabasesAsync(Server server, DateTime windowExceededDate, GapActivityType activityType) { using (var conn = connectionFactory.GetEddsPerformanceConnection()) { var parameters = new { server.ServerId, windowExceededDate }; return(activityType == GapActivityType.Dbcc ? await conn.QueryAsync <Database>(Resources.Database_ReadOutOfDateDatabasesByDbccs, parameters).ToListAsync().ConfigureAwait(false) : await conn.QueryAsync <Database>(Resources.Database_ReadOutOfDateDatabasesByBackups, parameters).ToListAsync().ConfigureAwait(false)); } }
public async Task <DateTime?> ReadMostOutOfDateActivityByServerAsync(Server server, GapActivityType activityType) { using (var conn = connectionFactory.GetEddsPerformanceConnection()) { return(activityType == GapActivityType.Dbcc ? await conn.QueryFirstOrDefaultAsync <DateTime?>(Resources.Database_ReadMostOutOfDateDbccByServer, server).ConfigureAwait(false) : await conn.QueryFirstOrDefaultAsync <DateTime?>(Resources.Database_ReadMostOutOfDateBackupFullDiffByServer, server).ConfigureAwait(false)); } }
/// <summary> /// Returns gap models as if they were created, but are not stored in the data store /// </summary> /// <param name="hour">Current hour</param> /// <param name="server">Server to get databases from</param> /// <returns></returns> public async Task <IList <Gap> > ReadUnresolvedGapsAsync(Hour hour, Server server, GapActivityType activityType) { var databases = await this.databaseRepository.ReadByServerIdAsync(server.ServerId); switch (activityType) { case GapActivityType.Backup: return(databases.Where(db => db.MostRecentBackupAnyType.HasValue && db.MostRecentBackupAnyType.Value < hour.HourTimeStamp) .Select( db => new Gap { ActivityType = activityType, DatabaseId = db.Id, Start = db.MostRecentBackupAnyType.Value, Duration = (int)(hour.HourTimeStamp - db.MostRecentBackupAnyType.Value).TotalSeconds }).ToList()); case GapActivityType.BackupFullAndDiff: return(databases.Where(db => (db.LastBackupDiffDate.HasValue && db.LastBackupDiffDate.Value < hour.HourTimeStamp) || (db.LastBackupFullDate.HasValue && db.LastBackupFullDate.Value < hour.HourTimeStamp)) .Select( db => { var start = (db.LastBackupDiffDate.HasValue && db.LastBackupDiffDate.Value < hour.HourTimeStamp) ? db.LastBackupDiffDate.Value : db.LastBackupFullDate.Value; return new Gap { ActivityType = activityType, DatabaseId = db.Id, Start = start, Duration = (int)(hour.HourTimeStamp - start).TotalSeconds }; }).ToList()); case GapActivityType.Dbcc: return(databases.Where(db => db.LastDbccDate.HasValue && db.LastDbccDate.Value < hour.HourTimeStamp) .Select( db => new Gap { ActivityType = activityType, DatabaseId = db.Id, Start = db.LastDbccDate.Value, Duration = (int)(hour.HourTimeStamp - db.LastDbccDate.Value).TotalSeconds }).ToList()); default: throw new ArgumentOutOfRangeException(nameof(activityType), activityType, null); } }
public async Task <FrequencyMetricData> CaptureFrequencyData <TGap>(Hour hour, Server server, GapActivityType activityType) where TGap : Gap { var endOfCurrentHour = hour.HourTimeStamp.AddHours(1); var windowInDays = RiDefaults.WindowInDays; // Get the largest unresolved gap for all the databases for the server var mostOutOfDateActivityForServer = await this.databaseRepository.ReadMostOutOfDateActivityByServerAsync(server, activityType); var largestUnresolvedGap = mostOutOfDateActivityForServer.HasValue ? (double?)(endOfCurrentHour - mostOutOfDateActivityForServer.Value).TotalDays : null; // Get the largest gap for gaps recorded for the hour var largestGap = await this.databaseGapsRepository.ReadLargestGapsForHourAsync <TGap>(server, hour, activityType); var largestGapInDays = largestGap?.Duration.HasValue ?? false ? (double?)TimeSpan.FromSeconds(largestGap.Duration.Value).TotalDays : null; await this.logger.LogVerboseAsync($"Window exceeded by largest {activityType} gap: {largestGapInDays} and for unresolved {activityType} gaps: {largestUnresolvedGap}. Hour: {hour.Id}-{hour.HourTimeStamp} Server: {server.ServerName}"); var worstWindowExceededBy = new[] { largestGapInDays, largestUnresolvedGap } .Select(gap => gap > windowInDays ? gap - windowInDays : null) // subtract the allowed 9 day window if the window is greater than 9 days. Else, the window has not been exceeded. .Max(); // Take the largest windowExceededBy return(new FrequencyMetricData { WindowExceededBy = worstWindowExceededBy.HasValue ? (int?)worstWindowExceededBy : null }); }
/// <inheritdoc /> public async Task <IList <TGap> > ReadLargestGapsForEachDatabaseAsync <TGap>(Server server, Hour hour, GapActivityType activityType) { using (var conn = this.connectionFactory.GetEddsPerformanceConnection()) { return((await conn.QueryAsync <TGap>( Resources.DatabaseGap_ReadLargestGapsForHourAllDatabase, new { server.ServerId, hourTimeStampStart = hour.HourTimeStamp, hourTimeStampEnd = hour.GetHourEnd(), activityType }).ConfigureAwait(false)).ToList()); } }