Add Logging & Stability

master
exsersewo 5 years ago
parent d811761ccc
commit 50ed32b2a0
  1. 4
      Cachet-Monitor/Cachet-Monitor.csproj
  2. 58
      Cachet-Monitor/Extensions/Extensions.cs
  3. 262
      Cachet-Monitor/Log.cs
  4. 4
      Cachet-Monitor/Models/Configuration/Configuration.cs
  5. 30
      Cachet-Monitor/Models/LogSeverity.cs
  6. 117
      Cachet-Monitor/Program.cs

@ -4,8 +4,8 @@
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Cachet_Monitor</RootNamespace> <RootNamespace>Cachet_Monitor</RootNamespace>
<AssemblyVersion>2020.2.24.0</AssemblyVersion> <AssemblyVersion>2020.3.4.0</AssemblyVersion>
<FileVersion>2020.2.24.0</FileVersion> <FileVersion>2020.3.4.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

@ -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;
}
}
}
}

@ -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 Uri ApiBase { get; set; }
public string ApiKey { get; set; } public string ApiKey { get; set; }
public LogSeverity LogLevel { get; set; }
public bool LogToFile { get; set; }
public List<Monitor> Monitors { get; set; } public List<Monitor> Monitors { get; set; }
@ -15,6 +17,8 @@ namespace Cachet_Monitor.Models
{ {
ApiBase = new Uri("https://domain.example.com"), ApiBase = new Uri("https://domain.example.com"),
ApiKey = "AAABBBCCC11223344556", ApiKey = "AAABBBCCC11223344556",
LogLevel = LogSeverity.Info,
LogToFile = true,
Monitors = new List<Monitor> Monitors = new List<Monitor>
{ {
new Monitor new Monitor

@ -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); Cachet = new CachetClient(Configuration.ApiBase.OriginalString, Configuration.ApiKey);
MainAsync().GetAwaiter().GetResult(); MainAsync().GetAwaiter().GetResult();
@ -52,8 +54,15 @@ namespace Cachet_Monitor
{ {
Thread.CurrentThread.IsBackground = true; Thread.CurrentThread.IsBackground = true;
while (true) while (true)
{
try
{ {
await DoMonitorCheck(Cachet, monitor).ConfigureAwait(false); 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); await Task.Delay(monitor.Interval * 1000);
} }
@ -70,22 +79,38 @@ namespace Cachet_Monitor
{ {
case MonitorType.PORT: case MonitorType.PORT:
{ {
using (TcpClient tcpClient = new TcpClient()) using TcpClient tcpClient = new TcpClient();
{
try try
{ {
tcpClient.Connect(monitor.Target, monitor.Settings.Port); tcpClient.Connect(monitor.Target, monitor.Settings.Port);
try
{
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.Operational, 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 await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.MajorOutage, 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); PingReply reply = ping.Send(monitor.Target, monitor.Timeout, null, options);
try
{
await Cachet.AddMetricPointAsync(monitor.MetricId, new PostMetricPoint await Cachet.AddMetricPointAsync(monitor.MetricId, new PostMetricPoint
{ {
Value = (int)reply.RoundtripTime 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) if (reply.Status == IPStatus.Success)
{
try
{ {
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.Operational, Status = ComponentStatus.Operational,
}); });
Log.Verbose("IPMonitorCheck", "Sent to Cachet successfully");
}
catch (Exception ex)
{
Log.Error("IPMonitorCheck", ex.Message, ex);
}
} }
if (reply.RoundtripTime >= monitor.Timeout) if (reply.RoundtripTime >= monitor.Timeout)
{
try
{ {
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.PerformanceIssues, 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.Success)
{ {
if (reply.Status == IPStatus.TimedOut) if (reply.Status == IPStatus.TimedOut)
{
try
{ {
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.PartialOutage, Status = ComponentStatus.PartialOutage,
}); });
Log.Verbose("IPMonitorCheck", "Sent to Cachet successfully");
}
catch (Exception ex)
{
Log.Error("IPMonitorCheck", ex.Message, ex);
}
} }
else else
{
try
{ {
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.MajorOutage, 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) if (response.StatusCode == (HttpStatusCode)monitor.Settings.ExpectedStatusCode)
{ {
var x = await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent try
{
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.Operational, Status = ComponentStatus.Operational,
}); });
Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
}
catch (Exception ex)
{
Log.Error("WebMonitorCheck", ex.Message, ex);
}
} }
else else
{
try
{ {
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.PartialOutage, Status = ComponentStatus.PartialOutage,
}); });
Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
}
catch (Exception ex)
{
Log.Error("WebMonitorCheck", ex.Message, ex);
}
} }
response.Close(); response.Close();
@ -176,35 +258,60 @@ namespace Cachet_Monitor
catch (WebException ex) catch (WebException ex)
{ {
timer.Stop(); timer.Stop();
Log.Warning("WebMonitorChcek", ex.Message, ex);
if (ex.Status == WebExceptionStatus.ProtocolError) if (ex.Status == WebExceptionStatus.ProtocolError)
{ {
if (ex.Response is HttpWebResponse response) if (ex.Response is HttpWebResponse response)
{ {
if (response.StatusCode == (HttpStatusCode)monitor.Settings.ExpectedStatusCode) if (response.StatusCode == (HttpStatusCode)monitor.Settings.ExpectedStatusCode)
{
try
{ {
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.Operational, Status = ComponentStatus.Operational,
}); });
Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
}
catch (Exception ex2)
{
Log.Error("WebMonitorCheck", ex2.Message, ex2);
}
} }
} }
} }
else else
{ {
if (ex.Status == WebExceptionStatus.Timeout) if (ex.Status == WebExceptionStatus.Timeout)
{
try
{ {
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.PerformanceIssues, Status = ComponentStatus.PerformanceIssues,
}); });
Log.Verbose("WebMonitorCheck", "Sent to Cachet successfully");
}
catch (Exception ex2)
{
Log.Error("WebMonitorCheck", ex2.Message, ex2);
}
} }
else else
{
try
{ {
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
{ {
Status = ComponentStatus.MajorOutage, 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; break;
} }
Console.WriteLine($"Ran check on \"{monitor.Target}\" Status: {componentStatus}"); Log.Verbose("DoMonitorCheck", $"Ran check on \"{monitor.Name}\" Status: {componentStatus}");
} }
} }
} }
Loading…
Cancel
Save