diff --git a/CHANGELOG.md b/CHANGELOG.md
index 923c7a8d..d0597d81 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added
+
+- Debug-level logs are now written to file in addition to the Info-level logs in console output.
+
## [1.4.2] - 2021-05-15
### Fixed
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
index c064ddce..7fb4a4bc 100644
--- a/src/Directory.Build.targets
+++ b/src/Directory.Build.targets
@@ -6,6 +6,7 @@
+
@@ -13,7 +14,6 @@
-
@@ -26,6 +26,7 @@
+
diff --git a/src/Trash.Tests/LogJanitorTest.cs b/src/Trash.Tests/LogJanitorTest.cs
new file mode 100644
index 00000000..c72957a1
--- /dev/null
+++ b/src/Trash.Tests/LogJanitorTest.cs
@@ -0,0 +1,41 @@
+using System.IO.Abstractions;
+using NSubstitute;
+using NUnit.Framework;
+
+namespace Trash.Tests
+{
+ [TestFixture]
+ [Parallelizable(ParallelScope.All)]
+ public class LogJanitorTest
+ {
+ [Test]
+ public void Keep_correct_number_of_newest_log_files()
+ {
+ var fs = Substitute.For();
+ var janitor = new LogJanitor(fs);
+
+ var testFileInfoList = new[]
+ {
+ Substitute.For(),
+ Substitute.For(),
+ Substitute.For(),
+ Substitute.For()
+ };
+
+ testFileInfoList[0].Name.Returns("trash_2021-05-15_19-00-00");
+ testFileInfoList[1].Name.Returns("trash_2021-05-15_20-00-00");
+ testFileInfoList[2].Name.Returns("trash_2021-05-15_21-00-00");
+ testFileInfoList[3].Name.Returns("trash_2021-05-15_22-00-00");
+
+ fs.DirectoryInfo.FromDirectoryName(Arg.Any()).GetFiles()
+ .Returns(testFileInfoList);
+
+ janitor.DeleteOldestLogFiles(2);
+
+ testFileInfoList[0].Received().Delete();
+ testFileInfoList[1].Received().Delete();
+ testFileInfoList[2].DidNotReceive().Delete();
+ testFileInfoList[3].DidNotReceive().Delete();
+ }
+ }
+}
diff --git a/src/Trash/AppPaths.cs b/src/Trash/AppPaths.cs
index 569d8330..a8bb2476 100644
--- a/src/Trash/AppPaths.cs
+++ b/src/Trash/AppPaths.cs
@@ -9,5 +9,7 @@ namespace Trash
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "trash-updater");
public static string DefaultConfigPath { get; } = Path.Combine(AppContext.BaseDirectory, "trash.yml");
+
+ public static string LogDirectory { get; } = Path.Combine(AppDataPath, "logs");
}
}
diff --git a/src/Trash/Command/ServiceCommand.cs b/src/Trash/Command/ServiceCommand.cs
index 08d7bbc2..d8b51aa6 100644
--- a/src/Trash/Command/ServiceCommand.cs
+++ b/src/Trash/Command/ServiceCommand.cs
@@ -19,10 +19,12 @@ namespace Trash.Command
public abstract class ServiceCommand : ICommand, IServiceCommand
{
private readonly LoggingLevelSwitch _loggingLevelSwitch;
+ private readonly ILogJanitor _logJanitor;
- protected ServiceCommand(ILogger logger, LoggingLevelSwitch loggingLevelSwitch)
+ protected ServiceCommand(ILogger logger, LoggingLevelSwitch loggingLevelSwitch, ILogJanitor logJanitor)
{
_loggingLevelSwitch = loggingLevelSwitch;
+ _logJanitor = logJanitor;
Log = logger;
}
@@ -54,6 +56,10 @@ namespace Trash.Command
Log.Error(e, "Unrecoverable Exception");
ExitDueToFailure();
}
+ finally
+ {
+ CleanupOldLogFiles();
+ }
}
[CommandOption("preview", 'p', Description =
@@ -72,6 +78,11 @@ namespace Trash.Command
public abstract string CacheStoragePath { get; }
+ private void CleanupOldLogFiles()
+ {
+ _logJanitor.DeleteOldestLogFiles(20);
+ }
+
private void SetupLogging()
{
_loggingLevelSwitch.MinimumLevel =
diff --git a/src/Trash/CompositionRoot.cs b/src/Trash/CompositionRoot.cs
index 5b34f157..63888a28 100644
--- a/src/Trash/CompositionRoot.cs
+++ b/src/Trash/CompositionRoot.cs
@@ -1,4 +1,6 @@
-using System.IO.Abstractions;
+using System;
+using System.IO;
+using System.IO.Abstractions;
using System.Reflection;
using Autofac;
using Autofac.Extras.AggregateService;
@@ -27,16 +29,23 @@ namespace Trash
{
private static void SetupLogging(ContainerBuilder builder)
{
+ builder.RegisterType().As();
builder.RegisterType().SingleInstance();
builder.Register(c =>
{
- const string template = "[{Level:u3}] {Message:lj}{NewLine}{Exception}";
+ var logPath = Path.Combine(AppPaths.LogDirectory,
+ $"trash_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log");
+
+ const string consoleTemplate = "[{Level:u3}] {Message:lj}{NewLine}{Exception}";
+
return new LoggerConfiguration()
- .MinimumLevel.ControlledBy(c.Resolve())
- .WriteTo.Console(outputTemplate: template)
+ .MinimumLevel.Debug()
+ .WriteTo.Console(outputTemplate: consoleTemplate, levelSwitch: c.Resolve())
+ .WriteTo.File(logPath)
.CreateLogger();
})
- .As();
+ .As()
+ .SingleInstance();
}
private static void SonarrRegistrations(ContainerBuilder builder)
@@ -123,9 +132,7 @@ namespace Trash
public static IContainer Setup(ContainerBuilder builder)
{
- builder.RegisterType()
- .As();
-
+ builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As();
diff --git a/src/Trash/ILogJanitor.cs b/src/Trash/ILogJanitor.cs
new file mode 100644
index 00000000..766d65c9
--- /dev/null
+++ b/src/Trash/ILogJanitor.cs
@@ -0,0 +1,7 @@
+namespace Trash
+{
+ public interface ILogJanitor
+ {
+ void DeleteOldestLogFiles(int numberOfNewestToKeep);
+ }
+}
diff --git a/src/Trash/LogJanitor.cs b/src/Trash/LogJanitor.cs
new file mode 100644
index 00000000..bd52351f
--- /dev/null
+++ b/src/Trash/LogJanitor.cs
@@ -0,0 +1,25 @@
+using System.IO.Abstractions;
+using System.Linq;
+
+namespace Trash
+{
+ public class LogJanitor : ILogJanitor
+ {
+ private readonly IFileSystem _fileSystem;
+
+ public LogJanitor(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
+ public void DeleteOldestLogFiles(int numberOfNewestToKeep)
+ {
+ foreach (var file in _fileSystem.DirectoryInfo.FromDirectoryName(AppPaths.LogDirectory).GetFiles()
+ .OrderByDescending(f => f.Name)
+ .Skip(numberOfNewestToKeep))
+ {
+ file.Delete();
+ }
+ }
+ }
+}
diff --git a/src/Trash/Radarr/RadarrCommand.cs b/src/Trash/Radarr/RadarrCommand.cs
index 979497cf..4a7cbbfe 100644
--- a/src/Trash/Radarr/RadarrCommand.cs
+++ b/src/Trash/Radarr/RadarrCommand.cs
@@ -24,10 +24,11 @@ namespace Trash.Radarr
public RadarrCommand(
ILogger logger,
LoggingLevelSwitch loggingLevelSwitch,
+ ILogJanitor logJanitor,
IConfigurationLoader configLoader,
Func qualityUpdaterFactory,
Lazy customFormatUpdater)
- : base(logger, loggingLevelSwitch)
+ : base(logger, loggingLevelSwitch, logJanitor)
{
_configLoader = configLoader;
_qualityUpdaterFactory = qualityUpdaterFactory;
diff --git a/src/Trash/Sonarr/SonarrCommand.cs b/src/Trash/Sonarr/SonarrCommand.cs
index adb2b835..83a8b982 100644
--- a/src/Trash/Sonarr/SonarrCommand.cs
+++ b/src/Trash/Sonarr/SonarrCommand.cs
@@ -24,10 +24,11 @@ namespace Trash.Sonarr
public SonarrCommand(
ILogger logger,
LoggingLevelSwitch loggingLevelSwitch,
+ ILogJanitor logJanitor,
IConfigurationLoader configLoader,
Func profileUpdaterFactory,
Func qualityUpdaterFactory)
- : base(logger, loggingLevelSwitch)
+ : base(logger, loggingLevelSwitch, logJanitor)
{
_configLoader = configLoader;
_profileUpdaterFactory = profileUpdaterFactory;
diff --git a/src/Trash/Trash.csproj b/src/Trash/Trash.csproj
index 21a9d26b..c0c4d331 100644
--- a/src/Trash/Trash.csproj
+++ b/src/Trash/Trash.csproj
@@ -12,6 +12,7 @@
+