|
24 | 24 | namespace logtail { |
25 | 25 |
|
26 | 26 | const std::string CPUCollector::sName = "cpu"; |
27 | | -const std::string kMetricLabelCPU = "cpu"; |
28 | | -const std::string kMetricLabelMode = "mode"; |
29 | 27 |
|
| 28 | +CPUCollector::CPUCollector() { |
| 29 | + Init(); |
| 30 | +} |
| 31 | +int CPUCollector::Init(int totalCount) { |
| 32 | + mCountPerReport = totalCount; |
| 33 | + mCount = 0; |
| 34 | + return 0; |
| 35 | +} |
30 | 36 | bool CPUCollector::Collect(const HostMonitorTimerEvent::CollectConfig& collectConfig, PipelineEventGroup* group) { |
31 | 37 | if (group == nullptr) { |
| 38 | + LOG_ERROR(sLogger, ("PipelineEventGroup got nullptr", "skip")); |
32 | 39 | return false; |
33 | 40 | } |
34 | 41 | CPUInformation cpuInfo; |
| 42 | + CPUPercent totalCpuPercent{}; |
35 | 43 | if (!SystemInterface::GetInstance()->GetCPUInformation(cpuInfo)) { |
36 | 44 | return false; |
37 | 45 | } |
| 46 | + |
| 47 | + if (cpuInfo.stats.size() <= 1) { |
| 48 | + LOG_ERROR(sLogger, ("cpu count is negative", cpuInfo.stats.size())); |
| 49 | + return false; |
| 50 | + } |
| 51 | + |
38 | 52 | const time_t now = time(nullptr); |
39 | | - constexpr struct MetricDef { |
40 | | - const char* name; |
41 | | - const char* mode; |
42 | | - double CPUStat::*value; |
43 | | - } metrics[] = { |
44 | | - {"node_cpu_seconds_total", "user", &CPUStat::user}, |
45 | | - {"node_cpu_seconds_total", "nice", &CPUStat::nice}, |
46 | | - {"node_cpu_seconds_total", "system", &CPUStat::system}, |
47 | | - {"node_cpu_seconds_total", "idle", &CPUStat::idle}, |
48 | | - {"node_cpu_seconds_total", "iowait", &CPUStat::iowait}, |
49 | | - {"node_cpu_seconds_total", "irq", &CPUStat::irq}, |
50 | | - {"node_cpu_seconds_total", "softirq", &CPUStat::softirq}, |
51 | | - {"node_cpu_seconds_total", "steal", &CPUStat::steal}, |
52 | | - {"node_cpu_guest_seconds_total", "user", &CPUStat::guest}, |
53 | | - {"node_cpu_guest_seconds_total", "nice", &CPUStat::guestNice}, |
54 | | - }; |
| 53 | + |
55 | 54 | for (const auto& cpu : cpuInfo.stats) { |
56 | | - if (cpu.index == -1) { |
| 55 | + if (cpu.index != -1) { |
57 | 56 | continue; |
58 | 57 | } |
| 58 | + |
| 59 | + CPUStat cpuTotal = cpu; |
| 60 | + double cpuCores = cpuCount; |
| 61 | + if (!CalculateCPUPercent(totalCpuPercent, cpuTotal)) { |
| 62 | + return false; |
| 63 | + } |
| 64 | + // first time get cpu count and not calculate mCount |
| 65 | + if (cpuCount == 0) { |
| 66 | + cpuCount = cpuInfo.stats.size() - 1; |
| 67 | + return true; |
| 68 | + } |
| 69 | + |
| 70 | + cpuCount = cpuInfo.stats.size() - 1; |
| 71 | + mCalculate.AddValue(totalCpuPercent); |
| 72 | + mCount++; |
| 73 | + |
| 74 | + if (mCount < mCountPerReport) { |
| 75 | + return true; |
| 76 | + } |
| 77 | + |
| 78 | + CPUPercent minCPU, maxCPU, avgCPU, lastCPU; |
| 79 | + mCalculate.Stat(maxCPU, minCPU, avgCPU, &lastCPU); |
| 80 | + |
| 81 | + mCount = 0; |
| 82 | + mCalculate.Reset(); |
| 83 | + struct MetricDef { |
| 84 | + const char* name; |
| 85 | + double* value; |
| 86 | + } metrics[] = { |
| 87 | + {"cpu_system_avg", &avgCPU.sys}, {"cpu_system_min", &minCPU.sys}, {"cpu_system_max", &maxCPU.sys}, |
| 88 | + {"cpu_idle_avg", &avgCPU.idle}, {"cpu_idle_min", &minCPU.idle}, {"cpu_idle_max", &maxCPU.idle}, |
| 89 | + {"cpu_user_avg", &avgCPU.user}, {"cpu_user_min", &minCPU.user}, {"cpu_user_max", &maxCPU.user}, |
| 90 | + {"cpu_wait_avg", &avgCPU.wait}, {"cpu_wait_min", &minCPU.wait}, {"cpu_wait_max", &maxCPU.wait}, |
| 91 | + {"cpu_other_avg", &avgCPU.other}, {"cpu_other_min", &minCPU.other}, {"cpu_other_max", &maxCPU.other}, |
| 92 | + {"cpu_total_avg", &avgCPU.total}, {"cpu_total_min", &minCPU.total}, {"cpu_total_max", &maxCPU.total}, |
| 93 | + {"cpu_cores_value", &cpuCores}, |
| 94 | + |
| 95 | + }; |
| 96 | + MetricEvent* metricEvent = group->AddMetricEvent(true); |
| 97 | + if (!metricEvent) { |
| 98 | + return false; |
| 99 | + } |
| 100 | + metricEvent->SetTimestamp(now, 0); |
| 101 | + metricEvent->SetValue<UntypedMultiDoubleValues>(metricEvent); |
| 102 | + metricEvent->SetTag(std::string("m"), std::string("system.cpu")); |
| 103 | + auto* multiDoubleValues = metricEvent->MutableValue<UntypedMultiDoubleValues>(); |
59 | 104 | for (const auto& def : metrics) { |
60 | | - auto* metricEvent = group->AddMetricEvent(true); |
61 | | - if (!metricEvent) { |
62 | | - continue; |
63 | | - } |
64 | | - metricEvent->SetName(def.name); |
65 | | - metricEvent->SetTimestamp(now, 0); |
66 | | - metricEvent->SetValue<UntypedSingleValue>(cpu.*(def.value) / SYSTEM_HERTZ); |
67 | | - metricEvent->SetTag(kMetricLabelCPU, std::to_string(cpu.index)); |
68 | | - metricEvent->SetTagNoCopy(kMetricLabelMode, def.mode); |
| 105 | + multiDoubleValues->SetValue(std::string(def.name), |
| 106 | + UntypedMultiDoubleValue{UntypedValueMetricType::MetricTypeGauge, *def.value}); |
69 | 107 | } |
70 | 108 | } |
71 | 109 | return true; |
72 | 110 | } |
73 | 111 |
|
| 112 | +bool CPUCollector::CalculateCPUPercent(CPUPercent& cpuPercent, CPUStat& currentCpu) { |
| 113 | + if (cpuCount == 0) { |
| 114 | + lastCpu = currentCpu; |
| 115 | + cpuPercent.sys = cpuPercent.user = cpuPercent.wait = cpuPercent.idle = cpuPercent.other = cpuPercent.total |
| 116 | + = 0.0; |
| 117 | + LOG_DEBUG(sLogger, ("first time collect Cpu info", "empty")); |
| 118 | + return true; |
| 119 | + } |
| 120 | + |
| 121 | + double currentJiffies, lastJiffies, jiffiesDelta; |
| 122 | + currentJiffies = currentCpu.user + currentCpu.nice + currentCpu.system + currentCpu.idle + currentCpu.iowait |
| 123 | + + currentCpu.irq + currentCpu.softirq + currentCpu.steal; |
| 124 | + lastJiffies = lastCpu.user + lastCpu.nice + lastCpu.system + lastCpu.idle + lastCpu.iowait + lastCpu.irq |
| 125 | + + lastCpu.softirq + lastCpu.steal; |
| 126 | + jiffiesDelta = currentJiffies - lastJiffies; |
| 127 | + |
| 128 | + if (jiffiesDelta <= 0) { |
| 129 | + LOG_ERROR(sLogger, ("jiffies delta is negative", "skip")); |
| 130 | + return false; |
| 131 | + } |
| 132 | + |
| 133 | + cpuPercent.sys = (currentCpu.system - lastCpu.system) / jiffiesDelta * 100; |
| 134 | + cpuPercent.user = (currentCpu.user - lastCpu.user) / jiffiesDelta * 100; |
| 135 | + cpuPercent.wait = (currentCpu.iowait - lastCpu.iowait) / jiffiesDelta * 100; |
| 136 | + cpuPercent.idle = (currentCpu.idle - lastCpu.idle) / jiffiesDelta * 100; |
| 137 | + cpuPercent.other = (currentCpu.nice + currentCpu.irq + currentCpu.softirq + currentCpu.steal - lastCpu.nice |
| 138 | + - lastCpu.irq - lastCpu.softirq - lastCpu.steal) |
| 139 | + / jiffiesDelta * 100; |
| 140 | + cpuPercent.total = 100 - cpuPercent.idle; |
| 141 | + lastCpu = currentCpu; |
| 142 | + return true; |
| 143 | +} |
| 144 | + |
74 | 145 | } // namespace logtail |
0 commit comments