aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2026-01-19 15:47:59 +0100
committerGitHub Enterprise <[email protected]>2026-01-19 15:47:59 +0100
commit975babca65c6e118db268c6335a4ecbf7c2a9744 (patch)
tree08c9ad8a58a7a2393ab10b26666d5fd29d44bd63 /src
parentZenServerProcess API changes (#719) (diff)
downloadzen-975babca65c6e118db268c6335a4ecbf7c2a9744.tar.xz
zen-975babca65c6e118db268c6335a4ecbf7c2a9744.zip
zenserver API changes, some other minor changes (#720)
* add system metrics output to top command * removed unnecessary xmake directives * file system API/comment tweaks * fixed out-of-range access in httpserver test * updated ZenServer base API to allow customization by mode
Diffstat (limited to 'src')
-rw-r--r--src/zen/cmds/top_cmd.cpp42
-rw-r--r--src/zen/xmake.lua2
-rw-r--r--src/zencore/include/zencore/filesystem.h15
-rw-r--r--src/zenhttp/httpserver.cpp2
-rw-r--r--src/zenserver/main.cpp54
-rw-r--r--src/zenserver/storage/zenstorageserver.cpp15
-rw-r--r--src/zenserver/storage/zenstorageserver.h3
-rw-r--r--src/zenserver/zenserver.cpp77
-rw-r--r--src/zenserver/zenserver.h5
9 files changed, 186 insertions, 29 deletions
diff --git a/src/zen/cmds/top_cmd.cpp b/src/zen/cmds/top_cmd.cpp
index 0e44dbbec..f674db6cd 100644
--- a/src/zen/cmds/top_cmd.cpp
+++ b/src/zen/cmds/top_cmd.cpp
@@ -4,6 +4,7 @@
#include <zencore/fmtutils.h>
#include <zencore/logging.h>
+#include <zencore/system.h>
#include <zencore/uid.h>
#include <zenutil/zenserverprocess.h>
@@ -24,6 +25,47 @@ TopCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
ZEN_UNUSED(GlobalOptions, argc, argv);
+ SystemMetrics Metrics = GetSystemMetrics();
+
+ struct SystemMetric
+ {
+ const char* Name;
+ uint64_t Value;
+ } MetricValues[] = {
+ {"Cpus", Metrics.CpuCount},
+ {"Cores", Metrics.CoreCount},
+ {"LPs", Metrics.LogicalProcessorCount},
+ {"SysMemMiB", Metrics.SystemMemoryMiB},
+ {"AvailSysMemMiB", Metrics.AvailSystemMemoryMiB},
+ {"VirtMemMiB", Metrics.VirtualMemoryMiB},
+ {"AvailVirtMemMiB", Metrics.AvailVirtualMemoryMiB},
+ {"PageFileMiB", Metrics.PageFileMiB},
+ {"AvailPageFileMiB", Metrics.AvailPageFileMiB},
+ };
+
+ std::vector<size_t> ColumnWidths;
+ for (const SystemMetric& Metric : MetricValues)
+ {
+ size_t NameLen = strlen(Metric.Name);
+ size_t ValueLen = fmt::formatted_size("{}", Metric.Value);
+ ColumnWidths.push_back(std::max(NameLen, ValueLen));
+ }
+
+ ExtendableStringBuilder<128> Header;
+ for (size_t i = 0; i < sizeof(MetricValues) / sizeof(MetricValues[0]); ++i)
+ {
+ Header << fmt::format("{:<{}} ", MetricValues[i].Name, ColumnWidths[i]);
+ }
+ ZEN_CONSOLE("{}", Header);
+
+ // Print values with same adaptive widths
+ ExtendableStringBuilder<128> Values;
+ for (size_t i = 0; i < sizeof(MetricValues) / sizeof(MetricValues[0]); ++i)
+ {
+ Values << fmt::format("{:>{}} ", MetricValues[i].Value, ColumnWidths[i]);
+ }
+ ZEN_CONSOLE("{}\n", Values);
+
ZenServerState State;
if (!State.InitializeReadOnly())
{
diff --git a/src/zen/xmake.lua b/src/zen/xmake.lua
index 55d073a86..ab094fef3 100644
--- a/src/zen/xmake.lua
+++ b/src/zen/xmake.lua
@@ -19,8 +19,6 @@ target("zen")
add_files("zen.rc")
add_ldflags("/subsystem:console,5.02")
add_ldflags("/LTCG")
- add_links("crypt32", "wldap32", "Ws2_32", "Shlwapi")
- add_links("dbghelp", "winhttp", "version") -- for Sentry
end
if is_plat("macosx") then
diff --git a/src/zencore/include/zencore/filesystem.h b/src/zencore/include/zencore/filesystem.h
index e3eafb875..f28863679 100644
--- a/src/zencore/include/zencore/filesystem.h
+++ b/src/zencore/include/zencore/filesystem.h
@@ -8,8 +8,14 @@
#include <zencore/iobuffer.h>
#include <zencore/string.h>
+ZEN_THIRD_PARTY_INCLUDES_START
#include <filesystem>
#include <functional>
+ZEN_THIRD_PARTY_INCLUDES_END
+
+#if ZEN_PLATFORM_WINDOWS
+# undef CopyFile
+#endif
namespace zen {
@@ -28,7 +34,7 @@ bool DeleteDirectories(const std::filesystem::path& Path, std::error_code& Ec);
/** Ensure directory exists.
- Will also create any required parent direCleanDirectoryctories
+ Will also create any required parent directories
*/
bool CreateDirectories(const std::filesystem::path& Path);
@@ -149,8 +155,15 @@ struct FileContents
std::error_code ErrorCode;
IoBuffer Flatten();
+
+ explicit operator bool() const { return !ErrorCode; }
};
+/** Read all of standard input into a FileContents structure
+ *
+ * Note that this will block until end-of-file is reached on standard input
+ * which could be a very bad idea in some contexts.
+ */
FileContents ReadStdIn();
/** Prepare file for reading
diff --git a/src/zenhttp/httpserver.cpp b/src/zenhttp/httpserver.cpp
index 085275195..c4e67d4ed 100644
--- a/src/zenhttp/httpserver.cpp
+++ b/src/zenhttp/httpserver.cpp
@@ -1345,7 +1345,7 @@ TEST_CASE("http.common")
"{a}",
[&](auto& Req) {
HandledA = true;
- Captures = {std::string(Req.GetCapture(1))};
+ Captures = {std::string(Req.GetCapture(0))};
},
HttpVerb::kGet);
diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp
index da256d06d..78bce7d06 100644
--- a/src/zenserver/main.cpp
+++ b/src/zenserver/main.cpp
@@ -54,8 +54,6 @@ SignalCallbackHandler(int SigNum)
namespace zen {
-using namespace std::literals;
-
//////////////////////////////////////////////////////////////////////////
#if ZEN_PLATFORM_WINDOWS
@@ -89,6 +87,13 @@ AppMain(int argc, char* argv[])
{
using namespace std::literals;
+ signal(SIGINT, utils::SignalCallbackHandler);
+ signal(SIGTERM, utils::SignalCallbackHandler);
+
+#if ZEN_PLATFORM_LINUX
+ IgnoreChildSignals();
+#endif
+
try
{
typename Main::Config ServerOptions;
@@ -227,26 +232,49 @@ main(int argc, char* argv[])
#endif // ZEN_PLATFORM_WINDOWS
using namespace zen;
+ using namespace std::literals;
+
+ auto _ = zen::MakeGuard([] {
+ // Allow some time for worker threads to unravel, in an effort
+ // to prevent shutdown races in TLS object destruction
+ WaitForThreads(1000);
+ });
+
+ enum
+ {
+ kHub,
+ kStore,
+ kTest
+ } ServerMode = kStore;
if (argc >= 2)
{
- if (argv[1] == "test"sv)
+ if (argv[1] == "hub"sv)
{
+ ServerMode = kHub;
+ }
+ else if (argv[1] == "store"sv)
+ {
+ ServerMode = kStore;
+ }
+ else if (argv[1] == "test"sv)
+ {
+ ServerMode = kTest;
+ }
+ }
+
+ switch (ServerMode)
+ {
+ case kTest:
#if ZEN_WITH_TESTS
return test_main(argc, argv);
#else
fprintf(stderr, "test option not available in release mode!\n");
exit(5);
#endif
- }
+ break;
+ default:
+ case kStore:
+ return AppMain<ZenStorageServerMain>(argc, argv);
}
-
- signal(SIGINT, utils::SignalCallbackHandler);
- signal(SIGTERM, utils::SignalCallbackHandler);
-
-#if ZEN_PLATFORM_LINUX
- IgnoreChildSignals();
-#endif
-
- return AppMain<ZenStorageServerMain>(argc, argv);
}
diff --git a/src/zenserver/storage/zenstorageserver.cpp b/src/zenserver/storage/zenstorageserver.cpp
index 559695a94..b2cae6482 100644
--- a/src/zenserver/storage/zenstorageserver.cpp
+++ b/src/zenserver/storage/zenstorageserver.cpp
@@ -17,6 +17,7 @@
#include <zencore/sentryintegration.h>
#include <zencore/session.h>
#include <zencore/string.h>
+#include <zencore/system.h>
#include <zencore/thread.h>
#include <zencore/timer.h>
#include <zencore/trace.h>
@@ -676,8 +677,8 @@ ZenStorageServer::Run()
" \\/ \\/ \\/ \\/ \\/ \n");
ExtendableStringBuilder<256> BuildOptions;
- GetBuildOptions(BuildOptions);
- ZEN_INFO("Build options: {}", BuildOptions);
+ GetBuildOptions(BuildOptions, '\n');
+ ZEN_INFO("Build options ({}/{}):\n{}", GetOperatingSystemName(), GetCpuName(), BuildOptions);
}
ZEN_INFO(ZEN_APP_NAME " now running (pid: {})", GetCurrentProcessId());
@@ -897,6 +898,16 @@ ZenStorageServerMain::ZenStorageServerMain(ZenStorageServerConfig& ServerOptions
{
}
+ZenStorageServerMain::~ZenStorageServerMain()
+{
+}
+
+void
+ZenStorageServerMain::InitializeLogging()
+{
+ InitializeServerLogging(m_ServerOptions, /* WithCacheService */ true);
+}
+
void
ZenStorageServerMain::DoRun(ZenServerState::ZenServerEntry* Entry)
{
diff --git a/src/zenserver/storage/zenstorageserver.h b/src/zenserver/storage/zenstorageserver.h
index f79c55bc8..5ccb587d6 100644
--- a/src/zenserver/storage/zenstorageserver.h
+++ b/src/zenserver/storage/zenstorageserver.h
@@ -103,7 +103,10 @@ class ZenStorageServerMain : public ZenServerMain
{
public:
ZenStorageServerMain(ZenStorageServerConfig& ServerOptions);
+ ~ZenStorageServerMain();
+
virtual void DoRun(ZenServerState::ZenServerEntry* Entry) override;
+ virtual void InitializeLogging() override;
ZenStorageServerMain(const ZenStorageServerMain&) = delete;
ZenStorageServerMain& operator=(const ZenStorageServerMain&) = delete;
diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp
index 95ea114bb..c5c36a4a8 100644
--- a/src/zenserver/zenserver.cpp
+++ b/src/zenserver/zenserver.cpp
@@ -151,6 +151,8 @@ ZenServerBase::Initialize(const ZenServerConfig& ServerOptions, ZenServerState::
EnqueueStatsReportingTimer();
}
+ LogSettingsSummary(ServerOptions);
+
return EffectiveBasePort;
}
@@ -163,24 +165,24 @@ ZenServerBase::Finalize()
}
void
-ZenServerBase::GetBuildOptions(StringBuilderBase& OutOptions)
+ZenServerBase::GetBuildOptions(StringBuilderBase& OutOptions, char Separator) const
{
ZEN_MEMSCOPE(GetZenserverTag());
OutOptions << "ZEN_ADDRESS_SANITIZER=" << (ZEN_ADDRESS_SANITIZER ? "1" : "0");
- OutOptions << ",";
+ OutOptions << Separator;
OutOptions << "ZEN_USE_SENTRY=" << (ZEN_USE_SENTRY ? "1" : "0");
- OutOptions << ",";
+ OutOptions << Separator;
OutOptions << "ZEN_WITH_TESTS=" << (ZEN_WITH_TESTS ? "1" : "0");
- OutOptions << ",";
+ OutOptions << Separator;
OutOptions << "ZEN_USE_MIMALLOC=" << (ZEN_USE_MIMALLOC ? "1" : "0");
- OutOptions << ",";
+ OutOptions << Separator;
OutOptions << "ZEN_USE_RPMALLOC=" << (ZEN_USE_RPMALLOC ? "1" : "0");
- OutOptions << ",";
+ OutOptions << Separator;
OutOptions << "ZEN_WITH_HTTPSYS=" << (ZEN_WITH_HTTPSYS ? "1" : "0");
- OutOptions << ",";
+ OutOptions << Separator;
OutOptions << "ZEN_WITH_MEMTRACK=" << (ZEN_WITH_MEMTRACK ? "1" : "0");
- OutOptions << ",";
+ OutOptions << Separator;
OutOptions << "ZEN_WITH_TRACE=" << (ZEN_WITH_TRACE ? "1" : "0");
}
@@ -374,6 +376,57 @@ ZenServerBase::HandleStatusRequest(HttpServerRequest& Request)
Request.WriteResponse(HttpResponseCode::OK, Cbo.Save());
}
+void
+ZenServerBase::LogSettingsSummary(const ZenServerConfig& ServerConfig)
+{
+ // clang-format off
+ std::list<std::pair<std::string_view, std::string>> Settings = {
+ {"DataDir"sv, ServerConfig.DataDir.string()},
+ {"AbsLogFile"sv, ServerConfig.AbsLogFile.string()},
+ {"SystemRootDir"sv, ServerConfig.SystemRootDir.string()},
+ {"ContentDir"sv, ServerConfig.ContentDir.string()},
+ {"BasePort"sv, fmt::to_string(ServerConfig.BasePort)},
+ {"IsDebug"sv, fmt::to_string(ServerConfig.IsDebug)},
+ {"IsCleanStart"sv, fmt::to_string(ServerConfig.IsCleanStart)},
+ {"IsPowerCycle"sv, fmt::to_string(ServerConfig.IsPowerCycle)},
+ {"IsTest"sv, fmt::to_string(ServerConfig.IsTest)},
+ {"Detach"sv, fmt::to_string(ServerConfig.Detach)},
+ {"NoConsoleOutput"sv, fmt::to_string(ServerConfig.NoConsoleOutput)},
+ {"QuietConsole"sv, fmt::to_string(ServerConfig.QuietConsole)},
+ {"CoreLimit"sv, fmt::to_string(ServerConfig.CoreLimit)},
+ {"IsDedicated"sv, fmt::to_string(ServerConfig.IsDedicated)},
+ {"ShouldCrash"sv, fmt::to_string(ServerConfig.ShouldCrash)},
+ {"ChildId"sv, ServerConfig.ChildId},
+ {"LogId"sv, ServerConfig.LogId},
+ {"Sentry DSN"sv, ServerConfig.SentryConfig.Dsn.empty() ? "not set" : ServerConfig.SentryConfig.Dsn},
+ {"Sentry Environment"sv, ServerConfig.SentryConfig.Environment},
+ {"Statsd Enabled"sv, fmt::to_string(ServerConfig.StatsConfig.Enabled)},
+ };
+ // clang-format on
+
+ if (ServerConfig.StatsConfig.Enabled)
+ {
+ Settings.emplace_back("Statsd Host", ServerConfig.StatsConfig.StatsdHost);
+ Settings.emplace_back("Statsd Port", fmt::to_string(ServerConfig.StatsConfig.StatsdPort));
+ }
+
+ size_t MaxWidth = 0;
+ for (const auto& Setting : Settings)
+ {
+ MaxWidth = std::max(MaxWidth, Setting.first.size());
+ }
+
+ ZEN_INFO("Server settings summary:");
+
+ for (const auto& Setting : Settings)
+ {
+ if (!Setting.second.empty())
+ {
+ ZEN_INFO(" {:<{}} : {}", Setting.first, MaxWidth, Setting.second);
+ }
+ }
+}
+
//////////////////////////////////////////////////////////////////////////
ZenServerMain::ZenServerMain(ZenServerConfig& ServerOptions) : m_ServerOptions(ServerOptions)
@@ -384,6 +437,12 @@ ZenServerMain::~ZenServerMain()
{
}
+void
+ZenServerMain::InitializeLogging()
+{
+ InitializeServerLogging(m_ServerOptions, /* WithCacheService */ false);
+}
+
int
ZenServerMain::Run()
{
@@ -511,7 +570,7 @@ ZenServerMain::Run()
}
}
- InitializeServerLogging(m_ServerOptions, /* WithCacheService */ true);
+ InitializeLogging();
ZEN_INFO("Command line: {}", m_ServerOptions.CommandLine);
diff --git a/src/zenserver/zenserver.h b/src/zenserver/zenserver.h
index 4de865a5f..ab7122fcc 100644
--- a/src/zenserver/zenserver.h
+++ b/src/zenserver/zenserver.h
@@ -10,6 +10,7 @@
#include <memory>
#include <string_view>
+#include "config/config.h"
ZEN_THIRD_PARTY_INCLUDES_START
#include <asio.hpp>
@@ -45,7 +46,8 @@ public:
protected:
int Initialize(const ZenServerConfig& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry);
void Finalize();
- void GetBuildOptions(StringBuilderBase& OutOptions);
+ void GetBuildOptions(StringBuilderBase& OutOptions, char Separator = ',') const;
+ void LogSettingsSummary(const ZenServerConfig& ServerConfig);
protected:
NamedMutex m_ServerMutex;
@@ -122,6 +124,7 @@ protected:
ZenServerConfig& m_ServerOptions;
LockFile m_LockFile;
+ virtual void InitializeLogging();
virtual void DoRun(ZenServerState::ZenServerEntry* Entry) = 0;
void NotifyReady();