11285115cSWilliam A. Kennington III // Copyright 2021 Google LLC 21285115cSWilliam A. Kennington III // 31285115cSWilliam A. Kennington III // Licensed under the Apache License, Version 2.0 (the "License"); 41285115cSWilliam A. Kennington III // you may not use this file except in compliance with the License. 51285115cSWilliam A. Kennington III // You may obtain a copy of the License at 61285115cSWilliam A. Kennington III // 71285115cSWilliam A. Kennington III // http://www.apache.org/licenses/LICENSE-2.0 81285115cSWilliam A. Kennington III // 91285115cSWilliam A. Kennington III // Unless required by applicable law or agreed to in writing, software 101285115cSWilliam A. Kennington III // distributed under the License is distributed on an "AS IS" BASIS, 111285115cSWilliam A. Kennington III // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 121285115cSWilliam A. Kennington III // See the License for the specific language governing permissions and 131285115cSWilliam A. Kennington III // limitations under the License. 141285115cSWilliam A. Kennington III 151285115cSWilliam A. Kennington III #include "metric.hpp" 161285115cSWilliam A. Kennington III 171285115cSWilliam A. Kennington III #include "metricblob.pb.h" 181285115cSWilliam A. Kennington III 191285115cSWilliam A. Kennington III #include "util.hpp" 201285115cSWilliam A. Kennington III 211285115cSWilliam A. Kennington III #include <sys/statvfs.h> 221285115cSWilliam A. Kennington III 231285115cSWilliam A. Kennington III #include <phosphor-logging/log.hpp> 241285115cSWilliam A. Kennington III 251285115cSWilliam A. Kennington III #include <cstdint> 261285115cSWilliam A. Kennington III #include <filesystem> 271285115cSWilliam A. Kennington III #include <sstream> 281285115cSWilliam A. Kennington III #include <string> 291285115cSWilliam A. Kennington III #include <string_view> 301285115cSWilliam A. Kennington III 311285115cSWilliam A. Kennington III namespace metric_blob 321285115cSWilliam A. Kennington III { 331285115cSWilliam A. Kennington III 341285115cSWilliam A. Kennington III using phosphor::logging::entry; 351285115cSWilliam A. Kennington III using phosphor::logging::log; 361285115cSWilliam A. Kennington III using level = phosphor::logging::level; 371285115cSWilliam A. Kennington III 381285115cSWilliam A. Kennington III BmcHealthSnapshot::BmcHealthSnapshot() : 391285115cSWilliam A. Kennington III done(false), stringId(0), ticksPerSec(0) 401285115cSWilliam A. Kennington III {} 411285115cSWilliam A. Kennington III 421285115cSWilliam A. Kennington III struct ProcStatEntry 431285115cSWilliam A. Kennington III { 441285115cSWilliam A. Kennington III std::string cmdline; 451285115cSWilliam A. Kennington III std::string tcomm; 461285115cSWilliam A. Kennington III float utime; 471285115cSWilliam A. Kennington III float stime; 481285115cSWilliam A. Kennington III 491285115cSWilliam A. Kennington III // Processes with the longest utime + stime are ranked first. 501285115cSWilliam A. Kennington III // Tie breaking is done with cmdline then tcomm. 511285115cSWilliam A. Kennington III bool operator<(const ProcStatEntry& other) const 521285115cSWilliam A. Kennington III { 531285115cSWilliam A. Kennington III const float negTime = -(utime + stime); 541285115cSWilliam A. Kennington III const float negOtherTime = -(other.utime + other.stime); 551285115cSWilliam A. Kennington III return std::tie(negTime, cmdline, tcomm) < 561285115cSWilliam A. Kennington III std::tie(negOtherTime, other.cmdline, other.tcomm); 571285115cSWilliam A. Kennington III } 581285115cSWilliam A. Kennington III }; 591285115cSWilliam A. Kennington III 601285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcProcStatMetric BmcHealthSnapshot::getProcStatList() 611285115cSWilliam A. Kennington III { 621285115cSWilliam A. Kennington III constexpr std::string_view procPath = "/proc/"; 631285115cSWilliam A. Kennington III 641285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcProcStatMetric ret; 651285115cSWilliam A. Kennington III std::vector<ProcStatEntry> entries; 661285115cSWilliam A. Kennington III 671285115cSWilliam A. Kennington III for (const auto& procEntry : std::filesystem::directory_iterator(procPath)) 681285115cSWilliam A. Kennington III { 691285115cSWilliam A. Kennington III const std::string& path = procEntry.path(); 701285115cSWilliam A. Kennington III int pid = -1; 711285115cSWilliam A. Kennington III if (isNumericPath(path, pid)) 721285115cSWilliam A. Kennington III { 731285115cSWilliam A. Kennington III ProcStatEntry entry; 741285115cSWilliam A. Kennington III 751285115cSWilliam A. Kennington III try 761285115cSWilliam A. Kennington III { 771285115cSWilliam A. Kennington III entry.cmdline = getCmdLine(pid); 781285115cSWilliam A. Kennington III TcommUtimeStime t = getTcommUtimeStime(pid, ticksPerSec); 791285115cSWilliam A. Kennington III entry.tcomm = t.tcomm; 801285115cSWilliam A. Kennington III entry.utime = t.utime; 811285115cSWilliam A. Kennington III entry.stime = t.stime; 821285115cSWilliam A. Kennington III 831285115cSWilliam A. Kennington III entries.push_back(entry); 841285115cSWilliam A. Kennington III } 851285115cSWilliam A. Kennington III catch (const std::exception& e) 861285115cSWilliam A. Kennington III { 871285115cSWilliam A. Kennington III log<level::ERR>("Could not obtain process stats"); 881285115cSWilliam A. Kennington III } 891285115cSWilliam A. Kennington III } 901285115cSWilliam A. Kennington III } 911285115cSWilliam A. Kennington III 921285115cSWilliam A. Kennington III std::sort(entries.begin(), entries.end()); 931285115cSWilliam A. Kennington III 941285115cSWilliam A. Kennington III bool isOthers = false; 951285115cSWilliam A. Kennington III ProcStatEntry others; 961285115cSWilliam A. Kennington III others.cmdline = "(Others)"; 971285115cSWilliam A. Kennington III others.utime = others.stime = 0; 981285115cSWilliam A. Kennington III 991285115cSWilliam A. Kennington III // Only show this many processes and aggregate all remaining ones into 1001285115cSWilliam A. Kennington III // "others" in order to keep the size of the snapshot reasonably small. 1011285115cSWilliam A. Kennington III // With 10 process stat entries and 10 FD count entries, the size of the 1021285115cSWilliam A. Kennington III // snapshot reaches around 1.5KiB. This is non-trivial, and we have to set 1031285115cSWilliam A. Kennington III // the collection interval long enough so as not to over-stress the IPMI 1041285115cSWilliam A. Kennington III // interface and the data collection service. The value of 10 is chosen 1051285115cSWilliam A. Kennington III // empirically, it might be subject to adjustments when the system is 1061285115cSWilliam A. Kennington III // launched later. 1071285115cSWilliam A. Kennington III constexpr int topN = 10; 1081285115cSWilliam A. Kennington III 1091285115cSWilliam A. Kennington III for (size_t i = 0; i < entries.size(); ++i) 1101285115cSWilliam A. Kennington III { 1111285115cSWilliam A. Kennington III if (i >= topN) 1121285115cSWilliam A. Kennington III { 1131285115cSWilliam A. Kennington III isOthers = true; 1141285115cSWilliam A. Kennington III } 1151285115cSWilliam A. Kennington III 1161285115cSWilliam A. Kennington III ProcStatEntry& entry = entries[i]; 1171285115cSWilliam A. Kennington III 1181285115cSWilliam A. Kennington III if (isOthers) 1191285115cSWilliam A. Kennington III { 1201285115cSWilliam A. Kennington III others.utime += entry.utime; 1211285115cSWilliam A. Kennington III others.stime += entry.stime; 1221285115cSWilliam A. Kennington III } 1231285115cSWilliam A. Kennington III else 1241285115cSWilliam A. Kennington III { 1251285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcProcStatMetric::BmcProcStat s; 1261285115cSWilliam A. Kennington III std::string fullCmdline = entry.cmdline; 1271285115cSWilliam A. Kennington III if (entry.tcomm.size() > 0) 1281285115cSWilliam A. Kennington III { 1291285115cSWilliam A. Kennington III fullCmdline += " " + entry.tcomm; 1301285115cSWilliam A. Kennington III } 1311285115cSWilliam A. Kennington III s.set_sidx_cmdline(getStringID(fullCmdline)); 1321285115cSWilliam A. Kennington III s.set_utime(entry.utime); 1331285115cSWilliam A. Kennington III s.set_stime(entry.stime); 1341285115cSWilliam A. Kennington III *(ret.add_stats()) = s; 1351285115cSWilliam A. Kennington III } 1361285115cSWilliam A. Kennington III } 1371285115cSWilliam A. Kennington III 1381285115cSWilliam A. Kennington III if (isOthers) 1391285115cSWilliam A. Kennington III { 1401285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcProcStatMetric::BmcProcStat s; 1411285115cSWilliam A. Kennington III s.set_sidx_cmdline(getStringID(others.cmdline)); 1421285115cSWilliam A. Kennington III s.set_utime(others.utime); 1431285115cSWilliam A. Kennington III s.set_stime(others.stime); 1441285115cSWilliam A. Kennington III *(ret.add_stats()) = s; 1451285115cSWilliam A. Kennington III } 1461285115cSWilliam A. Kennington III 1471285115cSWilliam A. Kennington III return ret; 1481285115cSWilliam A. Kennington III } 1491285115cSWilliam A. Kennington III 1501285115cSWilliam A. Kennington III int getFdCount(int pid) 1511285115cSWilliam A. Kennington III { 1521285115cSWilliam A. Kennington III const std::string& fdPath = "/proc/" + std::to_string(pid) + "/fd"; 1531285115cSWilliam A. Kennington III return std::distance(std::filesystem::directory_iterator(fdPath), 1541285115cSWilliam A. Kennington III std::filesystem::directory_iterator{}); 1551285115cSWilliam A. Kennington III } 1561285115cSWilliam A. Kennington III 1571285115cSWilliam A. Kennington III struct FdStatEntry 1581285115cSWilliam A. Kennington III { 1591285115cSWilliam A. Kennington III int fdCount; 1601285115cSWilliam A. Kennington III std::string cmdline; 1611285115cSWilliam A. Kennington III std::string tcomm; 1621285115cSWilliam A. Kennington III 1631285115cSWilliam A. Kennington III // Processes with the largest fdCount goes first. 1641285115cSWilliam A. Kennington III // Tie-breaking using cmdline then tcomm. 1651285115cSWilliam A. Kennington III bool operator<(const FdStatEntry& other) const 1661285115cSWilliam A. Kennington III { 1671285115cSWilliam A. Kennington III const int negFdCount = -fdCount; 1681285115cSWilliam A. Kennington III const int negOtherFdCount = -other.fdCount; 1691285115cSWilliam A. Kennington III return std::tie(negFdCount, cmdline, tcomm) < 1701285115cSWilliam A. Kennington III std::tie(negOtherFdCount, other.cmdline, other.tcomm); 1711285115cSWilliam A. Kennington III } 1721285115cSWilliam A. Kennington III }; 1731285115cSWilliam A. Kennington III 1741285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcFdStatMetric BmcHealthSnapshot::getFdStatList() 1751285115cSWilliam A. Kennington III { 1761285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcFdStatMetric ret; 1771285115cSWilliam A. Kennington III 1781285115cSWilliam A. Kennington III // Sort by fd count, no tie-breaking 1791285115cSWilliam A. Kennington III std::vector<FdStatEntry> entries; 1801285115cSWilliam A. Kennington III 1811285115cSWilliam A. Kennington III const std::string_view procPath = "/proc/"; 1821285115cSWilliam A. Kennington III for (const auto& procEntry : std::filesystem::directory_iterator(procPath)) 1831285115cSWilliam A. Kennington III { 1841285115cSWilliam A. Kennington III const std::string& path = procEntry.path(); 1851285115cSWilliam A. Kennington III int pid = 0; 1861285115cSWilliam A. Kennington III FdStatEntry entry; 1871285115cSWilliam A. Kennington III if (isNumericPath(path, pid)) 1881285115cSWilliam A. Kennington III { 1891285115cSWilliam A. Kennington III try 1901285115cSWilliam A. Kennington III { 1911285115cSWilliam A. Kennington III entry.fdCount = getFdCount(pid); 1921285115cSWilliam A. Kennington III TcommUtimeStime t = getTcommUtimeStime(pid, ticksPerSec); 1931285115cSWilliam A. Kennington III entry.cmdline = getCmdLine(pid); 1941285115cSWilliam A. Kennington III entry.tcomm = t.tcomm; 1951285115cSWilliam A. Kennington III entries.push_back(entry); 1961285115cSWilliam A. Kennington III } 1971285115cSWilliam A. Kennington III catch (const std::exception& e) 1981285115cSWilliam A. Kennington III { 1991285115cSWilliam A. Kennington III log<level::ERR>("Could not get file descriptor stats"); 2001285115cSWilliam A. Kennington III } 2011285115cSWilliam A. Kennington III } 2021285115cSWilliam A. Kennington III } 2031285115cSWilliam A. Kennington III 2041285115cSWilliam A. Kennington III std::sort(entries.begin(), entries.end()); 2051285115cSWilliam A. Kennington III 2061285115cSWilliam A. Kennington III bool isOthers = false; 2071285115cSWilliam A. Kennington III 2081285115cSWilliam A. Kennington III // Only report the detailed fd count and cmdline for the top 10 entries, 2091285115cSWilliam A. Kennington III // and collapse all others into "others". 2101285115cSWilliam A. Kennington III constexpr int topN = 10; 2111285115cSWilliam A. Kennington III 2121285115cSWilliam A. Kennington III FdStatEntry others; 2131285115cSWilliam A. Kennington III others.cmdline = "(Others)"; 2141285115cSWilliam A. Kennington III others.fdCount = 0; 2151285115cSWilliam A. Kennington III 2161285115cSWilliam A. Kennington III for (size_t i = 0; i < entries.size(); ++i) 2171285115cSWilliam A. Kennington III { 2181285115cSWilliam A. Kennington III if (i >= topN) 2191285115cSWilliam A. Kennington III { 2201285115cSWilliam A. Kennington III isOthers = true; 2211285115cSWilliam A. Kennington III } 2221285115cSWilliam A. Kennington III 2231285115cSWilliam A. Kennington III const FdStatEntry& entry = entries[i]; 2241285115cSWilliam A. Kennington III if (isOthers) 2251285115cSWilliam A. Kennington III { 2261285115cSWilliam A. Kennington III others.fdCount += entry.fdCount; 2271285115cSWilliam A. Kennington III } 2281285115cSWilliam A. Kennington III else 2291285115cSWilliam A. Kennington III { 2301285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcFdStatMetric::BmcFdStat s; 2311285115cSWilliam A. Kennington III std::string fullCmdline = entry.cmdline; 2321285115cSWilliam A. Kennington III if (entry.tcomm.size() > 0) 2331285115cSWilliam A. Kennington III { 2341285115cSWilliam A. Kennington III fullCmdline += " " + entry.tcomm; 2351285115cSWilliam A. Kennington III } 2361285115cSWilliam A. Kennington III s.set_sidx_cmdline(getStringID(fullCmdline)); 2371285115cSWilliam A. Kennington III s.set_fd_count(entry.fdCount); 2381285115cSWilliam A. Kennington III *(ret.add_stats()) = s; 2391285115cSWilliam A. Kennington III } 2401285115cSWilliam A. Kennington III } 2411285115cSWilliam A. Kennington III 2421285115cSWilliam A. Kennington III if (isOthers) 2431285115cSWilliam A. Kennington III { 2441285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcFdStatMetric::BmcFdStat s; 2451285115cSWilliam A. Kennington III s.set_sidx_cmdline(getStringID(others.cmdline)); 2461285115cSWilliam A. Kennington III s.set_fd_count(others.fdCount); 2471285115cSWilliam A. Kennington III *(ret.add_stats()) = s; 2481285115cSWilliam A. Kennington III } 2491285115cSWilliam A. Kennington III 2501285115cSWilliam A. Kennington III return ret; 2511285115cSWilliam A. Kennington III } 2521285115cSWilliam A. Kennington III 2531285115cSWilliam A. Kennington III void BmcHealthSnapshot::serializeSnapshotToArray( 2541285115cSWilliam A. Kennington III const bmcmetrics::metricproto::BmcMetricSnapshot& snapshot) 2551285115cSWilliam A. Kennington III { 2561285115cSWilliam A. Kennington III size_t size = snapshot.ByteSizeLong(); 2571285115cSWilliam A. Kennington III if (size > 0) 2581285115cSWilliam A. Kennington III { 2591285115cSWilliam A. Kennington III pbDump.resize(size); 2601285115cSWilliam A. Kennington III if (!snapshot.SerializeToArray(pbDump.data(), size)) 2611285115cSWilliam A. Kennington III { 2621285115cSWilliam A. Kennington III log<level::ERR>("Could not serialize protobuf to array"); 2631285115cSWilliam A. Kennington III } 2641285115cSWilliam A. Kennington III } 2651285115cSWilliam A. Kennington III } 2661285115cSWilliam A. Kennington III 2671285115cSWilliam A. Kennington III void BmcHealthSnapshot::doWork() 2681285115cSWilliam A. Kennington III { 2691285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcMetricSnapshot snapshot; 2701285115cSWilliam A. Kennington III 2711285115cSWilliam A. Kennington III // Memory info 272*b63d6314SMichael Shen std::string meminfoBuffer = readFileThenGrepIntoString("/proc/meminfo"); 2731285115cSWilliam A. Kennington III 2741285115cSWilliam A. Kennington III { 2751285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcMemoryMetric m; 2761285115cSWilliam A. Kennington III 2771285115cSWilliam A. Kennington III std::string_view sv(meminfoBuffer.data()); 2781285115cSWilliam A. Kennington III // MemAvailable 2791285115cSWilliam A. Kennington III int value; 2801285115cSWilliam A. Kennington III bool ok = parseMeminfoValue(sv, "MemAvailable:", value); 2811285115cSWilliam A. Kennington III if (ok) 2821285115cSWilliam A. Kennington III { 2831285115cSWilliam A. Kennington III m.set_mem_available(value); 2841285115cSWilliam A. Kennington III } 2851285115cSWilliam A. Kennington III 2861285115cSWilliam A. Kennington III ok = parseMeminfoValue(sv, "Slab:", value); 2871285115cSWilliam A. Kennington III if (ok) 2881285115cSWilliam A. Kennington III { 2891285115cSWilliam A. Kennington III m.set_slab(value); 2901285115cSWilliam A. Kennington III } 2911285115cSWilliam A. Kennington III 2921285115cSWilliam A. Kennington III ok = parseMeminfoValue(sv, "KernelStack:", value); 2931285115cSWilliam A. Kennington III if (ok) 2941285115cSWilliam A. Kennington III { 2951285115cSWilliam A. Kennington III m.set_kernel_stack(value); 2961285115cSWilliam A. Kennington III } 2971285115cSWilliam A. Kennington III 2981285115cSWilliam A. Kennington III *(snapshot.mutable_memory_metric()) = m; 2991285115cSWilliam A. Kennington III } 3001285115cSWilliam A. Kennington III 3011285115cSWilliam A. Kennington III // Uptime 302*b63d6314SMichael Shen std::string uptimeBuffer = readFileThenGrepIntoString("/proc/uptime"); 303*b63d6314SMichael Shen double uptime = 0; 304*b63d6314SMichael Shen double idleProcessTime = 0; 305*b63d6314SMichael Shen BootTimesMonotonic btm; 306*b63d6314SMichael Shen if (!parseProcUptime(uptimeBuffer, uptime, idleProcessTime)) 307*b63d6314SMichael Shen { 308*b63d6314SMichael Shen log<level::ERR>("Error parsing /proc/uptime"); 309*b63d6314SMichael Shen } 310*b63d6314SMichael Shen else if (!getBootTimesMonotonic(btm)) 311*b63d6314SMichael Shen { 312*b63d6314SMichael Shen log<level::ERR>("Could not get boot time"); 313*b63d6314SMichael Shen } 314*b63d6314SMichael Shen else 3151285115cSWilliam A. Kennington III { 3161285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcUptimeMetric m1; 3171285115cSWilliam A. Kennington III m1.set_uptime(uptime); 3181285115cSWilliam A. Kennington III m1.set_idle_process_time(idleProcessTime); 319*b63d6314SMichael Shen if (btm.firmwareTime == 0 && btm.powerOnSecCounterTime != 0) 320*b63d6314SMichael Shen { 321*b63d6314SMichael Shen m1.set_firmware_boot_time_sec( 322*b63d6314SMichael Shen static_cast<double>(btm.powerOnSecCounterTime) - uptime); 3231285115cSWilliam A. Kennington III } 3241285115cSWilliam A. Kennington III else 3251285115cSWilliam A. Kennington III { 326*b63d6314SMichael Shen m1.set_firmware_boot_time_sec( 327*b63d6314SMichael Shen static_cast<double>(btm.firmwareTime - btm.loaderTime) / 1e6); 328*b63d6314SMichael Shen } 329*b63d6314SMichael Shen m1.set_loader_boot_time_sec(static_cast<double>(btm.loaderTime) / 1e6); 330*b63d6314SMichael Shen // initrf presents 331*b63d6314SMichael Shen if (btm.initrdTime != 0) 332*b63d6314SMichael Shen { 333*b63d6314SMichael Shen m1.set_kernel_boot_time_sec(static_cast<double>(btm.initrdTime) / 334*b63d6314SMichael Shen 1e6); 335*b63d6314SMichael Shen m1.set_initrd_boot_time_sec( 336*b63d6314SMichael Shen static_cast<double>(btm.userspaceTime - btm.initrdTime) / 1e6); 337*b63d6314SMichael Shen m1.set_userspace_boot_time_sec( 338*b63d6314SMichael Shen static_cast<double>(btm.finishTime - btm.userspaceTime) / 1e6); 339*b63d6314SMichael Shen } 340*b63d6314SMichael Shen else 341*b63d6314SMichael Shen { 342*b63d6314SMichael Shen m1.set_kernel_boot_time_sec(static_cast<double>(btm.userspaceTime) / 343*b63d6314SMichael Shen 1e6); 344*b63d6314SMichael Shen m1.set_initrd_boot_time_sec(0); 345*b63d6314SMichael Shen m1.set_userspace_boot_time_sec( 346*b63d6314SMichael Shen static_cast<double>(btm.finishTime - btm.userspaceTime) / 1e6); 347*b63d6314SMichael Shen } 348*b63d6314SMichael Shen *(snapshot.mutable_uptime_metric()) = m1; 3491285115cSWilliam A. Kennington III } 3501285115cSWilliam A. Kennington III 3511285115cSWilliam A. Kennington III // Storage space 3521285115cSWilliam A. Kennington III struct statvfs fiData; 3531285115cSWilliam A. Kennington III if ((statvfs("/", &fiData)) < 0) 3541285115cSWilliam A. Kennington III { 3551285115cSWilliam A. Kennington III log<level::ERR>("Could not call statvfs"); 3561285115cSWilliam A. Kennington III } 3571285115cSWilliam A. Kennington III else 3581285115cSWilliam A. Kennington III { 3591285115cSWilliam A. Kennington III uint64_t kib = (fiData.f_bsize * fiData.f_bfree) / 1024; 3601285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcDiskSpaceMetric m2; 3611285115cSWilliam A. Kennington III m2.set_rwfs_kib_available(static_cast<int>(kib)); 3621285115cSWilliam A. Kennington III *(snapshot.mutable_storage_space_metric()) = m2; 3631285115cSWilliam A. Kennington III } 3641285115cSWilliam A. Kennington III 3651285115cSWilliam A. Kennington III // The next metrics require a sane ticks_per_sec value, typically 100 on 3661285115cSWilliam A. Kennington III // the BMC. In the very rare circumstance when it's 0, exit early and return 3671285115cSWilliam A. Kennington III // a partially complete snapshot (no process). 3681285115cSWilliam A. Kennington III ticksPerSec = getTicksPerSec(); 3691285115cSWilliam A. Kennington III 3701285115cSWilliam A. Kennington III // FD stat 3711285115cSWilliam A. Kennington III *(snapshot.mutable_fdstat_metric()) = getFdStatList(); 3721285115cSWilliam A. Kennington III 3731285115cSWilliam A. Kennington III if (ticksPerSec == 0) 3741285115cSWilliam A. Kennington III { 3751285115cSWilliam A. Kennington III log<level::ERR>("ticksPerSec is 0, skipping the process list metric"); 3761285115cSWilliam A. Kennington III serializeSnapshotToArray(snapshot); 3771285115cSWilliam A. Kennington III done = true; 3781285115cSWilliam A. Kennington III return; 3791285115cSWilliam A. Kennington III } 3801285115cSWilliam A. Kennington III 3811285115cSWilliam A. Kennington III // Proc stat 3821285115cSWilliam A. Kennington III *(snapshot.mutable_procstat_metric()) = getProcStatList(); 3831285115cSWilliam A. Kennington III 3841285115cSWilliam A. Kennington III // String table 3851285115cSWilliam A. Kennington III std::vector<std::string_view> strings(stringTable.size()); 3861285115cSWilliam A. Kennington III for (const auto& [s, i] : stringTable) 3871285115cSWilliam A. Kennington III { 3881285115cSWilliam A. Kennington III strings[i] = s; 3891285115cSWilliam A. Kennington III } 3901285115cSWilliam A. Kennington III 3911285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcStringTable st; 3921285115cSWilliam A. Kennington III for (size_t i = 0; i < strings.size(); ++i) 3931285115cSWilliam A. Kennington III { 3941285115cSWilliam A. Kennington III bmcmetrics::metricproto::BmcStringTable::StringEntry entry; 3951285115cSWilliam A. Kennington III entry.set_value(strings[i].data()); 3961285115cSWilliam A. Kennington III *(st.add_entries()) = entry; 3971285115cSWilliam A. Kennington III } 3981285115cSWilliam A. Kennington III *(snapshot.mutable_string_table()) = st; 3991285115cSWilliam A. Kennington III 4001285115cSWilliam A. Kennington III // Save to buffer 4011285115cSWilliam A. Kennington III serializeSnapshotToArray(snapshot); 4021285115cSWilliam A. Kennington III done = true; 4031285115cSWilliam A. Kennington III } 4041285115cSWilliam A. Kennington III 4051285115cSWilliam A. Kennington III // BmcBlobSessionStat (9) but passing meta as reference instead of pointer, 4061285115cSWilliam A. Kennington III // since the metadata must not be null at this point. 4071285115cSWilliam A. Kennington III bool BmcHealthSnapshot::stat(blobs::BlobMeta& meta) 4081285115cSWilliam A. Kennington III { 4091285115cSWilliam A. Kennington III if (!done) 4101285115cSWilliam A. Kennington III { 4111285115cSWilliam A. Kennington III // Bits 8~15 are blob-specific state flags. 4121285115cSWilliam A. Kennington III // For this blob, bit 8 is set when metric collection is still in 4131285115cSWilliam A. Kennington III // progress. 4141285115cSWilliam A. Kennington III meta.blobState |= (1 << 8); 4151285115cSWilliam A. Kennington III } 4161285115cSWilliam A. Kennington III else 4171285115cSWilliam A. Kennington III { 4181285115cSWilliam A. Kennington III meta.blobState = 0; 4191285115cSWilliam A. Kennington III meta.blobState = blobs::StateFlags::open_read; 4201285115cSWilliam A. Kennington III meta.size = pbDump.size(); 4211285115cSWilliam A. Kennington III } 4221285115cSWilliam A. Kennington III return true; 4231285115cSWilliam A. Kennington III } 4241285115cSWilliam A. Kennington III 4251285115cSWilliam A. Kennington III std::string_view BmcHealthSnapshot::read(uint32_t offset, 4261285115cSWilliam A. Kennington III uint32_t requestedSize) 4271285115cSWilliam A. Kennington III { 4281285115cSWilliam A. Kennington III uint32_t size = static_cast<uint32_t>(pbDump.size()); 4291285115cSWilliam A. Kennington III if (offset >= size) 4301285115cSWilliam A. Kennington III { 4311285115cSWilliam A. Kennington III return {}; 4321285115cSWilliam A. Kennington III } 4331285115cSWilliam A. Kennington III return std::string_view(pbDump.data() + offset, 4341285115cSWilliam A. Kennington III std::min(requestedSize, size - offset)); 4351285115cSWilliam A. Kennington III } 4361285115cSWilliam A. Kennington III 4371285115cSWilliam A. Kennington III int BmcHealthSnapshot::getStringID(const std::string_view s) 4381285115cSWilliam A. Kennington III { 4391285115cSWilliam A. Kennington III int ret = 0; 4401285115cSWilliam A. Kennington III auto itr = stringTable.find(s.data()); 4411285115cSWilliam A. Kennington III if (itr == stringTable.end()) 4421285115cSWilliam A. Kennington III { 4431285115cSWilliam A. Kennington III stringTable[s.data()] = stringId; 4441285115cSWilliam A. Kennington III ret = stringId; 4451285115cSWilliam A. Kennington III ++stringId; 4461285115cSWilliam A. Kennington III } 4471285115cSWilliam A. Kennington III else 4481285115cSWilliam A. Kennington III { 4491285115cSWilliam A. Kennington III ret = itr->second; 4501285115cSWilliam A. Kennington III } 4511285115cSWilliam A. Kennington III return ret; 4521285115cSWilliam A. Kennington III } 4531285115cSWilliam A. Kennington III 4541285115cSWilliam A. Kennington III } // namespace metric_blob