Skip to content

Commit 10dc0b2

Browse files
committed
Extract CMetrics dependent logic
Signed-off-by: Kentaro Hayashi <[email protected]>
1 parent f7e12d5 commit 10dc0b2

File tree

3 files changed

+135
-93
lines changed

3 files changed

+135
-93
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#
2+
# Copyright 2021- Kentaro Hayashi
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
require "cmetrics"
17+
require "etc"
18+
require "fluent/plugin/input"
19+
require "fluent/plugin/node_exporter/collector"
20+
21+
module Fluent
22+
module Plugin
23+
module NodeExporter
24+
class CpuCMetricsCollector < MetricsCollector
25+
def initialize(config={})
26+
super(config)
27+
28+
# It varies whether /sys/devices/system/cpu/cpuN/thermal_throttle exists or not
29+
@thermal_throttle_path = File.join(@sysfs_path, "devices/system/cpu/cpu0/thermal_throttle")
30+
31+
@core_throttles_total = if File.exist?(File.join(@thermal_throttle_path, "core_throttle_count"))
32+
CMetrics::Counter.new
33+
else
34+
nil
35+
end
36+
@core_throttles_total.create("node", "cpu", "core_throttles_total",
37+
"Number of times this CPU core has been throttled.",
38+
["core", "package"]) if @core_throttles_total
39+
40+
@package_throttles_total = if File.exist?(File.join(@thermal_throttle_path, "package_throttle_count"))
41+
CMetrics::Counter.new
42+
else
43+
nil
44+
end
45+
@package_throttles_total.create("node", "cpu", "package_throttles_total",
46+
"Number of times this CPU package has been throttled.",
47+
["package"]) if @package_throttles_total
48+
49+
@seconds_total = CMetrics::Counter.new
50+
@seconds_total.create("node", "cpu", "seconds_total",
51+
"Seconds the CPUs spent in each mode.",
52+
["cpu", "mode"])
53+
54+
@guest_seconds_total = CMetrics::Counter.new
55+
@guest_seconds_total.create("node", "cpu", "guest_seconds_total",
56+
"Seconds the CPUs spent in guests (VMs) for each mode.",
57+
["cpu", "mode"])
58+
59+
@core_throttles_set = {}
60+
@package_throttles_set = {}
61+
end
62+
63+
def run
64+
cpu_thermal_update
65+
cpu_stat_update
66+
end
67+
68+
def cpu_thermal_update
69+
scan_sysfs_path("devices/system/cpu/cpu[0-9]*").each do |path|
70+
next unless @core_throttles_total
71+
next unless @package_throttles_total
72+
73+
core_id_path = File.join(path, "topology", "core_id")
74+
physical_package_path = File.join(path, "topology", "physical_package_id")
75+
core_id = File.read(core_id_path).strip
76+
physical_package_id = File.read(physical_package_path).strip
77+
next if @core_throttles_set[{physical_package_id: physical_package_id, core_id: core_id}]
78+
@core_throttles_set[{physical_package_id: physical_package_id, core_id: core_id}] = true
79+
80+
core_throttle_count = File.read(File.join(path, "thermal_throttle", "core_throttle_count")).to_i
81+
@core_throttles_total.set(core_throttle_count, [core_id, physical_package_id])
82+
83+
next if @package_throttles_set[physical_package_id]
84+
@package_throttles_set[physical_package_id] = true
85+
86+
package_throttle_count = File.read(File.join(path, "thermal_throttle", "package_throttle_count")).to_i
87+
@package_throttles_total.set(package_throttle_count, [physical_package_id])
88+
89+
end
90+
end
91+
92+
STAT_CPU_PATTERN = /^cpu(?<cpuid>\d+)\s(?<user>\d+)\s(?<nice>\d+)\s(?<system>\d+)\s(?<idle>\d+)\s(?<iowait>\d+)\s(?<irq>\d+)\s(?<softirq>\d+)\s(?<steal>\d+)\s(?<guest>\d+)\s(?<guest_nice>\d+)/
93+
94+
def cpu_stat_update
95+
stat_path = File.join(@procfs_path, "stat")
96+
File.readlines(stat_path).each do |line|
97+
if line.start_with?("cpu ")
98+
# Ignore CPU total
99+
next
100+
elsif line.start_with?("cpu")
101+
user_hz = Etc.sysconf(Etc::SC_CLK_TCK)
102+
line.match(STAT_CPU_PATTERN) do |m|
103+
@seconds_total.set(m[:idle].to_f / user_hz, [m[:cpuid], "idle"])
104+
@seconds_total.set(m[:iowait].to_f / user_hz, [m[:cpuid], "iowait"])
105+
@seconds_total.set(m[:irq].to_f / user_hz, [m[:cpuid], "irq"])
106+
@seconds_total.set(m[:nice].to_f / user_hz, [m[:cpuid], "nice"])
107+
@seconds_total.set(m[:softirq].to_f / user_hz, [m[:cpuid], "softirq"])
108+
@seconds_total.set(m[:steal].to_f / user_hz, [m[:cpuid], "steal"])
109+
@seconds_total.set(m[:system].to_f / user_hz, [m[:cpuid], "system"])
110+
@seconds_total.set(m[:user].to_f / user_hz, [m[:cpuid], "user"])
111+
112+
@guest_seconds_total.set(m[:guest].to_f / user_hz, [m[:cpuid], "user"])
113+
@guest_seconds_total.set(m[:guest_nice].to_f / user_hz, [m[:cpuid], "nice"])
114+
end
115+
end
116+
end
117+
end
118+
119+
def cmetrics
120+
{
121+
core_throttles_total: @core_throttles_total,
122+
package_throttles_total: @package_throttles_total,
123+
seconds_total: @seconds_total,
124+
guest_seconds_total: @guest_seconds_total
125+
}
126+
end
127+
end
128+
end
129+
end
130+
end

