comparison ServerMonitor/Objects/Checks/Check.cs @ 2:453ecc1ed9ea

Disk space check
author Brad Greco <brad@bgreco.net>
date Sun, 06 Jan 2019 20:49:08 -0500
parents ServerMonitor/Objects/Check.cs@9e92780ebc0f
children 3142e52cbe69
comparison
equal deleted inserted replaced
1:9e92780ebc0f 2:453ecc1ed9ea
1 using System;
2 using System.Linq;
3 using System.Text;
4 using System.Text.RegularExpressions;
5 using System.Threading;
6 using System.Threading.Tasks;
7 using System.Xml.Serialization;
8
9 namespace ServerMonitorApp
10 {
11 /*public enum CheckType
12 {
13 Command
14 }*/
15
16 public enum CheckStatus
17 {
18 Success,
19 Information,
20 Warning,
21 Error,
22 Running,
23 Disabled,
24 }
25
26 public abstract class Check
27 {
28 private static Type[] _checkTypes;
29
30 public static Type[] CheckTypes
31 {
32 get
33 {
34 return _checkTypes ?? (_checkTypes = typeof(Check).Assembly.GetTypes()
35 .Where(t => t.IsSubclassOf(typeof(Check)))
36 .OrderBy(t => t.GetAttribute<DisplayWeightAttribute>()?.DisplayWeight).ToArray());
37 }
38 }
39
40 public int Id { get; set; }
41
42 public string Name { get; set; }
43
44 /*public CheckType Type { get; set; }*/
45
46 public int Timeout { get; set; }
47
48 public bool Enabled { get; set; }
49
50 public Schedule Schedule { get; set; }
51
52 public DateTime LastRunTime { get; set; }
53
54 public DateTime LastScheduledRunTime { get; set; }
55
56 public DateTime NextRunTime { get; set; }
57
58 public string LastMessage { get; set; }
59
60 public CheckStatus Status { get; set; }
61
62 public CheckStatus FailStatus { get; set; }
63
64 [XmlIgnore]
65 public Server Server { get; set; }
66
67 public Check()
68 {
69 FailStatus = CheckStatus.Error;
70 }
71
72 public override string ToString()
73 {
74 return Name;
75 }
76
77 public virtual string Validate(bool saving = true)
78 {
79 string message = string.Empty;
80 if (Name.IsNullOrEmpty() && saving)
81 message += "Name cannot be blank." + Environment.NewLine;
82 return message;
83 }
84
85 //public virtual CheckStatus Execute()
86 //{
87 // //TODO
88 // throw new NotImplementedException();
89 //}
90
91 public async Task<CheckResult> ExecuteAsync(CancellationToken token = default(CancellationToken), bool update = true)
92 {
93 //TODO check cancellation token before proceeding
94 CheckResult result;
95 DateTime startTime = DateTime.Now;
96 try
97 {
98 Task<CheckResult> checkTask = ExecuteCheckAsync(token);
99 try
100 {
101 if (await Task.WhenAny(checkTask, Task.Delay(Timeout, token)) == checkTask)
102 {
103 result = await checkTask;
104 }
105 else
106 {
107 result = Fail("Timed out.");
108 }
109 }
110 catch (TaskCanceledException)
111 {
112 return null;
113 }
114 }
115 catch (Exception e)
116 {
117 result = Fail(e.GetBaseException().Message);
118 }
119 result.StartTime = startTime;
120 result.EndTime = DateTime.Now;
121 // If a check is executed from the CheckForm, we don't want to update the status or log the event.
122 if (update)
123 {
124 Status = result.CheckStatus;
125 LastMessage = result.Message;
126 LastRunTime = result.EndTime;
127 }
128 return result;
129 }
130
131 public CheckResult Pass(string message)
132 {
133 return new CheckResult(this, CheckStatus.Success, message);
134 }
135
136 public CheckResult Fail(string message)
137 {
138 return new CheckResult(this, FailStatus, message);
139 }
140
141 protected CheckResult Fail(Exception e)
142 {
143 return new CheckResult(this, FailStatus, e.GetBaseException().Message);
144 }
145
146 protected CheckResult GetIntResult(int expectedValue, int resultValue, string description)
147 {
148 if (expectedValue == resultValue)
149 return Pass(string.Format("{0}: {1}", description, resultValue));
150 else
151 return Fail(string.Format("{0}: {1} (expected: {2})", description, resultValue, expectedValue));
152 }
153
154 protected CheckResult GetStringResult(MatchType matchType, string expectedPattern, bool useRegex, string resultValue, string description)
155 {
156 bool match;
157 if (useRegex)
158 {
159 if (matchType.In(MatchType.Equals, MatchType.NotEquals))
160 {
161 if (!expectedPattern.StartsWith("^"))
162 expectedPattern = "^" + expectedPattern;
163 if (!expectedPattern.EndsWith("$"))
164 expectedPattern += "$";
165 }
166 Regex re = new Regex(expectedPattern, RegexOptions.Singleline);
167 match = re.IsMatch(resultValue);
168 }
169 else
170 {
171 if (matchType.In(MatchType.Equals, MatchType.NotEquals))
172 {
173 match = expectedPattern == resultValue;
174 }
175 else if (matchType.In(MatchType.Contains, MatchType.NotContains))
176 {
177 match = resultValue.Contains(expectedPattern);
178 }
179 else
180 {
181 if (decimal.TryParse(expectedPattern, out decimal expectedNumeric) &&
182 decimal.TryParse(resultValue, out decimal resultNumeric))
183 {
184 match = (matchType == MatchType.GreaterThan && resultNumeric > expectedNumeric) ||
185 (matchType == MatchType.LessThan && resultNumeric < expectedNumeric);
186 }
187 else
188 {
189 return Fail(string.Format("{0} is not numeric: {1}", description, resultValue));
190 }
191 }
192 }
193
194 if (matchType.In(MatchType.Equals, MatchType.Contains))
195 {
196 if (match)
197 return Pass(string.Format("{0} {1} the pattern: {2}", description, matchType.ToString().ToLower(), expectedPattern));
198 else
199 return Fail(string.Format("{0} does not {1} the pattern: {2} ({0}: {3})", description, matchType.ToString().ToLower().TrimEnd('s'), expectedPattern, resultValue));
200 }
201 else if (matchType.In(MatchType.NotEquals, MatchType.NotContains))
202 {
203 if (match)
204 return Fail(string.Format("{0} {1} the pattern: {2} ({0}: {3})", description, matchType.ToString().ToLower().Replace("not", ""), expectedPattern, resultValue));
205 else
206 return Pass(string.Format("{0} does not {1} the pattern: {2}", description, matchType.ToString().ToLower().TrimEnd('s').Replace("not", ""), expectedPattern));
207 }
208 else
209 {
210 if (match)
211 return Pass(string.Format("{0} ({1}) is {2} {3}", description, resultValue, matchType.ToString().ToLower().Replace("than", " than"), expectedPattern));
212 else
213 return Fail(string.Format("{0} ({1}) is not {2} {3}", description, resultValue, matchType.ToString().ToLower().Replace("than", " than"), expectedPattern));
214 }
215 }
216
217 protected CheckResult MergeResults(params CheckResult[] results)
218 {
219 StringBuilder message = new StringBuilder();
220 bool failed = false;
221 foreach (CheckResult result in results)
222 {
223 if (result == null)
224 continue;
225 if (result.CheckStatus != CheckStatus.Success)
226 failed = true;
227 message.AppendLine(result.Message);
228 }
229 return failed ? Fail(message.ToString().Trim()) : Pass(message.ToString().Trim());
230 }
231
232 protected abstract Task<CheckResult> ExecuteCheckAsync(CancellationToken token);
233 }
234 }