diff --git a/Cachet-Monitor/Cachet-Monitor.csproj b/Cachet-Monitor/Cachet-Monitor.csproj
index 73d1f50..14324a1 100644
--- a/Cachet-Monitor/Cachet-Monitor.csproj
+++ b/Cachet-Monitor/Cachet-Monitor.csproj
@@ -4,8 +4,8 @@
Exe
netcoreapp3.1
Cachet_Monitor
- 2020.2.24.0
- 2020.2.24.0
+ 2020.3.4.0
+ 2020.3.4.0
diff --git a/Cachet-Monitor/Extensions/Extensions.cs b/Cachet-Monitor/Extensions/Extensions.cs
new file mode 100644
index 0000000..f960293
--- /dev/null
+++ b/Cachet-Monitor/Extensions/Extensions.cs
@@ -0,0 +1,58 @@
+using Cachet_Monitor.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Cachet_Monitor.Extensions
+{
+ public static class Extensions
+ {
+ public static string PrettyLines(this List lines, int padding = 1)
+ {
+ int elementCount = lines[0].Length;
+ int[] maxValues = new int[elementCount];
+
+ for (int i = 0; i < elementCount; i++)
+ maxValues[i] = lines.Max(x => x[i].Length) + padding;
+
+ var sb = new StringBuilder();
+ bool isFirst = true;
+
+ foreach (var line in lines)
+ {
+ if (!isFirst)
+ sb.AppendLine();
+
+ isFirst = false;
+
+ for (int i = 0; i < line.Length; i++)
+ {
+ var value = line[i];
+ sb.Append(value.PadRight(maxValues[i]));
+ }
+ }
+ return Convert.ToString(sb);
+ }
+
+ public static ConsoleColor SeverityToColor(this LogSeverity sev)
+ {
+ switch (sev)
+ {
+ case LogSeverity.Critical:
+ return ConsoleColor.Red;
+ case LogSeverity.Error:
+ return ConsoleColor.Red;
+ case LogSeverity.Info:
+ return ConsoleColor.Green;
+ case LogSeverity.Warning:
+ return ConsoleColor.Yellow;
+ case LogSeverity.Verbose:
+ return ConsoleColor.Cyan;
+
+ default:
+ return ConsoleColor.White;
+ }
+ }
+ }
+}
diff --git a/Cachet-Monitor/Log.cs b/Cachet-Monitor/Log.cs
new file mode 100644
index 0000000..7a76e6a
--- /dev/null
+++ b/Cachet-Monitor/Log.cs
@@ -0,0 +1,262 @@
+using Cachet_Monitor.Extensions;
+using Cachet_Monitor.Models;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace Cachet_Monitor
+{
+ public class Log
+ {
+ public readonly static string CurrentLogFileName = DateTime.UtcNow.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log";
+
+ private static StreamWriter LogFile;
+ private static Configuration Config;
+
+ public static void Configure(Configuration config)
+ {
+ Config = config;
+
+ var path = Path.Combine(Environment.CurrentDirectory, "logs");
+
+ if (Config.LogToFile && !Directory.Exists(path))
+ Directory.CreateDirectory(path);
+
+ if (LogFile == null && Directory.Exists(path))
+ {
+ LogFile = new StreamWriter(
+ File.Open(
+ Path.Combine(path, CurrentLogFileName),
+ FileMode.Append,
+ FileAccess.Write,
+ FileShare.Read)
+ )
+ {
+ AutoFlush = true,
+ NewLine = "\n"
+ };
+ }
+ }
+
+ private static string Message(string source, string message, LogSeverity severity)
+ {
+ var lines = new List
+ {
+ new[]
+ {
+ string.Format("{0:dd/MM/yyyy HH:mm:ss}", DateTime.UtcNow),
+ "[" + source + "]",
+ "[" + severity.ToString()[0] + "]",
+ message??""
+ }
+ };
+
+ var prettied = lines.PrettyLines(2);
+
+ Console.ForegroundColor = severity.SeverityToColor();
+
+ return prettied;
+ }
+
+ public static void Critical(string source, string message, Exception exception = null)
+ {
+ var msg = Message(source, message, LogSeverity.Critical);
+
+ if (exception != null)
+ {
+ var m = msg + "EXTRA INFORMATION:\n" + exception.ToString();
+
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(m);
+ }
+
+ if (Config.LogLevel >= LogSeverity.Critical)
+ Console.Out.WriteLine(m);
+ }
+ else
+ {
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(msg);
+ }
+
+ if (Config.LogLevel >= LogSeverity.Critical)
+ Console.Out.WriteLine(msg);
+ }
+
+ Console.ForegroundColor = ConsoleColor.White;
+
+ if (LogFile != null)
+ {
+ LogFile.Flush();
+ }
+ }
+
+ public static void Debug(string source, string message, Exception exception = null)
+ {
+ var msg = Message(source, message, LogSeverity.Debug);
+
+ if (exception != null)
+ {
+ var m = msg + "EXTRA INFORMATION:\n" + exception.ToString();
+
+ if (Config.LogLevel >= LogSeverity.Debug)
+ {
+ Console.Out.WriteLine(m);
+
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(m);
+ }
+ }
+ }
+ else
+ {
+ if (Config.LogLevel >= LogSeverity.Debug)
+ {
+ Console.Out.WriteLine(msg);
+
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(msg);
+ }
+ }
+ }
+
+ Console.ForegroundColor = ConsoleColor.White;
+
+ if (LogFile != null)
+ {
+ LogFile.Flush();
+ }
+ }
+
+ public static void Error(string source, string message, Exception exception = null)
+ {
+ var msg = Message(source, message, LogSeverity.Error);
+
+ if (exception != null)
+ {
+ var m = msg + "EXTRA INFORMATION:\n" + exception.ToString();
+
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(m);
+ }
+ }
+ else
+ {
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(msg);
+ }
+ }
+
+ if (Config.LogLevel >= LogSeverity.Error)
+ Console.Out.WriteLine(msg);
+
+ Console.ForegroundColor = ConsoleColor.White;
+
+ if (LogFile != null)
+ {
+ LogFile.Flush();
+ }
+ }
+
+ public static void Verbose(string source, string message, Exception exception = null)
+ {
+ var msg = Message(source, message, LogSeverity.Verbose);
+
+ if (Config.LogLevel >= LogSeverity.Verbose)
+ {
+ Console.Out.WriteLine(msg);
+
+ if (exception != null)
+ {
+ var m = msg + "EXTRA INFORMATION:\n" + exception.ToString();
+
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(m);
+ }
+ }
+ else
+ {
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(msg);
+ }
+ }
+ }
+
+ Console.ForegroundColor = ConsoleColor.White;
+
+ if (LogFile != null)
+ {
+ LogFile.Flush();
+ }
+ }
+
+ public static void Warning(string source, string message, Exception exception = null)
+ {
+ var msg = Message(source, message, LogSeverity.Warning);
+
+ if (exception != null)
+ {
+ var m = msg + "EXTRA INFORMATION:\n" + exception.ToString();
+
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(m);
+ }
+ }
+ else
+ {
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(msg);
+ }
+ }
+
+ if (Config.LogLevel >= LogSeverity.Warning)
+ Console.Out.WriteLine(msg);
+
+ Console.ForegroundColor = ConsoleColor.White;
+
+ if (LogFile != null)
+ {
+ LogFile.Flush();
+ }
+ }
+
+ public static void Info(string source, string message)
+ {
+ var msg = Message(source, message, LogSeverity.Info);
+
+ if (LogFile != null)
+ {
+ LogFile.WriteLine(msg);
+ }
+
+ if (Config.LogLevel >= LogSeverity.Info)
+ Console.Out.WriteLine(msg);
+
+ Console.ForegroundColor = ConsoleColor.White;
+
+ if (LogFile != null)
+ {
+ LogFile.Flush();
+ }
+ }
+
+ public static void FlushNewLine()
+ {
+ LogFile.WriteLine("-------------------------------------------");
+
+ LogFile.Close();
+ }
+ }
+}
diff --git a/Cachet-Monitor/Models/Configuration/Configuration.cs b/Cachet-Monitor/Models/Configuration/Configuration.cs
index ce41d5a..d20c116 100644
--- a/Cachet-Monitor/Models/Configuration/Configuration.cs
+++ b/Cachet-Monitor/Models/Configuration/Configuration.cs
@@ -8,6 +8,8 @@ namespace Cachet_Monitor.Models
{
public Uri ApiBase { get; set; }
public string ApiKey { get; set; }
+ public LogSeverity LogLevel { get; set; }
+ public bool LogToFile { get; set; }
public List Monitors { get; set; }
@@ -15,6 +17,8 @@ namespace Cachet_Monitor.Models
{
ApiBase = new Uri("https://domain.example.com"),
ApiKey = "AAABBBCCC11223344556",
+ LogLevel = LogSeverity.Info,
+ LogToFile = true,
Monitors = new List
{
new Monitor
diff --git a/Cachet-Monitor/Models/LogSeverity.cs b/Cachet-Monitor/Models/LogSeverity.cs
new file mode 100644
index 0000000..5cd12d4
--- /dev/null
+++ b/Cachet-Monitor/Models/LogSeverity.cs
@@ -0,0 +1,30 @@
+namespace Cachet_Monitor.Models
+{
+ public enum LogSeverity
+ {
+ ///
+ /// Logs that contain the most severe level of error. This type of error indicate that immediate attention may be required.
+ ///
+ Critical = 0,
+ ///
+ /// Logs that highlight when the flow of execution is stopped due to a failure.
+ ///
+ Error = 1,
+ ///
+ /// Logs that highlight an abnormal activity in the flow of execution.
+ ///
+ Warning = 2,
+ ///
+ /// Logs that track the general flow of the application.
+ ///
+ Info = 3,
+ ///
+ /// Logs that are used for interactive investigation during development.
+ ///
+ Verbose = 4,
+ ///
+ /// Logs that contain the most detailed messages.
+ ///
+ Debug = 5
+ }
+}
diff --git a/Cachet-Monitor/Program.cs b/Cachet-Monitor/Program.cs
index 593a09b..9fe3123 100644
--- a/Cachet-Monitor/Program.cs
+++ b/Cachet-Monitor/Program.cs
@@ -39,6 +39,8 @@ namespace Cachet_Monitor
}
}
+ Log.Configure(Configuration);
+
Cachet = new CachetClient(Configuration.ApiBase.OriginalString, Configuration.ApiKey);
MainAsync().GetAwaiter().GetResult();
@@ -53,7 +55,14 @@ namespace Cachet_Monitor
Thread.CurrentThread.IsBackground = true;
while (true)
{
- await DoMonitorCheck(Cachet, monitor).ConfigureAwait(false);
+ try
+ {
+ await DoMonitorCheck(Cachet, monitor).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ File.WriteAllText(Path.Combine(Environment.CurrentDirectory, "lastexception.txt"), ex.ToString());
+ }
await Task.Delay(monitor.Interval * 1000);
}
@@ -70,22 +79,38 @@ namespace Cachet_Monitor
{
case MonitorType.PORT:
{
- using (TcpClient tcpClient = new TcpClient())
+ using TcpClient tcpClient = new TcpClient();
+ try
{
+ tcpClient.Connect(monitor.Target, monitor.Settings.Port);
try
{
- tcpClient.Connect(monitor.Target, monitor.Settings.Port);
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{
Status = ComponentStatus.Operational,
});
+ Log.Verbose("PortMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("PortMonitorCheck", ex.Message, ex);
}
- catch (Exception)
+ }
+ catch (Exception ex)
+ {
+ Log.Error("PortMonitorCheck", ex.Message, ex);
+
+ try
{
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{
Status = ComponentStatus.MajorOutage,
});
+ Log.Verbose("PortMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch(Exception ex2)
+ {
+ Log.Error("PortMonitorCheck", ex2.Message, ex2);
}
}
}
@@ -102,42 +127,82 @@ namespace Cachet_Monitor
PingReply reply = ping.Send(monitor.Target, monitor.Timeout, null, options);
- await Cachet.AddMetricPointAsync(monitor.MetricId, new PostMetricPoint
+ try
{
- Value = (int)reply.RoundtripTime
- });
+ await Cachet.AddMetricPointAsync(monitor.MetricId, new PostMetricPoint
+ {
+ Value = (int)reply.RoundtripTime
+ });
+ Log.Verbose("IPMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("IPMonitorCheck", ex.Message, ex);
+ }
if (reply.Status == IPStatus.Success)
{
- await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.Operational,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.Operational,
+ });
+ Log.Verbose("IPMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("IPMonitorCheck", ex.Message, ex);
+ }
}
if (reply.RoundtripTime >= monitor.Timeout)
{
- await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.PerformanceIssues,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.PerformanceIssues,
+ });
+ Log.Verbose("IPMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("IPMonitorCheck", ex.Message, ex);
+ }
}
if (reply.Status != IPStatus.Success)
{
if (reply.Status == IPStatus.TimedOut)
{
- await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.PartialOutage,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.PartialOutage,
+ });
+ Log.Verbose("IPMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("IPMonitorCheck", ex.Message, ex);
+ }
}
else
{
- await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.MajorOutage,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.MajorOutage,
+ });
+ Log.Verbose("IPMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("IPMonitorCheck", ex.Message, ex);
+ }
}
}
}
@@ -158,17 +223,34 @@ namespace Cachet_Monitor
if (response.StatusCode == (HttpStatusCode)monitor.Settings.ExpectedStatusCode)
{
- var x = await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.Operational,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.Operational,
+ });
+ Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("WebMonitorCheck", ex.Message, ex);
+ }
}
else
{
- await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.PartialOutage,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.PartialOutage,
+ });
+ Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("WebMonitorCheck", ex.Message, ex);
+ }
+
}
response.Close();
@@ -176,6 +258,7 @@ namespace Cachet_Monitor
catch (WebException ex)
{
timer.Stop();
+ Log.Warning("WebMonitorChcek", ex.Message, ex);
if (ex.Status == WebExceptionStatus.ProtocolError)
{
@@ -183,10 +266,18 @@ namespace Cachet_Monitor
{
if (response.StatusCode == (HttpStatusCode)monitor.Settings.ExpectedStatusCode)
{
- await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.Operational,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.Operational,
+ });
+ Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex2)
+ {
+ Log.Error("WebMonitorCheck", ex2.Message, ex2);
+ }
}
}
}
@@ -194,17 +285,33 @@ namespace Cachet_Monitor
{
if (ex.Status == WebExceptionStatus.Timeout)
{
- await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.PerformanceIssues,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.PerformanceIssues,
+ });
+ Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex2)
+ {
+ Log.Error("WebMonitorCheck", ex2.Message, ex2);
+ }
}
else
{
- await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ try
{
- Status = ComponentStatus.MajorOutage,
- });
+ await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
+ {
+ Status = ComponentStatus.MajorOutage,
+ });
+ Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
+ }
+ catch (Exception ex2)
+ {
+ Log.Error("WebMonitorCheck", ex2.Message, ex2);
+ }
}
}
}
@@ -217,7 +324,7 @@ namespace Cachet_Monitor
break;
}
- Console.WriteLine($"Ran check on \"{monitor.Target}\" Status: {componentStatus}");
+ Log.Verbose("DoMonitorCheck", $"Ran check on \"{monitor.Name}\" Status: {componentStatus}");
}
}
}
\ No newline at end of file