mirror of
https://github.com/AlexMacocian/ServerManagementUtils.git
synced 2026-07-15 15:19:58 +00:00
Setup Robin base files
Setup base files for Robin monitoring service
This commit is contained in:
+137
@@ -0,0 +1,137 @@
|
|||||||
|
[*.cs]
|
||||||
|
|
||||||
|
# CA2254: Template should be a static expression
|
||||||
|
dotnet_diagnostic.CA2254.severity = none
|
||||||
|
csharp_indent_labels = one_less_than_current
|
||||||
|
csharp_using_directive_placement = outside_namespace:error
|
||||||
|
csharp_prefer_simple_using_statement = true:error
|
||||||
|
csharp_prefer_braces = true:silent
|
||||||
|
csharp_style_namespace_declarations = file_scoped:error
|
||||||
|
csharp_style_prefer_method_group_conversion = true:suggestion
|
||||||
|
csharp_style_expression_bodied_methods = false:silent
|
||||||
|
csharp_style_expression_bodied_constructors = false:silent
|
||||||
|
csharp_style_expression_bodied_operators = false:silent
|
||||||
|
csharp_style_expression_bodied_properties = true:silent
|
||||||
|
csharp_style_expression_bodied_indexers = true:silent
|
||||||
|
csharp_style_expression_bodied_accessors = true:silent
|
||||||
|
csharp_style_expression_bodied_lambdas = true:silent
|
||||||
|
csharp_style_expression_bodied_local_functions = false:silent
|
||||||
|
csharp_indent_braces = false
|
||||||
|
insert_final_newline = true
|
||||||
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_style_throw_expression = true:suggestion
|
||||||
|
csharp_style_prefer_null_check_over_type_check = true:suggestion
|
||||||
|
csharp_prefer_simple_default_expression = true:suggestion
|
||||||
|
csharp_style_prefer_local_over_anonymous_function = true:error
|
||||||
|
csharp_style_prefer_index_operator = true:suggestion
|
||||||
|
csharp_style_prefer_range_operator = true:suggestion
|
||||||
|
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
||||||
|
csharp_style_prefer_tuple_swap = true:suggestion
|
||||||
|
csharp_style_inlined_variable_declaration = true:suggestion
|
||||||
|
csharp_style_deconstructed_variable_declaration = true:error
|
||||||
|
csharp_style_unused_value_assignment_preference = discard_variable:error
|
||||||
|
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||||
|
csharp_prefer_static_local_function = true:suggestion
|
||||||
|
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
|
||||||
|
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
|
||||||
|
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:suggestion
|
||||||
|
csharp_style_conditional_delegate_call = true:suggestion
|
||||||
|
csharp_style_prefer_parameter_null_checking = true:suggestion
|
||||||
|
csharp_style_prefer_switch_expression = true:suggestion
|
||||||
|
csharp_style_prefer_pattern_matching = true:silent
|
||||||
|
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||||
|
csharp_style_prefer_not_pattern = true:suggestion
|
||||||
|
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||||
|
csharp_style_prefer_extended_property_pattern = true:suggestion
|
||||||
|
csharp_style_var_for_built_in_types = false:silent
|
||||||
|
csharp_style_var_when_type_is_apparent = false:silent
|
||||||
|
csharp_style_var_elsewhere = false:silent
|
||||||
|
csharp_style_prefer_top_level_statements = true:suggestion
|
||||||
|
csharp_style_prefer_utf8_string_literals = true:suggestion
|
||||||
|
csharp_style_prefer_readonly_struct = true:suggestion
|
||||||
|
|
||||||
|
[*.{cs,vb}]
|
||||||
|
#### Naming styles ####
|
||||||
|
|
||||||
|
# Naming rules
|
||||||
|
|
||||||
|
dotnet_naming_rule.interface_should_be_begins_with_i.severity = error
|
||||||
|
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||||
|
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||||
|
|
||||||
|
dotnet_naming_rule.types_should_be_pascal_case.severity = error
|
||||||
|
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||||
|
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||||
|
|
||||||
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = error
|
||||||
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||||
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||||
|
|
||||||
|
# Symbol specifications
|
||||||
|
|
||||||
|
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||||
|
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||||
|
dotnet_naming_symbols.interface.required_modifiers =
|
||||||
|
|
||||||
|
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
||||||
|
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||||
|
dotnet_naming_symbols.types.required_modifiers =
|
||||||
|
|
||||||
|
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||||
|
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||||
|
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||||
|
|
||||||
|
# Naming styles
|
||||||
|
|
||||||
|
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||||
|
dotnet_naming_style.begins_with_i.required_suffix =
|
||||||
|
dotnet_naming_style.begins_with_i.word_separator =
|
||||||
|
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||||
|
|
||||||
|
dotnet_naming_style.pascal_case.required_prefix =
|
||||||
|
dotnet_naming_style.pascal_case.required_suffix =
|
||||||
|
dotnet_naming_style.pascal_case.word_separator =
|
||||||
|
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||||
|
|
||||||
|
dotnet_naming_style.pascal_case.required_prefix =
|
||||||
|
dotnet_naming_style.pascal_case.required_suffix =
|
||||||
|
dotnet_naming_style.pascal_case.word_separator =
|
||||||
|
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||||
|
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||||
|
tab_width = 4
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = crlf
|
||||||
|
dotnet_style_coalesce_expression = true:suggestion
|
||||||
|
dotnet_style_null_propagation = true:suggestion
|
||||||
|
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error
|
||||||
|
dotnet_style_prefer_auto_properties = true:error
|
||||||
|
dotnet_style_object_initializer = true:suggestion
|
||||||
|
dotnet_style_collection_initializer = true:suggestion
|
||||||
|
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
|
||||||
|
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||||
|
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||||
|
dotnet_style_explicit_tuple_names = true:suggestion
|
||||||
|
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||||
|
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||||
|
dotnet_style_prefer_compound_assignment = true:suggestion
|
||||||
|
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||||
|
dotnet_style_namespace_match_folder = true:suggestion
|
||||||
|
dotnet_style_readonly_field = true:suggestion
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:silent
|
||||||
|
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||||
|
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
|
||||||
|
dotnet_style_allow_statement_immediately_after_block_experimental = false:suggestion
|
||||||
|
dotnet_code_quality_unused_parameters = all:error
|
||||||
|
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion
|
||||||
|
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion
|
||||||
|
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion
|
||||||
|
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
|
||||||
|
dotnet_style_qualification_for_field = true:error
|
||||||
|
dotnet_style_qualification_for_property = true:error
|
||||||
|
dotnet_style_qualification_for_method = true:error
|
||||||
|
dotnet_style_qualification_for_event = true:error
|
||||||
|
dotnet_diagnostic.CA1000.severity = error
|
||||||
|
|
||||||
|
[*.vb]
|
||||||
|
dotnet_diagnostic.CA1047.severity = error
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
robin/bin/*
|
||||||
|
robin/obj/*
|
||||||
|
robin/.env
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.2.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "robin", "robin\robin.csproj", "{A085BD72-D58C-10EC-30F2-771502387E48}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{A085BD72-D58C-10EC-30F2-771502387E48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A085BD72-D58C-10EC-30F2-771502387E48}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A085BD72-D58C-10EC-30F2-771502387E48}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A085BD72-D58C-10EC-30F2-771502387E48}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {295E5EEF-E6AD-459F-B2B1-21E624094138}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Core.Extensions;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
namespace Robin.Configuration;
|
||||||
|
|
||||||
|
public static class BuilderExtensions
|
||||||
|
{
|
||||||
|
public static IHostApplicationBuilder AddEnvironmentVariables(
|
||||||
|
this IHostApplicationBuilder builder
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DotNetEnv.Env.Load();
|
||||||
|
builder.ThrowIfNull().Configuration.AddEnvironmentVariables();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostApplicationBuilder AddAppsettings(this IHostApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.ThrowIfNull()
|
||||||
|
.Configuration.AddJsonFile(
|
||||||
|
path: "appsettings.json",
|
||||||
|
optional: false,
|
||||||
|
reloadOnChange: true
|
||||||
|
);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy csproj and restore as distinct layers
|
||||||
|
COPY robin/Robin.csproj ./robin/
|
||||||
|
RUN dotnet restore ./robin/Robin.csproj
|
||||||
|
|
||||||
|
# Copy everything else and build
|
||||||
|
COPY . .
|
||||||
|
WORKDIR /src/robin
|
||||||
|
RUN dotnet publish -c Release -o /app
|
||||||
|
|
||||||
|
# Build runtime image
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /app .
|
||||||
|
ENTRYPOINT ["dotnet", "Robin.dll"]
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System.Core.Extensions;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Serilog;
|
||||||
|
using Serilog.Settings.Configuration;
|
||||||
|
|
||||||
|
namespace Robin.Logging;
|
||||||
|
|
||||||
|
public static class BuilderExtensions
|
||||||
|
{
|
||||||
|
public static IHostApplicationBuilder ClearProviders(this IHostApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.ThrowIfNull().Logging.ClearProviders();
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostApplicationBuilder AddSerilog(this IHostApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.ThrowIfNull()
|
||||||
|
.Logging.ClearProviders()
|
||||||
|
.AddSerilog(
|
||||||
|
new LoggerConfiguration()
|
||||||
|
.ReadFrom.Configuration(
|
||||||
|
builder.Configuration,
|
||||||
|
new ConfigurationReaderOptions(
|
||||||
|
typeof(ConsoleLoggerConfigurationExtensions).Assembly
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SectionName = "Serilog",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.Enrich.FromLogContext()
|
||||||
|
.WriteTo.Console(
|
||||||
|
outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss}] {Level:u4}: [{SourceContext}]{NewLine}{Message:lj}{NewLine}{Exception}",
|
||||||
|
theme: Serilog.Sinks.SystemConsole.Themes.SystemConsoleTheme.Colored
|
||||||
|
)
|
||||||
|
.CreateLogger()
|
||||||
|
);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
namespace Robin.Options;
|
||||||
|
|
||||||
|
public static class BuilderExtensions
|
||||||
|
{
|
||||||
|
public static IHostApplicationBuilder AddRobinOptions(this IHostApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.Services.AddOptions<MonitorOptions>()
|
||||||
|
.Bind(builder.Configuration.GetSection("Monitor"));
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Robin.Options;
|
||||||
|
|
||||||
|
public sealed class MonitorOptions()
|
||||||
|
{
|
||||||
|
public required List<string> Paths { get; init; } = [];
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Robin.Configuration;
|
||||||
|
using Robin.Logging;
|
||||||
|
using Robin.Options;
|
||||||
|
using Robin.Services;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
var builder = Host.CreateApplicationBuilder(args);
|
||||||
|
builder
|
||||||
|
.AddAppsettings()
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.ClearProviders()
|
||||||
|
.AddSerilog()
|
||||||
|
.AddRobinOptions()
|
||||||
|
.AddRobinServices();
|
||||||
|
|
||||||
|
var host = builder.Build();
|
||||||
|
|
||||||
|
await host.RunAsync();
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<PublishAot>true</PublishAot>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DotNetEnv" Version="3.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="10.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="10.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Enrichers.Process" Version="3.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Logging" Version="10.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Formatting.Elasticsearch" Version="10.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
|
||||||
|
<PackageReference Include="SystemExtensions.NetCore" Version="1.6.12" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="appsettings*.json" CopyToOutputDirectory="PreserveNewest" />
|
||||||
|
<Content Include=".env*" CopyToOutputDirectory="PreserveNewest" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Core.Extensions;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
namespace Robin.Services;
|
||||||
|
|
||||||
|
public static class BuilderExtensions
|
||||||
|
{
|
||||||
|
public static IHostApplicationBuilder AddRobinServices(this IHostApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.ThrowIfNull();
|
||||||
|
builder.Services.AddHostedService<MonitoringService>();
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"Serilog": {
|
||||||
|
"MinimumLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Override": {
|
||||||
|
"Microsoft": "Information",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
|
"Robin.Services": "Debug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: robin
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
restart: unless-stopped
|
||||||
Reference in New Issue
Block a user