Add Logging & Stability
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>Cachet_Monitor</RootNamespace>
|
||||
<AssemblyVersion>2020.2.24.0</AssemblyVersion>
|
||||
<FileVersion>2020.2.24.0</FileVersion>
|
||||
<AssemblyVersion>2020.3.4.0</AssemblyVersion>
|
||||
<FileVersion>2020.3.4.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
58
Cachet-Monitor/Extensions/Extensions.cs
Normal file
58
Cachet-Monitor/Extensions/Extensions.cs
Normal file
@@ -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<string[]> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
262
Cachet-Monitor/Log.cs
Normal file
262
Cachet-Monitor/Log.cs
Normal file
@@ -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<string[]>
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Monitor> 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<Monitor>
|
||||
{
|
||||
new Monitor
|
||||
|
||||
30
Cachet-Monitor/Models/LogSeverity.cs
Normal file
30
Cachet-Monitor/Models/LogSeverity.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace Cachet_Monitor.Models
|
||||
{
|
||||
public enum LogSeverity
|
||||
{
|
||||
/// <summary>
|
||||
/// Logs that contain the most severe level of error. This type of error indicate that immediate attention may be required.
|
||||
/// </summary>
|
||||
Critical = 0,
|
||||
/// <summary>
|
||||
/// Logs that highlight when the flow of execution is stopped due to a failure.
|
||||
/// </summary>
|
||||
Error = 1,
|
||||
/// <summary>
|
||||
/// Logs that highlight an abnormal activity in the flow of execution.
|
||||
/// </summary>
|
||||
Warning = 2,
|
||||
/// <summary>
|
||||
/// Logs that track the general flow of the application.
|
||||
/// </summary>
|
||||
Info = 3,
|
||||
/// <summary>
|
||||
/// Logs that are used for interactive investigation during development.
|
||||
/// </summary>
|
||||
Verbose = 4,
|
||||
/// <summary>
|
||||
/// Logs that contain the most detailed messages.
|
||||
/// </summary>
|
||||
Debug = 5
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("PortMonitorCheck", ex.Message, ex);
|
||||
}
|
||||
}
|
||||
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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user