diff --git a/README.md b/README.md
index ac15bf7..5208f9e 100644
--- a/README.md
+++ b/README.md
@@ -88,8 +88,12 @@ docker run -d \
version: "3.3"
services:
cleanuperr:
+ volumes:
+ - ./cleanuperr/logs:/var/logs
environment:
- - LOGGING__LOGLEVEL__DEFAULT=Information
+ - LOGGING__LOGLEVEL=Information
+ - LOGGING__FILE__ENABLED=false
+ - LOGGING__FILE__PATH=/var/logs/
- TRIGGERS__QUEUECLEANER=0 0/5 * * * ?
- TRIGGERS__CONTENTBLOCKER=0 0/5 * * * ?
@@ -137,7 +141,9 @@ services:
| Variable | Required | Description | Default value |
|---|---|---|---|
-| LOGGING__LOGLEVEL__DEFAULT | No | Can be `Debug`, `Information`, `Warning` or `Error` | Information |
+| LOGGING__LOGLEVEL | No | Can be `Verbose`, `Debug`, `Information`, `Warning`, `Error` or `Fatal` | `Information` |
+| LOGGING__FILE__ENABLED | No | Enable or disable logging to file | false |
+| LOGGING__FILE__PATH | No | Directory where to save the log files | empty |
|||||
| TRIGGERS__QUEUECLEANER | Yes if queue cleaner is enabled | [Quartz cron trigger](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) | 0 0/5 * * * ? |
| TRIGGERS__CONTENTBLOCKER | Yes if content blocker is enabled | [Quartz cron trigger](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) | 0 0/5 * * * ? |
@@ -165,11 +171,11 @@ services:
| TRANSMISSION__USERNAME | No | Transmission user | empty |
| TRANSMISSION__PASSWORD | No | Transmission password | empty |
|||||
-| SONARR__ENABLED | No | Whether Sonarr cleanup is enabled or not | true |
+| SONARR__ENABLED | No | Enable or disable Sonarr cleanup | true |
| SONARR__INSTANCES__0__URL | Yes | First Sonarr instance url | http://localhost:8989 |
| SONARR__INSTANCES__0__APIKEY | Yes | First Sonarr instance API key | empty |
|||||
-| RADARR__ENABLED | No | Whether Radarr cleanup is enabled or not | false |
+| RADARR__ENABLED | No | Enable or disable Radarr cleanup | false |
| RADARR__INSTANCES__0__URL | Yes | First Radarr instance url | http://localhost:8989 |
| RADARR__INSTANCES__0__APIKEY | Yes | First Radarr instance API key | empty |
diff --git a/code/Common/Common.csproj b/code/Common/Common.csproj
index 3a63532..8edf131 100644
--- a/code/Common/Common.csproj
+++ b/code/Common/Common.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/code/Common/Configuration/Logging/FileLogConfig.cs b/code/Common/Configuration/Logging/FileLogConfig.cs
new file mode 100644
index 0000000..17d3ed7
--- /dev/null
+++ b/code/Common/Configuration/Logging/FileLogConfig.cs
@@ -0,0 +1,12 @@
+namespace Common.Configuration.Logging;
+
+public class FileLogConfig : IConfig
+{
+ public bool Enabled { get; set; }
+
+ public string Path { get; set; } = string.Empty;
+
+ public void Validate()
+ {
+ }
+}
\ No newline at end of file
diff --git a/code/Common/Configuration/Logging/LoggingConfig.cs b/code/Common/Configuration/Logging/LoggingConfig.cs
new file mode 100644
index 0000000..269f0e6
--- /dev/null
+++ b/code/Common/Configuration/Logging/LoggingConfig.cs
@@ -0,0 +1,16 @@
+using Serilog.Events;
+
+namespace Common.Configuration.Logging;
+
+public class LoggingConfig : IConfig
+{
+ public const string SectionName = "Logging";
+
+ public LogEventLevel LogLevel { get; set; }
+
+ public FileLogConfig? File { get; set; }
+
+ public void Validate()
+ {
+ }
+}
\ No newline at end of file
diff --git a/code/Executable/DependencyInjection/LoggingDI.cs b/code/Executable/DependencyInjection/LoggingDI.cs
new file mode 100644
index 0000000..5efbd6c
--- /dev/null
+++ b/code/Executable/DependencyInjection/LoggingDI.cs
@@ -0,0 +1,66 @@
+using Common.Configuration.Logging;
+using Infrastructure.Verticals.ContentBlocker;
+using Infrastructure.Verticals.QueueCleaner;
+using Serilog;
+using Serilog.Events;
+using Serilog.Templates;
+using Serilog.Templates.Themes;
+
+namespace Executable.DependencyInjection;
+
+public static class LoggingDI
+{
+ public static ILoggingBuilder AddLogging(this ILoggingBuilder builder, IConfiguration configuration)
+ {
+ LoggingConfig? config = configuration.GetSection(LoggingConfig.SectionName).Get();
+
+ if (!string.IsNullOrEmpty(config?.File?.Path) && !Directory.Exists(config.File.Path))
+ {
+ try
+ {
+ Directory.CreateDirectory(config.File.Path);
+ }
+ catch (Exception exception)
+ {
+ throw new Exception($"log file path is not a valid directory | {config.File.Path}", exception);
+ }
+ }
+
+ LoggerConfiguration logConfig = new();
+ const string consoleOutputTemplate = "[{@t:yyyy-MM-dd HH:mm:ss.fff} {@l:u3}]{#if JobName is not null} {Concat('[',JobName,']'),PAD}{#end} {@m}\n{@x}";
+ const string fileOutputTemplate = "{@t:yyyy-MM-dd HH:mm:ss.fff zzz} [{@l:u3}]{#if JobName is not null} {Concat('[',JobName,']'),PAD}{#end} {@m:lj}\n{@x}";
+ LogEventLevel level = LogEventLevel.Information;
+ List jobNames = [nameof(ContentBlocker), nameof(QueueCleaner)];
+ int padding = jobNames.Max(x => x.Length) + 2;
+
+ if (config is not null)
+ {
+ level = config.LogLevel;
+
+ if (config.File?.Enabled is true)
+ {
+ logConfig.WriteTo.File(
+ path: Path.Combine(config.File.Path, "cleanuperr-.txt"),
+ formatter: new ExpressionTemplate(fileOutputTemplate.Replace("PAD", padding.ToString())),
+ fileSizeLimitBytes: 10L * 1024 * 1024,
+ rollingInterval: RollingInterval.Day,
+ rollOnFileSizeLimit: true
+ );
+ }
+ }
+
+ Log.Logger = logConfig
+ .MinimumLevel.Is(level)
+ .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
+ .MinimumLevel.Override("Quartz", LogEventLevel.Warning)
+ .MinimumLevel.Override("System.Net.Http.HttpClient", LogEventLevel.Error)
+ .WriteTo.Console(new ExpressionTemplate(consoleOutputTemplate.Replace("PAD", padding.ToString())))
+ .Enrich.FromLogContext()
+ .Enrich.WithProperty("ApplicationName", "cleanuperr")
+ .CreateLogger();
+
+ return builder
+ .ClearProviders()
+ .AddSerilog();
+ }
+}
\ No newline at end of file
diff --git a/code/Executable/Executable.csproj b/code/Executable/Executable.csproj
index 703a45e..0518296 100644
--- a/code/Executable/Executable.csproj
+++ b/code/Executable/Executable.csproj
@@ -9,11 +9,17 @@
-
+
+
+
+
+
+
+
diff --git a/code/Executable/Jobs/GenericJob.cs b/code/Executable/Jobs/GenericJob.cs
index c8fce01..8fc8adc 100644
--- a/code/Executable/Jobs/GenericJob.cs
+++ b/code/Executable/Jobs/GenericJob.cs
@@ -1,5 +1,6 @@
using Infrastructure.Verticals.Jobs;
using Quartz;
+using Serilog.Context;
namespace Executable.Jobs;
@@ -19,6 +20,8 @@ public sealed class GenericJob : IJob
public async Task Execute(IJobExecutionContext context)
{
+ using var _ = LogContext.PushProperty("JobName", typeof(T).Name);
+
try
{
await _handler.ExecuteAsync();
diff --git a/code/Executable/Program.cs b/code/Executable/Program.cs
index a987692..1c1ebb2 100644
--- a/code/Executable/Program.cs
+++ b/code/Executable/Program.cs
@@ -3,6 +3,7 @@ using Executable.DependencyInjection;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddInfrastructure(builder.Configuration);
+builder.Logging.AddLogging(builder.Configuration);
var host = builder.Build();
diff --git a/code/Executable/appsettings.Development.json b/code/Executable/appsettings.Development.json
index 50aa0af..37bbe3e 100644
--- a/code/Executable/appsettings.Development.json
+++ b/code/Executable/appsettings.Development.json
@@ -1,10 +1,9 @@
{
"Logging": {
- "LogLevel": {
- "Default": "Debug",
- "Microsoft.Hosting.Lifetime": "Information",
- "Quartz": "Warning",
- "System.Net.Http.HttpClient": "Error"
+ "LogLevel": "Debug",
+ "File": {
+ "Enabled": false,
+ "Path": ""
}
},
"Triggers": {
diff --git a/code/Executable/appsettings.json b/code/Executable/appsettings.json
index a21b054..a5d5454 100644
--- a/code/Executable/appsettings.json
+++ b/code/Executable/appsettings.json
@@ -1,10 +1,9 @@
{
"Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.Hosting.Lifetime": "Information",
- "Quartz": "Warning",
- "System.Net.Http.HttpClient": "Error"
+ "LogLevel": "Information",
+ "File": {
+ "Enabled": false,
+ "Path": ""
}
},
"Triggers": {
diff --git a/code/test/docker-compose.yml b/code/test/docker-compose.yml
index 27d77a4..002520a 100644
--- a/code/test/docker-compose.yml
+++ b/code/test/docker-compose.yml
@@ -171,7 +171,9 @@ services:
image: flaminel/cleanuperr:latest
container_name: cleanuperr
environment:
- - LOGGING__LOGLEVEL__DEFAULT=Debug
+ - LOGGING__LOGLEVEL=Debug
+ - LOGGING__FILE__ENABLED=false
+ - LOGGING__FILE__PATH=/var/logs
- TRIGGERS__QUEUECLEANER=0/30 * * * * ?
- TRIGGERS__CONTENTBLOCKER=0/30 * * * * ?
@@ -207,6 +209,8 @@ services:
- RADARR__ENABLED=true
- RADARR__INSTANCES__0__URL=http://radarr:7878
- RADARR__INSTANCES__0__APIKEY=705b553732ab4167ab23909305d60600
+ volumes:
+ - ./data/cleanuperr/logs:/var/logs
restart: unless-stopped
depends_on:
- qbittorrent