// Copyright Epic Games, Inc. All Rights Reserved. #include "top_cmd.h" #include #include #include #include #include #include #include ////////////////////////////////////////////////////////////////////////// namespace zen { TopCommand::TopCommand() { } TopCommand::~TopCommand() = default; void 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 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()) { ZEN_CONSOLE("No Zen state found"); return; } int n = 0; const int HeaderPeriod = 20; for (;;) { if ((n++ % HeaderPeriod) == 0) { ZEN_CONSOLE("{:>5} {:>6} {:>24} {}", "port", "pid", "session", "socket"); } State.Snapshot([&](const ZenServerState::ZenServerEntry& Entry) { StringBuilder<25> SessionStringBuilder; Entry.GetSessionId().ToString(SessionStringBuilder); std::string SocketPath; if (Entry.HasInstanceInfo()) { ZenServerInstanceInfo Info; if (Info.OpenReadOnly(Entry.GetSessionId())) { InstanceInfoData Data = Info.Read(); if (!Data.UnixSocketPath.empty()) { SocketPath = PathToUtf8(Data.UnixSocketPath); } } } std::string PortStr = Entry.IsNoNetwork() ? std::string("-") : fmt::to_string(Entry.EffectiveListenPort.load()); ZEN_CONSOLE("{:>5} {:>6} {:>24} {}", PortStr, Entry.Pid.load(), SessionStringBuilder, SocketPath); }); zen::Sleep(1000); if (!State.IsReadOnly()) { State.Sweep(); } } } ////////////////////////////////////////////////////////////////////////// PsCommand::PsCommand() { } PsCommand::~PsCommand() = default; void PsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions, argc, argv); ZenServerState State; if (!State.InitializeReadOnly()) { ZEN_CONSOLE("No Zen state found"); return; } State.Snapshot([&](const ZenServerState::ZenServerEntry& Entry) { std::string Extra; if (Entry.HasInstanceInfo()) { ZenServerInstanceInfo Info; if (Info.OpenReadOnly(Entry.GetSessionId())) { InstanceInfoData Data = Info.Read(); if (!Data.UnixSocketPath.empty()) { Extra = fmt::format(" (unix: {})", Data.UnixSocketPath); } } } std::string PortStr = Entry.IsNoNetwork() ? std::string("-") : fmt::to_string(Entry.EffectiveListenPort.load()); ZEN_CONSOLE("Port {} : pid {}{}", PortStr, Entry.Pid.load(), Extra); }); } } // namespace zen