Mercurial > servermonitor
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ServerMonitor/Objects/Checks/Check.cs Sun Jan 06 20:49:08 2019 -0500 @@ -0,0 +1,234 @@ +using System; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Xml.Serialization; + +namespace ServerMonitorApp +{ + /*public enum CheckType + { + Command + }*/ + + public enum CheckStatus + { + Success, + Information, + Warning, + Error, + Running, + Disabled, + } + + public abstract class Check + { + private static Type[] _checkTypes; + + public static Type[] CheckTypes + { + get + { + return _checkTypes ?? (_checkTypes = typeof(Check).Assembly.GetTypes() + .Where(t => t.IsSubclassOf(typeof(Check))) + .OrderBy(t => t.GetAttribute<DisplayWeightAttribute>()?.DisplayWeight).ToArray()); + } + } + + public int Id { get; set; } + + public string Name { get; set; } + + /*public CheckType Type { get; set; }*/ + + public int Timeout { get; set; } + + public bool Enabled { get; set; } + + public Schedule Schedule { get; set; } + + public DateTime LastRunTime { get; set; } + + public DateTime LastScheduledRunTime { get; set; } + + public DateTime NextRunTime { get; set; } + + public string LastMessage { get; set; } + + public CheckStatus Status { get; set; } + + public CheckStatus FailStatus { get; set; } + + [XmlIgnore] + public Server Server { get; set; } + + public Check() + { + FailStatus = CheckStatus.Error; + } + + public override string ToString() + { + return Name; + } + + public virtual string Validate(bool saving = true) + { + string message = string.Empty; + if (Name.IsNullOrEmpty() && saving) + message += "Name cannot be blank." + Environment.NewLine; + return message; + } + + //public virtual CheckStatus Execute() + //{ + // //TODO + // throw new NotImplementedException(); + //} + + public async Task<CheckResult> ExecuteAsync(CancellationToken token = default(CancellationToken), bool update = true) + { + //TODO check cancellation token before proceeding + CheckResult result; + DateTime startTime = DateTime.Now; + try + { + Task<CheckResult> checkTask = ExecuteCheckAsync(token); + try + { + if (await Task.WhenAny(checkTask, Task.Delay(Timeout, token)) == checkTask) + { + result = await checkTask; + } + else + { + result = Fail("Timed out."); + } + } + catch (TaskCanceledException) + { + return null; + } + } + catch (Exception e) + { + result = Fail(e.GetBaseException().Message); + } + result.StartTime = startTime; + result.EndTime = DateTime.Now; + // If a check is executed from the CheckForm, we don't want to update the status or log the event. + if (update) + { + Status = result.CheckStatus; + LastMessage = result.Message; + LastRunTime = result.EndTime; + } + return result; + } + + public CheckResult Pass(string message) + { + return new CheckResult(this, CheckStatus.Success, message); + } + + public CheckResult Fail(string message) + { + return new CheckResult(this, FailStatus, message); + } + + protected CheckResult Fail(Exception e) + { + return new CheckResult(this, FailStatus, e.GetBaseException().Message); + } + + protected CheckResult GetIntResult(int expectedValue, int resultValue, string description) + { + if (expectedValue == resultValue) + return Pass(string.Format("{0}: {1}", description, resultValue)); + else + return Fail(string.Format("{0}: {1} (expected: {2})", description, resultValue, expectedValue)); + } + + protected CheckResult GetStringResult(MatchType matchType, string expectedPattern, bool useRegex, string resultValue, string description) + { + bool match; + if (useRegex) + { + if (matchType.In(MatchType.Equals, MatchType.NotEquals)) + { + if (!expectedPattern.StartsWith("^")) + expectedPattern = "^" + expectedPattern; + if (!expectedPattern.EndsWith("$")) + expectedPattern += "$"; + } + Regex re = new Regex(expectedPattern, RegexOptions.Singleline); + match = re.IsMatch(resultValue); + } + else + { + if (matchType.In(MatchType.Equals, MatchType.NotEquals)) + { + match = expectedPattern == resultValue; + } + else if (matchType.In(MatchType.Contains, MatchType.NotContains)) + { + match = resultValue.Contains(expectedPattern); + } + else + { + if (decimal.TryParse(expectedPattern, out decimal expectedNumeric) && + decimal.TryParse(resultValue, out decimal resultNumeric)) + { + match = (matchType == MatchType.GreaterThan && resultNumeric > expectedNumeric) || + (matchType == MatchType.LessThan && resultNumeric < expectedNumeric); + } + else + { + return Fail(string.Format("{0} is not numeric: {1}", description, resultValue)); + } + } + } + + if (matchType.In(MatchType.Equals, MatchType.Contains)) + { + if (match) + return Pass(string.Format("{0} {1} the pattern: {2}", description, matchType.ToString().ToLower(), expectedPattern)); + else + return Fail(string.Format("{0} does not {1} the pattern: {2} ({0}: {3})", description, matchType.ToString().ToLower().TrimEnd('s'), expectedPattern, resultValue)); + } + else if (matchType.In(MatchType.NotEquals, MatchType.NotContains)) + { + if (match) + return Fail(string.Format("{0} {1} the pattern: {2} ({0}: {3})", description, matchType.ToString().ToLower().Replace("not", ""), expectedPattern, resultValue)); + else + return Pass(string.Format("{0} does not {1} the pattern: {2}", description, matchType.ToString().ToLower().TrimEnd('s').Replace("not", ""), expectedPattern)); + } + else + { + if (match) + return Pass(string.Format("{0} ({1}) is {2} {3}", description, resultValue, matchType.ToString().ToLower().Replace("than", " than"), expectedPattern)); + else + return Fail(string.Format("{0} ({1}) is not {2} {3}", description, resultValue, matchType.ToString().ToLower().Replace("than", " than"), expectedPattern)); + } + } + + protected CheckResult MergeResults(params CheckResult[] results) + { + StringBuilder message = new StringBuilder(); + bool failed = false; + foreach (CheckResult result in results) + { + if (result == null) + continue; + if (result.CheckStatus != CheckStatus.Success) + failed = true; + message.AppendLine(result.Message); + } + return failed ? Fail(message.ToString().Trim()) : Pass(message.ToString().Trim()); + } + + protected abstract Task<CheckResult> ExecuteCheckAsync(CancellationToken token); + } +} \ No newline at end of file