From 7ce418d474578f934fe9e1c3d2d443964456d751 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 4 Jun 2026 19:11:50 +0200 Subject: [PATCH] feat(logging): shared LoggingSetup with build-config sink branching --- src/ClaudeDo.Logging/LoggingSetup.cs | 44 +++++++++++++++++++ .../Logging/LoggingSetupTests.cs | 30 +++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/ClaudeDo.Logging/LoggingSetup.cs create mode 100644 tests/ClaudeDo.Worker.Tests/Logging/LoggingSetupTests.cs diff --git a/src/ClaudeDo.Logging/LoggingSetup.cs b/src/ClaudeDo.Logging/LoggingSetup.cs new file mode 100644 index 0000000..c93ea40 --- /dev/null +++ b/src/ClaudeDo.Logging/LoggingSetup.cs @@ -0,0 +1,44 @@ +using Serilog; +using Serilog.Events; + +namespace ClaudeDo.Logging; + +public static class LoggingSetup +{ + private const string OutputTemplate = + "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Process}/{SourceContext} [{TaskId}] {Message:lj}{NewLine}{Exception}"; + + public static LoggerConfiguration Configure(LoggerConfiguration cfg, string processTag, string logRoot) + { + Directory.CreateDirectory(logRoot); + var logFile = Path.Combine(logRoot, "claudedo-.log"); + + cfg.Enrich.FromLogContext() + .Enrich.WithProperty("Process", processTag) + .Enrich.With(new DefaultTaskIdEnricher()); + + if (BuildConfig.IsDebug) + { + cfg.MinimumLevel.Debug() + .WriteTo.Console(outputTemplate: OutputTemplate) + .WriteTo.File( + logFile, + rollingInterval: RollingInterval.Day, + retainedFileCountLimit: 2, + shared: true, + outputTemplate: OutputTemplate); + } + else + { + cfg.MinimumLevel.Warning() + .WriteTo.File( + logFile, + rollingInterval: RollingInterval.Day, + retainedFileCountLimit: 2, + shared: true, + outputTemplate: OutputTemplate); + } + + return cfg; + } +} diff --git a/tests/ClaudeDo.Worker.Tests/Logging/LoggingSetupTests.cs b/tests/ClaudeDo.Worker.Tests/Logging/LoggingSetupTests.cs new file mode 100644 index 0000000..4706c9c --- /dev/null +++ b/tests/ClaudeDo.Worker.Tests/Logging/LoggingSetupTests.cs @@ -0,0 +1,30 @@ +using ClaudeDo.Logging; +using Serilog; + +namespace ClaudeDo.Worker.Tests.Logging; + +public sealed class LoggingSetupTests +{ + [Fact] + public void Configure_WritesSharedLogFile() + { + var logRoot = Path.Combine(Path.GetTempPath(), "claudedo-logtest-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(logRoot); + try + { + var logger = LoggingSetup.Configure(new LoggerConfiguration(), "test", logRoot).CreateLogger(); + logger.Warning("marker-{Marker}", "xyz"); + logger.Dispose(); // flush + release the file handle + + var files = Directory.GetFiles(logRoot, "claudedo-*.log"); + var file = Assert.Single(files); + var contents = File.ReadAllText(file); + Assert.Contains("marker-", contents); + Assert.Contains("test/", contents); // {Process} tag in the template + } + finally + { + try { Directory.Delete(logRoot, recursive: true); } catch { /* best effort */ } + } + } +}