diff options
| author | Stefan Boberg <[email protected]> | 2026-03-12 15:03:03 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-03-12 15:03:03 +0100 |
| commit | 81bc43aa96f0059cecb28d1bd88338b7d84667f9 (patch) | |
| tree | a3428cb7fddceae0b284d33562af5bf3e64a367e /src/zencore/include | |
| parent | update fmt 12.0.0 -> 12.1.0 (#828) (diff) | |
| download | zen-81bc43aa96f0059cecb28d1bd88338b7d84667f9.tar.xz zen-81bc43aa96f0059cecb28d1bd88338b7d84667f9.zip | |
Transparent proxy mode (#823)
Adds a **transparent TCP proxy mode** to zenserver (activated via `zenserver proxy`), allowing it to sit between clients and upstream Zen servers to inspect and monitor HTTP/1.x traffic in real time. Primarily useful during development, to be able to observe multi-server/client interactions in one place.
- **Dedicated proxy port** -- Proxy mode defaults to port 8118 with its own data directory to avoid collisions with a normal zenserver instance.
- **TCP proxy core** (`src/zenserver/proxy/`) -- A new transparent TCP proxy that forwards connections to upstream targets, with support for both TCP/IP and Unix socket listeners. Multi-threaded I/O for connection handling. Supports Unix domain sockets for both upstream/downstream.
- **HTTP traffic inspection** -- Parses HTTP/1.x request/response streams inline to extract method, path, status, content length, and WebSocket upgrades without breaking the proxied data.
- **Proxy dashboard** -- A web UI showing live connection stats, per-target request counts, active connections, bytes transferred, and client IP/session ID rollups.
- **Server mode display** -- Dashboard banner now shows the running server mode (Zen Proxy, Zen Compute, etc.).
Supporting changes included in this branch:
- **Wildcard log level matching** -- Log levels can now be set per-category using wildcard patterns (e.g. `proxy.*=debug`).
- **`zen down --all`** -- New flag to shut down all running zenserver instances; also used by the new `xmake kill` task.
- Minor test stability fixes (flaky hash collisions, per-thread RNG seeds).
- Support ZEN_MALLOC environment variable for default allocator selection and switch default to rpmalloc
- Fixed sentry-native build to allow LTO on Windows
Diffstat (limited to 'src/zencore/include')
| -rw-r--r-- | src/zencore/include/zencore/logbase.h | 44 | ||||
| -rw-r--r-- | src/zencore/include/zencore/logging.h | 6 | ||||
| -rw-r--r-- | src/zencore/include/zencore/logging/logger.h | 33 | ||||
| -rw-r--r-- | src/zencore/include/zencore/logging/registry.h | 4 |
4 files changed, 66 insertions, 21 deletions
diff --git a/src/zencore/include/zencore/logbase.h b/src/zencore/include/zencore/logbase.h index ece17a85e..ad2ab218d 100644 --- a/src/zencore/include/zencore/logbase.h +++ b/src/zencore/include/zencore/logbase.h @@ -2,8 +2,10 @@ #pragma once -#include <string_view> +#include <zenbase/refcount.h> +#include <atomic> +#include <string_view> namespace zen::logging { enum LogLevel : int @@ -54,6 +56,29 @@ struct LogPoint class Logger; +/** This is the base class for all loggers + + There's only one derived type - `Logger`. The reason this + exists is just to try and hide the full Logger definition + but once that is lightweight enough it may not be necessary + to have this split + */ +class LoggerBase : public TRefCounted<Logger> +{ +public: + bool ShouldLog(LogLevel InLevel) const { return InLevel >= m_Level.load(std::memory_order_relaxed); } + + void SetLevel(LogLevel InLevel) { m_Level.store(InLevel, std::memory_order_relaxed); } + LogLevel GetLevel() const { return m_Level.load(std::memory_order_relaxed); } + + void SetFlushLevel(LogLevel InLevel) { m_FlushLevel.store(InLevel, std::memory_order_relaxed); } + LogLevel GetFlushLevel() const { return m_FlushLevel.load(std::memory_order_relaxed); } + +protected: + std::atomic<LogLevel> m_Level{Info}; + std::atomic<LogLevel> m_FlushLevel{Off}; +}; + } // namespace zen::logging namespace zen { @@ -65,24 +90,25 @@ namespace zen { struct LoggerRef { LoggerRef() = default; - LoggerRef(logging::Logger& InLogger) : m_Logger(&InLogger) {} + explicit LoggerRef(logging::Logger& InLogger); // This exists so that logging macros can pass LoggerRef or LogCategory // to ZEN_LOG without needing to know which one it is LoggerRef Logger() { return *this; } - bool ShouldLog(logging::LogLevel Level) const; inline operator bool() const { return m_Logger != nullptr; } - inline logging::Logger* operator->() const { return m_Logger; } - inline logging::Logger& operator*() const { return *m_Logger; } + inline logging::Logger* operator->() const; + inline logging::Logger& operator*() const; + + bool ShouldLog(logging::LogLevel Level) const { return m_Logger->ShouldLog(Level); } + void SetLogLevel(logging::LogLevel NewLogLevel) { m_Logger->SetLevel(NewLogLevel); } + logging::LogLevel GetLogLevel() { return m_Logger->GetLevel(); } - void SetLogLevel(logging::LogLevel NewLogLevel); - logging::LogLevel GetLogLevel(); - void Flush(); + void Flush(); private: - logging::Logger* m_Logger = nullptr; + logging::LoggerBase* m_Logger = nullptr; }; } // namespace zen diff --git a/src/zencore/include/zencore/logging.h b/src/zencore/include/zencore/logging.h index 4b593c19e..dc5e05656 100644 --- a/src/zencore/include/zencore/logging.h +++ b/src/zencore/include/zencore/logging.h @@ -74,7 +74,11 @@ extern LoggerRef TheDefaultLogger; * Typically, classes which want to log to its own channel will declare a Log() * member function which returns a LoggerRef created at construction time. */ -LoggerRef Log(); +inline LoggerRef +Log() +{ + return TheDefaultLogger; +} using logging::ConsoleLog; using logging::ErrorLog; diff --git a/src/zencore/include/zencore/logging/logger.h b/src/zencore/include/zencore/logging/logger.h index 39d1139a5..c94bc58fa 100644 --- a/src/zencore/include/zencore/logging/logger.h +++ b/src/zencore/include/zencore/logging/logger.h @@ -17,7 +17,7 @@ public: virtual void HandleError(const std::string_view& Msg) = 0; }; -class Logger : public RefCounted +class Logger final : public LoggerBase { public: Logger(std::string_view InName, SinkPtr InSink); @@ -29,14 +29,6 @@ public: void Log(const LogPoint& Point, fmt::format_args Args); - bool ShouldLog(LogLevel InLevel) const { return InLevel >= m_Level.load(std::memory_order_relaxed); } - - void SetLevel(LogLevel InLevel) { m_Level.store(InLevel, std::memory_order_relaxed); } - LogLevel GetLevel() const { return m_Level.load(std::memory_order_relaxed); } - - void SetFlushLevel(LogLevel InLevel) { m_FlushLevel.store(InLevel, std::memory_order_relaxed); } - LogLevel GetFlushLevel() const { return m_FlushLevel.load(std::memory_order_relaxed); } - std::string_view Name() const; void SetSinks(std::vector<SinkPtr> InSinks); @@ -56,8 +48,27 @@ private: struct Impl; std::unique_ptr<Impl> m_Impl; - std::atomic<LogLevel> m_Level{Info}; - std::atomic<LogLevel> m_FlushLevel{Off}; }; } // namespace zen::logging + +namespace zen { + +// These can't be defined next to the LoggerRef declaration since +// they depend on knowing about logging::Logger above. But it's fine +// since to be able to use these you have to include this header +// anyway + +inline logging::Logger* +LoggerRef::operator->() const +{ + return static_cast<logging::Logger*>(m_Logger); +} + +inline logging::Logger& +LoggerRef::operator*() const +{ + return *static_cast<logging::Logger*>(m_Logger); +} + +} // namespace zen diff --git a/src/zencore/include/zencore/logging/registry.h b/src/zencore/include/zencore/logging/registry.h index a4d3692d2..71e84d75f 100644 --- a/src/zencore/include/zencore/logging/registry.h +++ b/src/zencore/include/zencore/logging/registry.h @@ -13,6 +13,10 @@ namespace zen::logging { +// Match a logger name against a pattern that may contain '*' wildcards. +// Supports '*' anywhere in the pattern (e.g. "proxy*", "*store", "zen*store"). +bool MatchLoggerPattern(std::string_view Pattern, std::string_view Name); + class Registry { public: |