aboutsummaryrefslogtreecommitdiff
path: root/src/zenutil/logging/logging.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2026-03-23 12:53:58 +0100
committerGitHub Enterprise <[email protected]>2026-03-23 12:53:58 +0100
commite12feda1272922f6ad3567dd27509f0ec53d3a7b (patch)
tree8d238687c643a6790f9f307db3008a0e400caf42 /src/zenutil/logging/logging.cpp
parentDocumentation updates (#882) (diff)
downloadzen-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.cpp38
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