lib/fluent/plugin/node_exporter/cpu_collector.rb

Lines changed: 4 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -17,112 +17,23 @@
1717
require "etc"
1818
require "fluent/plugin/input"
1919
require "fluent/plugin/node_exporter/collector"
20+
require "fluent/plugin/node_exporter/cmetrics/cpu_collector"
2021

2122
module Fluent
2223
module Plugin
2324
module NodeExporter
2425
class CpuMetricsCollector < MetricsCollector
2526
def initialize(config={})
2627
super(config)
27-
28-
# It varies whether /sys/devices/system/cpu/cpuN/thermal_throttle exists or not
29-
@thermal_throttle_path = File.join(@sysfs_path, "devices/system/cpu/cpu0/thermal_throttle")
30-
31-
@core_throttles_total = if File.exist?(File.join(@thermal_throttle_path, "core_throttle_count"))
32-
CMetrics::Counter.new
33-
else
34-
nil
35-
end
36-
@core_throttles_total.create("node", "cpu", "core_throttles_total",
37-
"Number of times this CPU core has been throttled.",
38-
["core", "package"]) if @core_throttles_total
39-
40-
@package_throttles_total = if File.exist?(File.join(@thermal_throttle_path, "package_throttle_count"))
41-
CMetrics::Counter.new
42-
else
43-
nil
44-
end
45-
@package_throttles_total.create("node", "cpu", "package_throttles_total",
46-
"Number of times this CPU package has been throttled.",
47-
["package"]) if @package_throttles_total
48-
49-
@seconds_total = CMetrics::Counter.new
50-
@seconds_total.create("node", "cpu", "seconds_total",
51-
"Seconds the CPUs spent in each mode.",
52-
["cpu", "mode"])
53-
54-
@guest_seconds_total = CMetrics::Counter.new
55-
@guest_seconds_total.create("node", "cpu", "guest_seconds_total",
56-
"Seconds the CPUs spent in guests (VMs) for each mode.",
57-
["cpu", "mode"])
58-
59-
@core_throttles_set = {}
60-
@package_throttles_set = {}
28+
@collector = CpuCMetricsCollector.new(config)
6129
end
6230

