Init
This commit is contained in:
25
Cachet-Monitor.sln
Normal file
25
Cachet-Monitor.sln
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29728.190
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cachet-Monitor", "Cachet-Monitor\Cachet-Monitor.csproj", "{95DC5C5F-1837-4577-BD25-CA8BE900060D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{95DC5C5F-1837-4577-BD25-CA8BE900060D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{95DC5C5F-1837-4577-BD25-CA8BE900060D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{95DC5C5F-1837-4577-BD25-CA8BE900060D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{95DC5C5F-1837-4577-BD25-CA8BE900060D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {564B86A6-C853-4278-B04A-BF3776B746B0}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
23
Cachet-Monitor/Cachet-Monitor.csproj
Normal file
23
Cachet-Monitor/Cachet-Monitor.csproj
Normal file
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>Cachet_Monitor</RootNamespace>
|
||||
<AssemblyVersion>2020.2.24.0</AssemblyVersion>
|
||||
<FileVersion>2020.2.24.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CachNet" Version="0.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="RestEase" Version="1.4.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="CachNet">
|
||||
<HintPath>..\CachNet.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
62
Cachet-Monitor/Models/Configuration/Configuration.cs
Normal file
62
Cachet-Monitor/Models/Configuration/Configuration.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Cachet_Monitor.Models.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Cachet_Monitor.Models
|
||||
{
|
||||
public class Configuration
|
||||
{
|
||||
public Uri ApiBase { get; set; }
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
public List<Monitor> Monitors { get; set; }
|
||||
|
||||
public static Configuration Default = new Configuration
|
||||
{
|
||||
ApiBase = new Uri("https://domain.example.com"),
|
||||
ApiKey = "AAABBBCCC11223344556",
|
||||
Monitors = new List<Monitor>
|
||||
{
|
||||
new Monitor
|
||||
{
|
||||
Name = "Website",
|
||||
Target = "https://example.com",
|
||||
ComponentId = 1,
|
||||
MetricId = 1,
|
||||
Interval = 60,
|
||||
Timeout = 5,
|
||||
Type = MonitorType.HTTP,
|
||||
Settings = new MonitorSettings
|
||||
{
|
||||
ExpectedStatusCode = 200,
|
||||
Method = "GET"
|
||||
}
|
||||
},
|
||||
new Monitor
|
||||
{
|
||||
Name = "Database",
|
||||
Target = "example.com",
|
||||
ComponentId = 1,
|
||||
MetricId = 1,
|
||||
Interval = 60,
|
||||
Timeout = 5,
|
||||
Type = MonitorType.PORT,
|
||||
Settings = new MonitorSettings
|
||||
{
|
||||
Port = 3306
|
||||
}
|
||||
},
|
||||
new Monitor
|
||||
{
|
||||
Name = "Server",
|
||||
Target = "example.com",
|
||||
ComponentId = 1,
|
||||
MetricId = 1,
|
||||
Interval = 60,
|
||||
Timeout = 5,
|
||||
Type = MonitorType.ICMP
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
24
Cachet-Monitor/Models/Configuration/Monitor/Monitor.cs
Normal file
24
Cachet-Monitor/Models/Configuration/Monitor/Monitor.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace Cachet_Monitor.Models.Config
|
||||
{
|
||||
public class Monitor
|
||||
{
|
||||
//Meta
|
||||
public string Name;
|
||||
|
||||
public string Target;
|
||||
|
||||
//Cachet
|
||||
public int ComponentId;
|
||||
|
||||
public int MetricId;
|
||||
|
||||
//Timing
|
||||
public int Interval;
|
||||
|
||||
public int Timeout;
|
||||
|
||||
public MonitorType Type;
|
||||
|
||||
public MonitorSettings Settings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Cachet_Monitor.Models.Config
|
||||
{
|
||||
public class MonitorSettings
|
||||
{
|
||||
//Http
|
||||
public string Method = "GET";
|
||||
|
||||
public int ExpectedStatusCode = 200;
|
||||
|
||||
//TCP
|
||||
public int Port;
|
||||
|
||||
public int TTL;
|
||||
}
|
||||
}
|
||||
11
Cachet-Monitor/Models/Configuration/Monitor/MonitorType.cs
Normal file
11
Cachet-Monitor/Models/Configuration/Monitor/MonitorType.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Cachet_Monitor.Models.Config
|
||||
{
|
||||
public enum MonitorType
|
||||
{
|
||||
HTTP,
|
||||
PORT,
|
||||
ICMP
|
||||
}
|
||||
}
|
||||
223
Cachet-Monitor/Program.cs
Normal file
223
Cachet-Monitor/Program.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using Cachet_Monitor.Models;
|
||||
using Cachet_Monitor.Models.Config;
|
||||
using Monitor = Cachet_Monitor.Models.Config.Monitor;
|
||||
using CachNet;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Diagnostics;
|
||||
using CachNet.Entities;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace Cachet_Monitor
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
private static Configuration Configuration;
|
||||
private static CachetClient Cachet;
|
||||
|
||||
private static void Main()
|
||||
{
|
||||
{
|
||||
var config = Path.Combine(Environment.CurrentDirectory, "settings.json");
|
||||
|
||||
if (File.Exists(config))
|
||||
{
|
||||
Configuration = JsonConvert.DeserializeObject<Configuration>(File.ReadAllText(config));
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllText(config, JsonConvert.SerializeObject(Configuration.Default, Formatting.Indented));
|
||||
|
||||
Console.WriteLine($"Written a new instance of the configuration to: {config}");
|
||||
Console.ReadKey();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
Cachet = new CachetClient(Configuration.ApiBase.OriginalString, Configuration.ApiKey);
|
||||
|
||||
MainAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private static async Task MainAsync()
|
||||
{
|
||||
foreach (var monitor in Configuration.Monitors)
|
||||
{
|
||||
new Thread(async () =>
|
||||
{
|
||||
Thread.CurrentThread.IsBackground = true;
|
||||
while (true)
|
||||
{
|
||||
await DoMonitorCheck(Cachet, monitor).ConfigureAwait(false);
|
||||
|
||||
await Task.Delay(monitor.Interval * 1000);
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
|
||||
await Task.Delay(-1).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static async Task DoMonitorCheck(CachetClient Cachet, Monitor monitor)
|
||||
{
|
||||
ComponentStatus componentStatus = 0;
|
||||
switch (monitor.Type)
|
||||
{
|
||||
case MonitorType.PORT:
|
||||
{
|
||||
using (TcpClient tcpClient = new TcpClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
tcpClient.Connect(monitor.Target, monitor.Settings.Port);
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.Operational,
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.MajorOutage,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MonitorType.ICMP:
|
||||
{
|
||||
Ping ping = new Ping();
|
||||
PingOptions options = new PingOptions
|
||||
{
|
||||
DontFragment = true,
|
||||
Ttl = monitor.Settings.TTL
|
||||
};
|
||||
|
||||
PingReply reply = ping.Send(monitor.Target, monitor.Timeout, null, options);
|
||||
|
||||
await Cachet.AddMetricPointAsync(monitor.MetricId, new PostMetricPoint
|
||||
{
|
||||
Value = (int)reply.RoundtripTime
|
||||
});
|
||||
|
||||
if (reply.Status == IPStatus.Success)
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.Operational,
|
||||
});
|
||||
}
|
||||
|
||||
if (reply.RoundtripTime >= monitor.Timeout)
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.PerformanceIssues,
|
||||
});
|
||||
}
|
||||
|
||||
if (reply.Status != IPStatus.Success)
|
||||
{
|
||||
if (reply.Status == IPStatus.TimedOut)
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.PartialOutage,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.MajorOutage,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MonitorType.HTTP:
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(monitor.Target);
|
||||
request.Timeout = monitor.Timeout * 1000;
|
||||
|
||||
Stopwatch timer = new Stopwatch();
|
||||
|
||||
timer.Start();
|
||||
try
|
||||
{
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
timer.Stop();
|
||||
|
||||
if (response.StatusCode == (HttpStatusCode)monitor.Settings.ExpectedStatusCode)
|
||||
{
|
||||
var x = await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.Operational,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.PartialOutage,
|
||||
});
|
||||
}
|
||||
|
||||
response.Close();
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
timer.Stop();
|
||||
|
||||
if (ex.Status == WebExceptionStatus.ProtocolError)
|
||||
{
|
||||
if (ex.Response is HttpWebResponse response)
|
||||
{
|
||||
if (response.StatusCode == (HttpStatusCode)monitor.Settings.ExpectedStatusCode)
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.Operational,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ex.Status == WebExceptionStatus.Timeout)
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.PerformanceIssues,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await Cachet.UpdateComponentAsync(monitor.ComponentId, new PutComponent
|
||||
{
|
||||
Status = ComponentStatus.MajorOutage,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Cachet.AddMetricPointAsync(monitor.MetricId, new PostMetricPoint
|
||||
{
|
||||
Value = (int)timer.ElapsedMilliseconds
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Ran check on \"{monitor.Target}\" Status: {componentStatus}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user