mirror of
https://github.com/AlexMacocian/ServerManagementUtils.git
synced 2026-07-15 15:19:58 +00:00
69fd4bfb62
Setup base files for Robin monitoring service
128 lines
4.0 KiB
C#
128 lines
4.0 KiB
C#
using System.Extensions.Core;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using Robin.Options;
|
|
|
|
namespace Robin.Services;
|
|
|
|
public sealed class MonitoringService(
|
|
IOptions<MonitorOptions> options,
|
|
ILogger<MonitoringService> logger
|
|
) : IHostedLifecycleService
|
|
{
|
|
private readonly MonitorOptions options = options.Value;
|
|
private readonly ILogger<MonitoringService> logger = logger;
|
|
private readonly List<FileSystemWatcher> watchers = [];
|
|
|
|
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
|
|
public Task StartedAsync(CancellationToken cancellationToken) =>
|
|
this.MonitorFiles(cancellationToken);
|
|
|
|
public Task StartingAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
|
|
public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
|
|
public Task StoppingAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
|
|
public async Task MonitorFiles(CancellationToken cancellationToken)
|
|
{
|
|
var scopedLogger = this.logger.CreateScopedLogger();
|
|
scopedLogger.LogDebug(
|
|
"Starting file monitoring service. Parsing provided paths {paths}",
|
|
string.Join(", ", this.options.Paths)
|
|
);
|
|
var expandedPaths = ExpandPaths(this.options.Paths);
|
|
scopedLogger.LogInformation(
|
|
"Monitoring the following files: {files}",
|
|
string.Join(", ", expandedPaths)
|
|
);
|
|
|
|
foreach (var filePath in expandedPaths)
|
|
{
|
|
var watcher = CreateWatcher(filePath);
|
|
if (watcher is null)
|
|
{
|
|
scopedLogger.LogWarning("Failed to watch file: {file}", filePath);
|
|
continue;
|
|
}
|
|
|
|
this.watchers.Add(watcher);
|
|
scopedLogger.LogDebug("Watching file: {file}", filePath);
|
|
}
|
|
}
|
|
|
|
private FileSystemWatcher? CreateWatcher(string filePath)
|
|
{
|
|
var scpoedLogger = this.logger.CreateScopedLogger();
|
|
var directory = Path.GetDirectoryName(filePath);
|
|
var fileName = Path.GetFileName(filePath);
|
|
if (directory is null || fileName is null)
|
|
{
|
|
scpoedLogger.LogWarning("Invalid file path: {filePath}", filePath);
|
|
return default;
|
|
}
|
|
|
|
var watcher = new FileSystemWatcher(directory, fileName)
|
|
{
|
|
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
|
EnableRaisingEvents = true,
|
|
};
|
|
|
|
watcher.Changed += this.OnFileChanged;
|
|
watcher.Error += this.OnWatcherError;
|
|
return watcher;
|
|
}
|
|
|
|
private void OnFileChanged(object sender, FileSystemEventArgs e)
|
|
{
|
|
var scopedLogger = this.logger.CreateScopedLogger();
|
|
scopedLogger.LogDebug("File changed: {file}", e.FullPath);
|
|
// TODO:: Read changes and push to Elastic
|
|
}
|
|
|
|
private void OnWatcherError(object sender, ErrorEventArgs e)
|
|
{
|
|
var scopedLogger = this.logger.CreateScopedLogger();
|
|
scopedLogger.LogError(e.GetException(), "Watcher error");
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
foreach (var watcher in this.watchers)
|
|
{
|
|
watcher.Changed -= this.OnFileChanged;
|
|
watcher.Error -= this.OnWatcherError;
|
|
watcher.Dispose();
|
|
}
|
|
|
|
this.watchers.Clear();
|
|
}
|
|
|
|
private static List<string> ExpandPaths(List<string>? patterns)
|
|
{
|
|
if (patterns is null || patterns.Count == 0)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
var results = new List<string>();
|
|
foreach (var pattern in patterns)
|
|
{
|
|
var directory = Path.GetDirectoryName(pattern);
|
|
var filePattern = Path.GetFileName(pattern);
|
|
if (string.IsNullOrEmpty(directory) || !Directory.Exists(directory))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
results.AddRange(Directory.GetFiles(directory, filePattern));
|
|
}
|
|
|
|
return results;
|
|
}
|
|
}
|