Логирование, багфиксы, добавил мониторин /proc/mdstat. Юнит для systemd

This commit is contained in:
ftc
2020-08-30 09:15:43 +03:00
parent 092cba1cee
commit bbb0f9c63e
10 changed files with 241 additions and 79 deletions
+1
View File
@@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="ini-parser" Version="2.5.2" />
<PackageReference Include="NLog" Version="4.7.4" />
</ItemGroup>
</Project>
+16
View File
@@ -0,0 +1,16 @@
using NLog;
namespace Barsik
{
public static class Logging
{
public static void Setup()
{
var config = new NLog.Config.LoggingConfiguration();
var logConsole = new NLog.Targets.ConsoleTarget("logconsole");
config.AddRuleForAllLevels(logConsole);
LogManager.Configuration = config;
}
}
}
+66
View File
@@ -0,0 +1,66 @@
using IniParser.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
namespace Barsik
{
/// <summary>
/// Monitors configured RAID array status via /proc/mdstat
/// Will fill registers info starting from baseAddress with
/// disk status (0 - fail, 1 - up) in following order:
/// raid #0 disk #0
/// raid #0 disk #1
/// ...
/// raid #0 disk #N
/// raid #1 disk #0
/// ...
/// etc
/// </summary>
class MDStatMonitoringUnit : BaseMonitoringUnit
{
public MDStatMonitoringUnit(SectionData config, RegistersContainer registers) : base(config, registers)
{
}
public override void Run()
{
while (true)
{
int currentAddress = baseAddress;
// the file is not so big, so read it completely
var lines = File.ReadAllLines("/proc/mdstat");
for (int i = 0; i < lines.Length;)
{
if (lines[i].StartsWith("md") && i < lines.Length - 1)
{
// we found device description
// second line of it is as follows:
// 2930264896 blocks super 1.0 [2/2] [UU]
// we need last characters in brackets []
currentAddress += FillDiskStatus(currentAddress, lines[i + 1]);
i += 2;
}
else i++;
}
Thread.Sleep(2000);
}
}
private int FillDiskStatus(int address, string v)
{
int last_pos = v.LastIndexOf(']');
int pos;
for (pos = last_pos; pos > 0 && v[pos] != '['; pos--) ;
if (v[pos] != '[') return 0;
for (int i = pos + 1; i < last_pos; i++)
{
if (v[i] == 'U') registers[address + i - (pos + 1)] = 1;
else registers[address + i - (pos + 1)] = 1;
}
return last_pos - pos - 1;
}
}
}
+23 -2
View File
@@ -1,4 +1,5 @@
using System;
using NLog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
@@ -20,11 +21,14 @@ namespace Barsik
internal void Run()
{
var logger = LogManager.GetCurrentClassLogger();
logger.Info("Accepting connections on port " + Port);
var listener = new TcpListener(IPAddress.Any, Port);
listener.Start();
while (true)
{
var client = listener.AcceptTcpClient();
logger.Info("Accepted connection from " + client.Client.RemoteEndPoint);
var worker = new ModbusServerWorker(registers, client);
Thread clientThread = new Thread(new ThreadStart(worker.Run));
clientThread.Start();
@@ -38,6 +42,7 @@ namespace Barsik
private RegistersContainer registers;
private TcpClient client;
private static Logger logger = LogManager.GetCurrentClassLogger();
public ModbusServerWorker(RegistersContainer registers, TcpClient client)
{
this.registers = registers;
@@ -52,6 +57,7 @@ namespace Barsik
public void Run()
{
logger.Debug("Working with client");
received = new List<byte>();
try
{
@@ -63,11 +69,13 @@ namespace Barsik
readCompleted.Reset();
stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(this.OnReadCompleted), this);
readCompleted.WaitOne();
if (currentReceived < 0)
if (currentReceived <= 0)
{
logger.Debug("Received no data, closing ");
client.Close();
return;
}
logger.Debug("ProcessReceivedData of " + received.Count);
ProcessReceivedData();
}
}
@@ -75,6 +83,11 @@ namespace Barsik
{
client.Close();
}
finally
{
if (stream != null) stream.Dispose();
client.Dispose();
}
}
private void ProcessReceivedData()
@@ -122,6 +135,8 @@ namespace Barsik
}
private void OnReadCompleted(IAsyncResult ar)
{
try
{
currentReceived = stream.EndRead(ar);
lock (received)
@@ -130,5 +145,11 @@ namespace Barsik
}
readCompleted.Set();
}
catch (IOException e)
{
logger.Info("Error receiving " + e);
currentReceived = -1;
}
}
}
}
+4 -58
View File
@@ -1,8 +1,5 @@
using IniParser.Model;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Barsik
{
@@ -30,6 +27,10 @@ namespace Barsik
if (type == "Sensors")
{
return new SensorsMonitoringUnit(config, registers);
}
else if (type == "MDStat")
{
return new MDStatMonitoringUnit(config, registers);
}
else
{
@@ -38,59 +39,4 @@ namespace Barsik
}
}
}
class SensorsMonitoringUnit : BaseMonitoringUnit
{
public SensorsMonitoringUnit(SectionData config, RegistersContainer registers) : base(config, registers)
{
}
public override void Run()
{
var stringToFind = config.Keys["String"];
var multiplier = float.Parse(config.Keys["Multiplier"]);
while (true)
{
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("sensors");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
while (!proc.HasExited)
{
Thread.Sleep(100);
}
string result = proc.StandardOutput.ReadToEnd();
var lines = result.Split('\n');
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].Contains(stringToFind))
{
var value = ExtractValue(lines[i]);
registers[baseAddress] = (int)(value * multiplier);
}
}
}
}
bool Good(char c)
{
if (c == '-' || c == '+' || c == '.') return true;
if (c >= '0' && c <= '9') return true;
return false;
}
private float ExtractValue(string v)
{
int pos = 0;
while (pos < v.Length && !Good(v[pos])) pos++;
int pos2 = pos;
while (pos2 < v.Length && Good(v[pos2])) pos2++;
float res = 0;
float.TryParse(v.Substring(pos, pos2 - pos), out res);
return res;
}
}
}
+12 -6
View File
@@ -1,6 +1,8 @@
using IniParser;
using System;
using NLog;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
namespace Barsik
@@ -10,14 +12,20 @@ namespace Barsik
private static RegistersContainer registers;
private static List<BaseMonitoringUnit> units;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
static void Main(string[] args)
{
Logging.Setup();
logger.Info("Barsik monitoring service starting");
registers = new RegistersContainer();
var server = new ModbusServer(registers);
units = new List<BaseMonitoringUnit>();
var configParser = new FileIniDataParser();
var data = configParser.ReadFile("barsik.ini");
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var data = configParser.ReadFile(Path.Combine(assemblyFolder, "barsik.ini"));
foreach (var section in data.Sections)
{
if (section.SectionName.StartsWith("Unit"))
@@ -31,12 +39,10 @@ namespace Barsik
}
}
}
logger.Info("Configuration loaded, we have " + units.Count + " units");
server.Port = int.Parse(data["Server"]["Port"]);
while (true)
{
server.Run();
Thread.Sleep(1000);
}
logger.Info("Exiting");
}
}
}
@@ -10,7 +10,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<TargetFramework>netcoreapp2.1</TargetFramework>
<PublishDir>bin\Debug\netcoreapp2.1\publish\</PublishDir>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<_IsPortable>false</_IsPortable>
<SelfContained>false</SelfContained>
<_IsPortable>true</_IsPortable>
</PropertyGroup>
</Project>
+88
View File
@@ -0,0 +1,88 @@
using IniParser.Model;
using System;
using System.Threading;
namespace Barsik
{
/// <summary>
/// Parses output of "sensors" command and puts CPU core temperatures into
/// registers
/// </summary>
class SensorsMonitoringUnit : BaseMonitoringUnit
{
const string CORE_STR = "Core{0} Temp:";
public SensorsMonitoringUnit(SectionData config, RegistersContainer registers) : base(config, registers)
{
}
public override void Run()
{
int cores = int.Parse(config.Keys["Cores"]);
var multiplier = float.Parse(config.Keys["Multiplier"]);
while (true)
{
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("sensors");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
{
proc.StartInfo = procStartInfo;
proc.Start();
while (!proc.HasExited)
{
Thread.Sleep(100);
}
string result = proc.StandardOutput.ReadToEnd();
var lines = result.Split('\n');
// lines in output will be of format:
// Core0 Temp: +29.0°C
// and there could be several lines for one core
// so let's take all of them and use maximal value as core temp
float[] t = new float[cores];
for (int i = 0; i < cores; i++)
{
t[i] = 0;
}
for (int i = 0; i < lines.Length; i++)
{
for (int j = 0; j < cores; j++)
{
string toFind = string.Format(CORE_STR, j);
if (lines[i].Contains(toFind))
{
var value = ExtractValue(lines[i].Substring(toFind.Length));
t[j] = Math.Max(t[j], value);
}
}
}
// fill register data starting from baseAddress
for (int i = 0; i < cores; i++)
{
registers[baseAddress + i] = (int)(t[i] * multiplier);
}
}
Thread.Sleep(2000);
}
}
bool Good(char c)
{
if (c == '-' || c == '+' || c == '.') return true;
if (c >= '0' && c <= '9') return true;
return false;
}
private float ExtractValue(string v)
{
int pos = 0;
while (pos < v.Length && !Good(v[pos])) pos++;
int pos2 = pos;
while (pos2 < v.Length && Good(v[pos2])) pos2++;
float res;
float.TryParse(v.Substring(pos, pos2 - pos), out res);
return res;
}
}
}
+5 -1
View File
@@ -4,5 +4,9 @@ Port = 4500
[Unit_CPU]
Type = Sensors
BaseAddress = 1
String = CPU Temperature
Multiplier = 100
Cores = 2
[Unit_RAID]
Type = MDStat
BaseAddress = 3
+14
View File
@@ -0,0 +1,14 @@
[Unit]
Description=Barsik monitoring service
After=network.target
[Service]
ExecStart=dotnet /root/barsik/Barsik.dll
User=root
Group=root
RuntimeDirectory=/root/barsik
RuntimeDirectoryMode=0755
ProtectHome=false
[Install]
WantedBy=multi-user.target