Mercurial > servermonitor
comparison 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 |
comparison
equal
deleted
inserted
replaced
16:7626b099aefd | 17:68d7834dc28e |
---|---|
1 using ServerMonitorApp.Properties; | 1 using ServerMonitorApp.Properties; |
2 using System; | 2 using System; |
3 using System.Collections.Generic; | 3 using System.Collections.Generic; |
4 using System.IO; | 4 using System.IO; |
5 using System.Linq; | 5 using System.Linq; |
6 using System.Reflection; | |
7 using System.Text; | 6 using System.Text; |
8 using System.Threading.Tasks; | |
9 | 7 |
10 namespace ServerMonitorApp | 8 namespace ServerMonitorApp |
11 { | 9 { |
10 /// <summary>Manages reading and writing check results to a log file.</summary> | |
12 public class Logger | 11 public class Logger |
13 { | 12 { |
14 private const int logVersion = 1; | 13 private const int logVersion = 1; |
15 private readonly string logFile; | 14 private readonly string logFile; |
16 | 15 |
16 /// <summary>Logger constructor.</summary> | |
17 /// <param name="file">The path of the log file to use.</param> | |
17 public Logger(string file) | 18 public Logger(string file) |
18 { | 19 { |
19 logFile = file; | 20 logFile = file; |
20 } | 21 } |
21 | 22 |
23 /// <summary>Appends a string to the log file, creating the log file if it does not exist.</summary> | |
24 /// <param name="logString">The string to log.</param> | |
22 public async void Log(string logString) | 25 public async void Log(string logString) |
23 { | 26 { |
27 // Create the file if it does not exist. | |
28 // Write the current version at the beginning in case we ever change the format. | |
24 if (!File.Exists(logFile)) | 29 if (!File.Exists(logFile)) |
25 logString = "Server Monitor log version " + logVersion + Environment.NewLine + logString; | 30 logString = "Server Monitor log version " + logVersion + Environment.NewLine + logString; |
31 // Write the message. | |
26 using (FileStream stream = new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.Read, 4096, true)) | 32 using (FileStream stream = new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.Read, 4096, true)) |
27 using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8)) | 33 using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8)) |
28 { | 34 { |
29 await writer.WriteLineAsync(logString); | 35 await writer.WriteLineAsync(logString); |
30 } | 36 } |
31 } | 37 } |
32 | 38 |
39 /// <summary>Appends a check result to the log file, creating the log file if it does not exist.</summary> | |
40 /// <param name="result">The check result to log.</param> | |
33 public void Log(CheckResult result) | 41 public void Log(CheckResult result) |
34 { | 42 { |
35 Log(result.ToLogString()); | 43 Log(result.ToLogString()); |
36 } | 44 } |
37 | 45 |
46 /// <summary>Reads all check results from the log for a server.</summary> | |
47 /// <param name="server">The server whose check results should be read.</param> | |
48 /// <returns>A list of all check results found in the log file for the given server.</returns> | |
38 public IList<CheckResult> Read(Server server) | 49 public IList<CheckResult> Read(Server server) |
39 { | 50 { |
51 // Store the checks by ID. | |
40 Dictionary<int, Check> checks = server.Checks.ToDictionary(c => c.Id); | 52 Dictionary<int, Check> checks = server.Checks.ToDictionary(c => c.Id); |
41 List<CheckResult> results = new List<CheckResult>(); | 53 List<CheckResult> results = new List<CheckResult>(); |
42 using (FileStream stream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.Read)) | 54 using (FileStream stream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.Read)) |
43 using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) | 55 using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) |
44 { | 56 { |
57 // Read through the whole file, searching for results belonging to the server. | |
45 while (true) | 58 while (true) |
46 { | 59 { |
47 try | 60 try |
48 { | 61 { |
49 string line = reader.ReadLine(); | 62 string line = reader.ReadLine(); |
63 // Exit the loop when we reach the end. | |
50 if (line == null) | 64 if (line == null) |
51 break; | 65 break; |
66 // The check ID is a fixed length. | |
67 // Parse it and see if it matches any of the checks we are interested in. | |
52 if (int.TryParse(line.Substring(0, 5), out int id) && checks.TryGetValue(id, out Check check)) | 68 if (int.TryParse(line.Substring(0, 5), out int id) && checks.TryGetValue(id, out Check check)) |
53 { | 69 { |
70 // If it is, add it to our results list. | |
54 results.Add(CheckResult.FromLogString(check, line)); | 71 results.Add(CheckResult.FromLogString(check, line)); |
55 } | 72 } |
56 } | 73 } |
74 // Don't know why this catch block is empty. | |
75 // Maybe to ignore errors if the file does not exist? | |
57 catch (Exception) { } | 76 catch (Exception) { } |
58 } | 77 } |
59 } | 78 } |
79 // Return the newest results first since that's how they are displayed. | |
60 results.Reverse(); | 80 results.Reverse(); |
61 return results; | 81 return results; |
62 } | 82 } |
63 | 83 |
84 /// <summary>Removes old entries from the log.</summary> | |
64 public async void TrimLog() | 85 public async void TrimLog() |
65 { | 86 { |
87 // Delete entries older than this date. | |
66 DateTime maxAge = DateTime.Now.AddDays(-1 * Settings.Default.KeepLogDays); | 88 DateTime maxAge = DateTime.Now.AddDays(-1 * Settings.Default.KeepLogDays); |
67 string tempFile = logFile + ".tmp"; | 89 string tempFile = logFile + ".tmp"; |
68 try | 90 try |
69 { | 91 { |
92 // Read through the log file and check the date of each entry. | |
93 // If it is newer than the max age, copy it to a temporary file. | |
70 using (FileStream stream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.Read)) | 94 using (FileStream stream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.Read)) |
71 using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) | 95 using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) |
72 using (FileStream outStream = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.None)) | 96 using (FileStream outStream = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.None)) |
73 using (StreamWriter writer = new StreamWriter(outStream, Encoding.UTF8)) | 97 using (StreamWriter writer = new StreamWriter(outStream, Encoding.UTF8)) |
74 { | 98 { |
85 } | 109 } |
86 } | 110 } |
87 catch (Exception) { } | 111 catch (Exception) { } |
88 } | 112 } |
89 } | 113 } |
114 // Delete the original file and rename the temporary file that contains only recent entries. | |
90 File.Delete(logFile); | 115 File.Delete(logFile); |
91 File.Move(tempFile, logFile); | 116 File.Move(tempFile, logFile); |
92 } | 117 } |
93 catch (FileNotFoundException) | 118 catch (FileNotFoundException) |
94 { | 119 { |