6331
def run
64-
cpu_thermal_update
65-
cpu_stat_update
66-
end
67-
68-
def cpu_thermal_update
69-
scan_sysfs_path("devices/system/cpu/cpu[0-9]*").each do |path|
70-
next unless @core_throttles_total
71-
next unless @package_throttles_total
72-
73-
core_id_path = File.join(path, "topology", "core_id")
74-
physical_package_path = File.join(path, "topology", "physical_package_id")
75-
core_id = File.read(core_id_path).strip
76-
physical_package_id = File.read(physical_package_path).strip
77-
next if @core_throttles_set[{physical_package_id: physical_package_id, core_id: core_id}]
78-
@core_throttles_set[{physical_package_id: physical_package_id, core_id: core_id}] = true
79-
80-
core_throttle_count = File.read(File.join(path, "thermal_throttle", "core_throttle_count")).to_i
81-
@core_throttles_total.set(core_throttle_count, [core_id, physical_package_id])
82-
83-
next if @package_throttles_set[physical_package_id]
84-
@package_throttles_set[physical_package_id] = true
85-
86-
package_throttle_count = File.read(File.join(path, "thermal_throttle", "package_throttle_count")).to_i
87-
@package_throttles_total.set(package_throttle_count, [physical_package_id])
88-
89-
end
90-
end
91-
92-
STAT_CPU_PATTERN = /^cpu(?<cpuid>\d+)\s(?<user>\d+)\s(?<nice>\d+)\s(?<system>\d+)\s(?<idle>\d+)\s(?<iowait>\d+)\s(?<irq>\d+)\s(?<softirq>\d+)\s(?<steal>\d+)\s(?<guest>\d+)\s(?<guest_nice>\d+)/
93-
94-
def cpu_stat_update
95-
stat_path = File.join(@procfs_path, "stat")
96-
File.readlines(stat_path).each do |line|
97-
if line.start_with?("cpu ")
98-
# Ignore CPU total
99-
next
100-
elsif line.start_with?("cpu")
101-
user_hz = Etc.sysconf(Etc::SC_CLK_TCK)
102-
line.match(STAT_CPU_PATTERN) do |m|
103-
@seconds_total.set(m[:idle].to_f / user_hz, [m[:cpuid], "idle"])
104-
@seconds_total.set(m[:iowait].to_f / user_hz, [m[:cpuid], "iowait"])
105-
@seconds_total.set(m[:irq].to_f / user_hz, [m[:cpuid], "irq"])
106-
@seconds_total.set(m[:nice].to_f / user_hz, [m[:cpuid], "nice"])
107-
@seconds_total.set(m[:softirq].to_f / user_hz, [m[:cpuid], "softirq"])
108-
@seconds_total.set(m[:steal].to_f / user_hz, [m[:cpuid], "steal"])
109-
@seconds_total.set(m[:system].to_f / user_hz, [m[:cpuid], "system"])
110-
@seconds_total.set(m[:user].to_f / user_hz, [m[:cpuid], "user"])
111-
112-
@guest_seconds_total.set(m[:guest].to_f / user_hz, [m[:cpuid], "user"])
113-
@guest_seconds_total.set(m[:guest_nice].to_f / user_hz, [m[:cpuid], "nice"])
114-
end
115-
end
116-
end
32+
@collector.run
11733
end
11834

11935
def cmetrics
120-
{
121-
core_throttles_total: @core_throttles_total,
122-
package_throttles_total: @package_throttles_total,
123-
seconds_total: @seconds_total,
124-
guest_seconds_total: @guest_seconds_total
125-
}
36+
@collector.cmetrics
12637
end
12738
end
12839
end

test/plugin/test_cpu_collector.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require "helper"
22
require "fluent/plugin/in_node_exporter_metrics"
33
require "fluent/plugin/node_exporter/cpu_collector"
4+
require "fluent/plugin/node_exporter/cmetrics/cpu_collector"
45

56
class CpuColectorTest < Test::Unit::TestCase
67
setup do

0 commit comments

Comments
 (0)