Mercurial > servermonitor
diff ServerMonitor/Objects/Logger.cs @ 17:68d7834dc28e
More comments.
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Sat, 25 May 2019 15:14:26 -0400 |
parents | 7127d5b5ac75 |
children |
line wrap: on
line diff
--- a/ServerMonitor/Objects/Logger.cs Tue Apr 30 20:40:58 2019 -0400 +++ b/ServerMonitor/Objects/Logger.cs Sat May 25 15:14:26 2019 -0400 @@ -3,26 +3,32 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; using System.Text; -using System.Threading.Tasks; namespace ServerMonitorApp { + /// <summary>Manages reading and writing check results to a log file.</summary> public class Logger { private const int logVersion = 1; private readonly string logFile; + /// <summary>Logger constructor.</summary> + /// <param name="file">The path of the log file to use.</param> public Logger(string file) { logFile = file; } + /// <summary>Appends a string to the log file, creating the log file if it does not exist.</summary> + /// <param name="logString">The string to log.</param> public async void Log(string logString) { + // Create the file if it does not exist. + // Write the current version at the beginning in case we ever change the format. if (!File.Exists(logFile)) logString = "Server Monitor log version " + logVersion + Environment.NewLine + logString; + // Write the message. using (FileStream stream = new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.Read, 4096, true)) using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8)) { @@ -30,43 +36,61 @@ } } + /// <summary>Appends a check result to the log file, creating the log file if it does not exist.</summary> + /// <param name="result">The check result to log.</param> public void Log(CheckResult result) { Log(result.ToLogString()); } + /// <summary>Reads all check results from the log for a server.</summary> + /// <param name="server">The server whose check results should be read.</param> + /// <returns>A list of all check results found in the log file for the given server.</returns> public IList<CheckResult> Read(Server server) { + // Store the checks by ID. Dictionary<int, Check> checks = server.Checks.ToDictionary(c => c.Id); List<CheckResult> results = new List<CheckResult>(); using (FileStream stream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.Read)) using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { + // Read through the whole file, searching for results belonging to the server. while (true) { try { string line = reader.ReadLine(); + // Exit the loop when we reach the end. if (line == null) break; + // The check ID is a fixed length. + // Parse it and see if it matches any of the checks we are interested in. if (int.TryParse(line.Substring(0, 5), out int id) && checks.TryGetValue(id, out Check check)) { + // If it is, add it to our results list. results.Add(CheckResult.FromLogString(check, line)); } } + // Don't know why this catch block is empty. + // Maybe to ignore errors if the file does not exist? catch (Exception) { } } } + // Return the newest results first since that's how they are displayed. results.Reverse(); return results; } + /// <summary>Removes old entries from the log.</summary> public async void TrimLog() { + // Delete entries older than this date. DateTime maxAge = DateTime.Now.AddDays(-1 * Settings.Default.KeepLogDays); string tempFile = logFile + ".tmp"; try { + // Read through the log file and check the date of each entry. + // If it is newer than the max age, copy it to a temporary file. using (FileStream stream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.Read)) using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) using (FileStream outStream = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.None)) @@ -87,6 +111,7 @@ catch (Exception) { } } } + // Delete the original file and rename the temporary file that contains only recent entries. File.Delete(logFile); File.Move(tempFile, logFile); }