aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/admin/admin.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-12-12 12:38:54 +0100
committerGitHub <[email protected]>2023-12-12 12:38:54 +0100
commit1ea80957f0beac872d69009137b5308a1c8d0881 (patch)
tree5ce116efab10268eed3b2820ce57e132d38efd38 /src/zenserver/admin/admin.cpp
parentpremature logging shutdown fix (#603) (diff)
downloadzen-1ea80957f0beac872d69009137b5308a1c8d0881.tar.xz
zen-1ea80957f0beac872d69009137b5308a1c8d0881.zip
Adding an info command to display a top-level summary of disk space etc (#602)
this also adds a central, shared folder for storing information which may be found by any instance on the host. The directory is currently located alongside the default install and state directory. Initially this is used to store a collection of known `root_manifest` locations and a copy of the latest manifest version which allow us to find all known locations where zen state is present.
Diffstat (limited to 'src/zenserver/admin/admin.cpp')
-rw-r--r--src/zenserver/admin/admin.cpp129
1 files changed, 123 insertions, 6 deletions
diff --git a/src/zenserver/admin/admin.cpp b/src/zenserver/admin/admin.cpp
index c2df847ad..cc1ffdcdc 100644
--- a/src/zenserver/admin/admin.cpp
+++ b/src/zenserver/admin/admin.cpp
@@ -3,6 +3,7 @@
#include "admin.h"
#include <zencore/compactbinarybuilder.h>
+#include <zencore/filesystem.h>
#include <zencore/fmtutils.h>
#include <zencore/jobqueue.h>
#include <zencore/logging.h>
@@ -20,24 +21,86 @@
#include <zenstore/gc.h>
#include "cache/structuredcachestore.h"
+#include "config.h"
#include "projectstore/projectstore.h"
#include <chrono>
namespace zen {
-HttpAdminService::HttpAdminService(GcScheduler& Scheduler,
- JobQueue& BackgroundJobQueue,
- ZenCacheStore* CacheStore,
- CidStore* CidStore,
- ProjectStore* ProjectStore,
- const LogPaths& LogPaths)
+struct DirStats
+{
+ uint64_t FileCount = 0;
+ uint64_t DirCount = 0;
+ uint64_t ByteCount = 0;
+};
+
+DirStats
+GetStatsForDirectory(std::filesystem::path Dir)
+{
+ if (!std::filesystem::exists(Dir))
+ return {};
+
+ FileSystemTraversal Traversal;
+
+ struct StatsTraversal : public FileSystemTraversal::TreeVisitor
+ {
+ virtual void VisitFile(const std::filesystem::path& Parent, const path_view& File, uint64_t FileSize) override
+ {
+ ZEN_UNUSED(Parent, File);
+ ++TotalFileCount;
+ TotalBytes += FileSize;
+ }
+ virtual bool VisitDirectory(const std::filesystem::path&, const path_view&) override
+ {
+ ++TotalDirCount;
+ return true;
+ }
+
+ uint64_t TotalBytes = 0;
+ uint64_t TotalFileCount = 0;
+ uint64_t TotalDirCount = 0;
+
+ DirStats GetStats() { return {.FileCount = TotalFileCount, .DirCount = TotalDirCount, .ByteCount = TotalBytes}; }
+ };
+
+ StatsTraversal DirTraverser;
+ Traversal.TraverseFileSystem(Dir, DirTraverser);
+
+ return DirTraverser.GetStats();
+}
+
+struct StateDiskStats
+{
+ DirStats CacheStats;
+ DirStats CasStats;
+ DirStats ProjectStats;
+};
+
+StateDiskStats
+GetStatsForStateDirectory(std::filesystem::path StateDir)
+{
+ StateDiskStats Stats;
+ Stats.CacheStats = GetStatsForDirectory(StateDir / "cache");
+ Stats.CasStats = GetStatsForDirectory(StateDir / "cas");
+ Stats.ProjectStats = GetStatsForDirectory(StateDir / "projects");
+ return Stats;
+}
+
+HttpAdminService::HttpAdminService(GcScheduler& Scheduler,
+ JobQueue& BackgroundJobQueue,
+ ZenCacheStore* CacheStore,
+ CidStore* CidStore,
+ ProjectStore* ProjectStore,
+ const LogPaths& LogPaths,
+ const ZenServerOptions& ServerOptions)
: m_GcScheduler(Scheduler)
, m_BackgroundJobQueue(BackgroundJobQueue)
, m_CacheStore(CacheStore)
, m_CidStore(CidStore)
, m_ProjectStore(ProjectStore)
, m_LogPaths(LogPaths)
+, m_ServerOptions(ServerOptions)
{
using namespace std::literals;
@@ -509,6 +572,60 @@ HttpAdminService::HttpAdminService(GcScheduler& Scheduler,
#endif // ZEN_WITH_TRACE
m_Router.RegisterRoute(
+ "info",
+ [this](HttpRouterRequest& Req) {
+ CbObjectWriter Obj;
+
+ Obj << "root" << m_ServerOptions.SystemRootDir.generic_wstring();
+ Obj << "install" << (m_ServerOptions.SystemRootDir / "Install").generic_wstring();
+
+ Obj.BeginObject("primary");
+ Obj << "data" << m_ServerOptions.DataDir.generic_wstring();
+
+ try
+ {
+ auto Stats = GetStatsForStateDirectory(m_ServerOptions.DataDir);
+
+ auto EmitStats = [&](std::string_view Tag, const DirStats& Stats) {
+ Obj.BeginObject(Tag);
+ Obj << "bytes" << Stats.ByteCount;
+ Obj << "files" << Stats.FileCount;
+ Obj << "dirs" << Stats.DirCount;
+ Obj.EndObject();
+ };
+
+ EmitStats("cache", Stats.CacheStats);
+ EmitStats("cas", Stats.CasStats);
+ EmitStats("project", Stats.ProjectStats);
+ }
+ catch (std::exception& Ex)
+ {
+ ZEN_WARN("exception in disk stats gathering for '{}': {}", m_ServerOptions.DataDir, Ex.what());
+ }
+ Obj.EndObject();
+
+ try
+ {
+ std::vector<CbObject> Manifests = ReadAllCentralManifests(m_ServerOptions.SystemRootDir);
+
+ Obj.BeginArray("known");
+
+ for (const auto& Manifest : Manifests)
+ {
+ Obj.AddObject(Manifest);
+ }
+
+ Obj.EndArray();
+ }
+ catch (std::exception& Ex)
+ {
+ ZEN_WARN("exception in state gathering for '{}': {}", m_ServerOptions.SystemRootDir, Ex.what());
+ }
+ Req.ServerRequest().WriteResponse(HttpResponseCode::OK, Obj.Save());
+ },
+ HttpVerb::kGet);
+
+ m_Router.RegisterRoute(
"logs",
[this](HttpRouterRequest& Req) {
CbObjectWriter Obj;