aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/include
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2026-03-12 15:03:03 +0100
committerGitHub Enterprise <[email protected]>2026-03-12 15:03:03 +0100
commit81bc43aa96f0059cecb28d1bd88338b7d84667f9 (patch)
treea3428cb7fddceae0b284d33562af5bf3e64a367e /src/zencore/include
parentupdate fmt 12.0.0 -> 12.1.0 (#828) (diff)
downloadzen-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.h44
-rw-r--r--src/zencore/include/zencore/logging.h6
-rw-r--r--src/zencore/include/zencore/logging/logger.h33
-rw-r--r--src/zencore/include/zencore/logging/registry.h4
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: