aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-09-22 03:47:31 -0400
committerGitHub <[email protected]>2023-09-22 09:47:31 +0200
commit34132b6d936ea4077f8c96d84a00c74496332a4f (patch)
tree865131960ed43e2e9a0db5d2eb80144a204b4969 /src
parentImprovement: Add names to background jobs for easier debugging (#412) (diff)
downloadzen-34132b6d936ea4077f8c96d84a00c74496332a4f.tar.xz
zen-34132b6d936ea4077f8c96d84a00c74496332a4f.zip
add trace command to enable/disable tracing at runtime (#416)
* add trace command to enable/disable tracing at runtime * rework tracing init/start/stop * changelog
Diffstat (limited to 'src')
-rw-r--r--src/zen/cmds/trace.cpp93
-rw-r--r--src/zen/cmds/trace.h28
-rw-r--r--src/zen/zen.cpp3
-rw-r--r--src/zencore/include/zencore/trace.h5
-rw-r--r--src/zencore/trace.cpp74
-rw-r--r--src/zenserver/admin/admin.cpp67
-rw-r--r--src/zenserver/zenserver.cpp16
7 files changed, 248 insertions, 38 deletions
diff --git a/src/zen/cmds/trace.cpp b/src/zen/cmds/trace.cpp
new file mode 100644
index 000000000..f8968a680
--- /dev/null
+++ b/src/zen/cmds/trace.cpp
@@ -0,0 +1,93 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include "trace.h"
+#include <zencore/logging.h>
+#include <zenhttp/httpclient.h>
+#include <zenhttp/httpcommon.h>
+
+using namespace std::literals;
+
+namespace zen {
+
+TraceCommand::TraceCommand()
+{
+ m_Options.add_options()("h,help", "Print help");
+ m_Options.add_option("", "u", "hosturl", "Host URL", cxxopts::value(m_HostName)->default_value(""), "<hosturl>");
+ m_Options.add_option("", "s", "stop", "Stop tracing", cxxopts::value(m_Stop)->default_value("false"), "<stop>");
+ m_Options.add_option("", "", "host", "Start tracing to host", cxxopts::value(m_TraceHost), "<hostip>");
+ m_Options.add_option("", "", "file", "Start tracing to file", cxxopts::value(m_TraceFile), "<filepath>");
+}
+
+TraceCommand::~TraceCommand() = default;
+
+int
+TraceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
+{
+ ZEN_UNUSED(GlobalOptions);
+
+ if (!ParseOptions(argc, argv))
+ {
+ return 0;
+ }
+
+ m_HostName = ResolveTargetHostSpec(m_HostName);
+
+ if (m_HostName.empty())
+ {
+ throw OptionParseException("unable to resolve server specification");
+ }
+
+ zen::HttpClient Http(m_HostName);
+
+ if (m_Stop)
+ {
+ if (zen::HttpClient::Response Response = Http.Post("/admin/trace/stop"sv))
+ {
+ ZEN_CONSOLE("OK: {}", Response.ToText());
+ return 0;
+ }
+ else
+ {
+ ZEN_ERROR("trace stop failed: {}", Response.AsText());
+ return 1;
+ }
+ }
+
+ std::string StartArg;
+ if (!m_TraceHost.empty())
+ {
+ StartArg = fmt::format("host={}", m_TraceHost);
+ }
+ else if (!m_TraceFile.empty())
+ {
+ StartArg = fmt::format("file={}", m_TraceFile);
+ }
+
+ if (!StartArg.empty())
+ {
+ if (zen::HttpClient::Response Response = Http.Post(fmt::format("/admin/trace/start?{}"sv, StartArg)))
+ {
+ ZEN_CONSOLE("OK: {}", Response.ToText());
+ return 0;
+ }
+ else
+ {
+ ZEN_ERROR("trace start failed: {}", Response.AsText());
+ return 1;
+ }
+ }
+
+ if (zen::HttpClient::Response Response = Http.Get("/admin/trace"sv))
+ {
+ ZEN_CONSOLE("OK: {}", Response.ToText());
+ return 0;
+ }
+ else
+ {
+ ZEN_ERROR("trace status failed: {}", Response.AsText());
+ }
+
+ return 1;
+}
+
+} // namespace zen
diff --git a/src/zen/cmds/trace.h b/src/zen/cmds/trace.h
new file mode 100644
index 000000000..7b2d15fb1
--- /dev/null
+++ b/src/zen/cmds/trace.h
@@ -0,0 +1,28 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include "../zen.h"
+
+namespace zen {
+
+/** Scrub storage
+ */
+class TraceCommand : public ZenCmdBase
+{
+public:
+ TraceCommand();
+ ~TraceCommand();
+
+ virtual int Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
+ virtual cxxopts::Options& Options() override { return m_Options; }
+
+private:
+ cxxopts::Options m_Options{"trace", "Control zen realtime tracing"};
+ std::string m_HostName;
+ bool m_Stop;
+ std::string m_TraceHost;
+ std::string m_TraceFile;
+};
+
+} // namespace zen
diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp
index db67fbae0..8449c7a43 100644
--- a/src/zen/zen.cpp
+++ b/src/zen/zen.cpp
@@ -18,6 +18,7 @@
#include "cmds/serve.h"
#include "cmds/status.h"
#include "cmds/top.h"
+#include "cmds/trace.h"
#include "cmds/up.h"
#include "cmds/version.h"
#include "cmds/vfs_cmd.h"
@@ -228,6 +229,7 @@ main(int argc, char** argv)
StatusCommand StatusCmd;
JobCommand JobCmd;
TopCommand TopCmd;
+ TraceCommand TraceCmd;
UpCommand UpCmd;
AttachCommand AttachCmd;
VersionCommand VersionCmd;
@@ -278,6 +280,7 @@ main(int argc, char** argv)
{"status", &StatusCmd, "Show zen status"},
{"jobs", &JobCmd, "Show/cancel zen background jobs"},
{"top", &TopCmd, "Monitor zen server activity"},
+ {"trace", &TraceCmd, "Control zen realtime tracing"},
{"up", &UpCmd, "Bring zen server up"},
{"attach", &AttachCmd, "Add a sponsor process to a running zen service"},
{"version", &VersionCmd, "Get zen server version"},
diff --git a/src/zencore/include/zencore/trace.h b/src/zencore/include/zencore/trace.h
index 3bc2f7f02..665df5808 100644
--- a/src/zencore/include/zencore/trace.h
+++ b/src/zencore/include/zencore/trace.h
@@ -25,8 +25,11 @@ enum class TraceType
None
};
-void TraceInit(const char* HostOrPath, TraceType Type);
+void TraceInit();
void TraceShutdown();
+bool IsTracing();
+void TraceStart(const char* HostOrPath, TraceType Type);
+bool TraceStop();
#else
diff --git a/src/zencore/trace.cpp b/src/zencore/trace.cpp
index 6da5d28d6..d71ca0984 100644
--- a/src/zencore/trace.cpp
+++ b/src/zencore/trace.cpp
@@ -9,10 +9,48 @@
# include <zencore/trace.h>
void
-TraceInit(const char* HostOrPath, TraceType Type)
+TraceInit()
{
- bool EnableEvents = true;
+ static std::atomic_bool gInited = false;
+ bool Expected = false;
+ if (!gInited.compare_exchange_strong(Expected, true))
+ {
+ return;
+ }
+
+ trace::FInitializeDesc Desc = {
+ .bUseImportantCache = true,
+ };
+ trace::Initialize(Desc);
+ trace::ThreadRegister("main", /* system id */ 0, /* sort id */ 0);
+ trace::DescribeSession("zenserver",
+# if ZEN_BUILD_DEBUG
+ trace::Build::Debug,
+# else
+ trace::Build::Development,
+# endif
+ "",
+ ZEN_CFG_VERSION_BUILD_STRING);
+}
+
+void
+TraceShutdown()
+{
+ (void)TraceStop();
+ trace::Shutdown();
+}
+
+bool
+IsTracing()
+{
+ return trace::IsTracing();
+}
+
+void
+TraceStart(const char* HostOrPath, TraceType Type)
+{
+ TraceInit();
switch (Type)
{
case TraceType::Network:
@@ -24,34 +62,20 @@ TraceInit(const char* HostOrPath, TraceType Type)
break;
case TraceType::None:
- EnableEvents = false;
break;
}
-
- trace::FInitializeDesc Desc = {
- .bUseImportantCache = false,
- };
- trace::Initialize(Desc);
-
- if (EnableEvents)
- {
- trace::ToggleChannel("cpu", true);
- trace::ThreadRegister("main", /* system id */ 0, /* sort id */ 0);
- trace::DescribeSession("zenserver",
-# if ZEN_BUILD_DEBUG
- trace::Build::Debug,
-# else
- trace::Build::Development,
-# endif
- "",
- ZEN_CFG_VERSION_BUILD_STRING);
- }
+ trace::ToggleChannel("cpu", true);
}
-void
-TraceShutdown()
+bool
+TraceStop()
{
- trace::Shutdown();
+ trace::ToggleChannel("cpu", false);
+ if (trace::Stop())
+ {
+ return true;
+ }
+ return false;
}
#endif // ZEN_WITH_TRACE
diff --git a/src/zenserver/admin/admin.cpp b/src/zenserver/admin/admin.cpp
index cef2ba403..05ae0a24a 100644
--- a/src/zenserver/admin/admin.cpp
+++ b/src/zenserver/admin/admin.cpp
@@ -5,6 +5,10 @@
#include <zencore/compactbinarybuilder.h>
#include <zencore/jobqueue.h>
#include <zencore/string.h>
+#if ZEN_WITH_TRACE
+# include <zencore/trace.h>
+#endif // ZEN_WITH_TRACE
+
#include <zenstore/gc.h>
#include <chrono>
@@ -248,6 +252,69 @@ HttpAdminService::HttpAdminService(GcScheduler& Scheduler, JobQueue& BackgroundJ
Req.ServerRequest().WriteResponse(HttpResponseCode::OK, Obj.Save());
},
HttpVerb::kPost);
+#if ZEN_WITH_TRACE
+ m_Router.RegisterRoute(
+ "trace",
+ [this](HttpRouterRequest& Req) {
+ bool Enabled = IsTracing();
+ return Req.ServerRequest().WriteResponse(HttpResponseCode::OK, HttpContentType::kText, Enabled ? "enabled" : "disabled");
+ },
+ HttpVerb::kGet);
+
+ m_Router.RegisterRoute(
+ "trace/start",
+ [this](HttpRouterRequest& Req) {
+ HttpServerRequest& HttpReq = Req.ServerRequest();
+ const HttpServerRequest::QueryParams Params = HttpReq.GetQueryParams();
+ TraceType Type = TraceType::None;
+ std::string HostOrPath;
+ if (auto Param = Params.GetValue("file"); Param.empty() == false)
+ {
+ Type = TraceType::File;
+ HostOrPath = Param;
+ }
+ if (auto Param = Params.GetValue("host"); Param.empty() == false)
+ {
+ Type = TraceType::Network;
+ HostOrPath = Param;
+ }
+ if (Type == TraceType::None)
+ {
+ return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest,
+ HttpContentType::kText,
+ "Invalid trace type, use `file` or `host`"sv);
+ }
+ if (IsTracing())
+ {
+ return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest,
+ HttpContentType::kText,
+ "Tracing is already enabled"sv);
+ }
+ TraceStart(HostOrPath.c_str(), Type);
+ return Req.ServerRequest().WriteResponse(HttpResponseCode::OK, HttpContentType::kText, "Tracing started");
+ },
+ HttpVerb::kPost);
+
+ m_Router.RegisterRoute(
+ "trace/stop",
+ [this](HttpRouterRequest& Req) {
+ if (!IsTracing())
+ {
+ return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "Tracing is not enabled"sv);
+ }
+ if (TraceStop())
+ {
+ return Req.ServerRequest().WriteResponse(HttpResponseCode::OK, HttpContentType::kText, "Tracing stopped");
+ }
+ else
+ {
+ return Req.ServerRequest().WriteResponse(HttpResponseCode::InternalServerError,
+ HttpContentType::kText,
+ "Failed stopping trace");
+ }
+ },
+ HttpVerb::kPost);
+#endif // ZEN_WITH_TRACE
}
HttpAdminService::~HttpAdminService()
diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp
index 921e3038d..9c607f1d3 100644
--- a/src/zenserver/zenserver.cpp
+++ b/src/zenserver/zenserver.cpp
@@ -1420,14 +1420,6 @@ test_main(int argc, char** argv)
}
#endif
-#if ZEN_WITH_TRACE
-static void
-StopTrace()
-{
- TraceShutdown();
-}
-#endif // ZEN_WITH_TRACE
-
int
main(int argc, char* argv[])
{
@@ -1466,17 +1458,17 @@ main(int argc, char* argv[])
#if ZEN_WITH_TRACE
if (ServerOptions.TraceHost.size())
{
- TraceInit(ServerOptions.TraceHost.c_str(), TraceType::Network);
+ TraceStart(ServerOptions.TraceHost.c_str(), TraceType::Network);
}
else if (ServerOptions.TraceFile.size())
{
- TraceInit(ServerOptions.TraceFile.c_str(), TraceType::File);
+ TraceStart(ServerOptions.TraceFile.c_str(), TraceType::File);
}
else
{
- TraceInit(nullptr, TraceType::None);
+ TraceInit();
}
- atexit(StopTrace);
+ atexit(TraceShutdown);
#endif // ZEN_WITH_TRACE
#if ZEN_PLATFORM_WINDOWS