diff options
| author | Stefan Boberg <[email protected]> | 2026-03-23 12:53:58 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-03-23 12:53:58 +0100 |
| commit | e12feda1272922f6ad3567dd27509f0ec53d3a7b (patch) | |
| tree | 8d238687c643a6790f9f307db3008a0e400caf42 /src/zenutil/logging/logging.cpp | |
| parent | Documentation updates (#882) (diff) | |
| download | zen-e12feda1272922f6ad3567dd27509f0ec53d3a7b.tar.xz zen-e12feda1272922f6ad3567dd27509f0ec53d3a7b.zip | |
Logger simplification (#883)
- **`Logger` now holds a single `SinkPtr`** instead of a `std::vector<SinkPtr>`. The `SetSinks`/`AddSink` API is replaced with a single `SetSink`. This removes complexity from `Logger` itself and makes `Clone()` cheaper (no vector copy).
- **New `BroadcastSink`** (`zencore/logging/broadcastsink.h`) acts as a thread-safe, shared indirection point that fans out to a dynamic list of child sinks. Adding or removing a child sink via `AddSink`/`RemoveSink` is immediately visible to every `Logger` that holds a reference to it — including cloned loggers — without requiring each logger to be updated individually.
- **`GetDefaultBroadcastSink()`** (exposed from `zenutil/logging.h`) gives server-layer code access to the shared broadcast sink so it can register optional sinks (OTel, TCP log stream) after logging is initialized, without going through `Default()->AddSink()`.
### Motivation
Previously, dynamically adding sinks post-initialization mutated the default logger's internal sink vector directly. This was fragile: cloned loggers (created before `AddSink` was called) would not pick up the new sinks. `BroadcastSink` fixes this by making the sink list a shared, mutable object that all loggers sharing the same broadcast instance observe uniformly.
Diffstat (limited to 'src/zenutil/logging/logging.cpp')
| -rw-r--r-- | src/zenutil/logging/logging.cpp | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/src/zenutil/logging/logging.cpp b/src/zenutil/logging/logging.cpp index ea2448a42..e1755414b 100644 --- a/src/zenutil/logging/logging.cpp +++ b/src/zenutil/logging/logging.cpp @@ -8,6 +8,7 @@ #include <zencore/logging.h> #include <zencore/logging/ansicolorsink.h> #include <zencore/logging/asyncsink.h> +#include <zencore/logging/broadcastsink.h> #include <zencore/logging/logger.h> #include <zencore/logging/msvcsink.h> #include <zencore/logging/registry.h> @@ -23,8 +24,9 @@ namespace zen { -static bool g_IsLoggingInitialized; -logging::SinkPtr g_FileSink; +static bool g_IsLoggingInitialized; +logging::SinkPtr g_FileSink; +Ref<logging::BroadcastSink> g_BroadcastSink; logging::SinkPtr GetFileSink() @@ -32,6 +34,12 @@ GetFileSink() return g_FileSink; } +Ref<logging::BroadcastSink> +GetDefaultBroadcastSink() +{ + return g_BroadcastSink; +} + void InitializeLogging(const LoggingOptions& LogOptions) { @@ -117,8 +125,10 @@ BeginInitializeLogging(const LoggingOptions& LogOptions) LoggerRef DefaultLogger = zen::logging::Default(); - // Collect sinks into a local vector first so we can optionally wrap them - std::vector<logging::SinkPtr> Sinks; + // Build the broadcast sink — a shared indirection point that all + // loggers cloned from the default will share. Adding or removing + // a child sink later is immediately visible to every logger. + std::vector<logging::SinkPtr> BroadcastChildren; if (LogOptions.NoConsoleOutput) { @@ -126,17 +136,18 @@ BeginInitializeLogging(const LoggingOptions& LogOptions) } else { - logging::SinkPtr ConsoleSink(new logging::AnsiColorStdoutSink()); + logging::SinkPtr ConsoleSink( + new logging::AnsiColorStdoutSink(LogOptions.ForceColor ? logging::ColorMode::On : logging::ColorMode::Auto)); if (LogOptions.QuietConsole) { ConsoleSink->SetLevel(logging::Warn); } - Sinks.push_back(ConsoleSink); + BroadcastChildren.push_back(ConsoleSink); } if (FileSink) { - Sinks.push_back(FileSink); + BroadcastChildren.push_back(FileSink); } #if ZEN_PLATFORM_WINDOWS @@ -144,21 +155,21 @@ BeginInitializeLogging(const LoggingOptions& LogOptions) { logging::SinkPtr DebugSink(new logging::MsvcSink()); DebugSink->SetLevel(logging::Debug); - Sinks.push_back(DebugSink); + BroadcastChildren.push_back(DebugSink); } #endif + g_BroadcastSink = Ref<logging::BroadcastSink>(new logging::BroadcastSink(std::move(BroadcastChildren))); + bool IsAsync = LogOptions.AllowAsync && !LogOptions.IsDebug && !LogOptions.IsTest; if (IsAsync) { - std::vector<logging::SinkPtr> AsyncSinks; - AsyncSinks.emplace_back(new logging::AsyncSink(std::move(Sinks))); - DefaultLogger->SetSinks(std::move(AsyncSinks)); + DefaultLogger->SetSink(logging::SinkPtr(new logging::AsyncSink({logging::SinkPtr(g_BroadcastSink.Get())}))); } else { - DefaultLogger->SetSinks(std::move(Sinks)); + DefaultLogger->SetSink(logging::SinkPtr(g_BroadcastSink.Get())); } static struct : logging::ErrorHandler @@ -258,7 +269,8 @@ ShutdownLogging() zen::logging::ShutdownLogging(); - g_FileSink = nullptr; + g_FileSink = nullptr; + g_BroadcastSink = nullptr; } } // namespace zen |