/// <summary> /// Logs a new data gap for processing. /// </summary> /// <param name="startTime">Start time of data gap.</param> /// <param name="endTime">End time of data gap.</param> /// <param name="forceLog">Indicates whether to skip data gap validation and force the outage to be logged.</param> /// <returns><c>true</c> if data gap was logged for processing; otherwise, <c>false</c>.</returns> /// <remarks> /// Data gap will not be logged for processing if the <paramref name="startTime"/> and <paramref name="endTime"/> do not represent /// a valid time span for recovery according to <see cref="MinimumRecoverySpan"/> and <see cref="MaximumRecoverySpan"/>. /// </remarks> public bool LogDataGap(DateTimeOffset startTime, DateTimeOffset endTime, bool forceLog = false) { if (m_disposed) { throw new InvalidOperationException("Data gap recoverer has been disposed. Cannot log data gap for processing."); } if ((object)m_dataGapLog == null) { throw new InvalidOperationException("Data gap recoverer has not been initialized. Cannot log data gap for processing."); } OnStatusMessage(MessageLevel.Info, $"Data gap recovery requested for period \"{startTime.ToString(OutageLog.DateTimeFormat, CultureInfo.InvariantCulture)}\" - \"{endTime.ToString(OutageLog.DateTimeFormat, CultureInfo.InvariantCulture)}\"..."); Time dataGapSpan = (endTime - startTime).TotalSeconds; // Only log data gap for processing if it is in an acceptable time span for recovery if (forceLog || dataGapSpan >= m_minimumRecoverySpan && dataGapSpan <= m_maximumRecoverySpan) { // Since local clock may float we add some buffer around recovery window m_dataGapLog.Add(new Outage(startTime.AddSeconds(StartRecoveryBuffer), endTime.AddSeconds(EndRecoveryBuffer))); return(true); } Time rangeLimit; string rangeLimitText; if (dataGapSpan < m_minimumRecoverySpan) { rangeLimit = m_minimumRecoverySpan; rangeLimitText = "minimum"; } else { rangeLimit = m_maximumRecoverySpan; rangeLimitText = "maximum"; } OnStatusMessage(MessageLevel.Info, $"Skipped data gap recovery for {Time.ToElapsedTimeString(dataGapSpan, 2)} of missed data - outside configured {rangeLimitText} range of {Time.ToElapsedTimeString(rangeLimit, 2)}."); return(false); }
static void Main(string[] args) { string line; Console.WriteLine("Type HELP for a list of options."); Console.WriteLine(); using (OutageLog log = new OutageLog()) { log.FileName = @"C:\Users\swills\test.txt"; log.LogModified += (sender, arg) => Console.WriteLine("Modified!"); log.Initialize(); while (!(line = Console.ReadLine()).Equals("EXIT", StringComparison.OrdinalIgnoreCase)) { switch (line.ToUpper()) { case "ADD": log.Add(DateTimeOffset.UtcNow.AddSeconds(-1.0D), DateTimeOffset.UtcNow); Console.WriteLine($"Count: {log.Count}"); break; case "REMOVE": log.Remove(log.First()); Console.WriteLine($"Count: {log.Count}"); break; case "DUMP": foreach (Outage outage in log.Outages) { Console.WriteLine($"{outage.Start:yyyy-MM-dd HH:mm:ss.fff};{outage.End:yyyy-MM-dd HH:mm:ss.fff}"); } Console.WriteLine(); break; case "STATUS": Console.WriteLine(log.Status); Console.WriteLine(); break; case "HELP": Console.WriteLine("ADD - Adds a new outage to the log"); Console.WriteLine("REMOVE - Removes the first outage from the log"); Console.WriteLine("DUMP - Displays the contents of the log"); Console.WriteLine("STATUS - Displays detailed status of the log"); Console.WriteLine("EXIT - Exits this application"); Console.WriteLine(); break; } } } }