fluent-plugin-node-exporter-metrics 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/linux-test.yaml +42 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +3 -0
- data/LICENSE +202 -0
- data/README.md +167 -0
- data/Rakefile +13 -0
- data/docs/cpu.md +26 -0
- data/docs/cpufreq.md +43 -0
- data/docs/diskstats.md +27 -0
- data/docs/filefd.md +12 -0
- data/docs/loadavg.md +13 -0
- data/docs/meminfo.md +61 -0
- data/docs/netdev.md +26 -0
- data/docs/stat.md +17 -0
- data/docs/time.md +9 -0
- data/docs/uname.md +15 -0
- data/docs/vmstat.md +17 -0
- data/fluent-plugin-node-exporter-metrics.gemspec +31 -0
- data/lib/fluent/plugin/in_node_exporter_metrics.rb +138 -0
- data/lib/fluent/plugin/node_exporter/cmetrics_dataschema_parser.rb +84 -0
- data/lib/fluent/plugin/node_exporter/collector.rb +41 -0
- data/lib/fluent/plugin/node_exporter/cpu_collector.rb +130 -0
- data/lib/fluent/plugin/node_exporter/cpufreq_collector.rb +97 -0
- data/lib/fluent/plugin/node_exporter/diskstats_collector.rb +280 -0
- data/lib/fluent/plugin/node_exporter/filefd_collector.rb +60 -0
- data/lib/fluent/plugin/node_exporter/loadavg_collector.rb +64 -0
- data/lib/fluent/plugin/node_exporter/meminfo_collector.rb +61 -0
- data/lib/fluent/plugin/node_exporter/netdev_collector.rb +92 -0
- data/lib/fluent/plugin/node_exporter/stat_collector.rb +84 -0
- data/lib/fluent/plugin/node_exporter/time_collector.rb +50 -0
- data/lib/fluent/plugin/node_exporter/uname_collector.rb +64 -0
- data/lib/fluent/plugin/node_exporter/vmstat_collector.rb +56 -0
- data/lib/fluent/plugin/parser_node_exporter_metrics.rb +54 -0
- data/test/fixtures/cpu/with_thermal_throttle/proc/stat +3 -0
- data/test/fixtures/cpu/with_thermal_throttle/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count +1 -0
- data/test/fixtures/cpu/with_thermal_throttle/sys/devices/system/cpu/cpu0/thermal_throttle/package_throttle_count +1 -0
- data/test/fixtures/cpu/with_thermal_throttle/sys/devices/system/cpu/cpu0/topology/core_id +1 -0
- data/test/fixtures/cpu/with_thermal_throttle/sys/devices/system/cpu/cpu0/topology/physical_package_id +1 -0
- data/test/fixtures/cpu/with_thermal_throttle/sys/devices/system/cpu/cpu1/thermal_throttle/core_throttle_count +1 -0
- data/test/fixtures/cpu/with_thermal_throttle/sys/devices/system/cpu/cpu1/thermal_throttle/package_throttle_count +1 -0
- data/test/fixtures/cpu/with_thermal_throttle/sys/devices/system/cpu/cpu1/topology/core_id +1 -0
- data/test/fixtures/cpu/with_thermal_throttle/sys/devices/system/cpu/cpu1/topology/physical_package_id +1 -0
- data/test/fixtures/cpu/without_thermal_throttle/proc/stat +3 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_max_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_min_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq +1 -0
- data/test/fixtures/cpufreq/with_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_max_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_min_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq +1 -0
- data/test/fixtures/cpufreq/without_cur_freq/sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq +1 -0
- data/test/helper.rb +24 -0
- data/test/plugin/test_cmetrics_data_schema_parser.rb +83 -0
- data/test/plugin/test_cpu_collector.rb +84 -0
- data/test/plugin/test_cpufreq_collector.rb +75 -0
- data/test/plugin/test_diskstats_collector.rb +200 -0
- data/test/plugin/test_filefd_collector.rb +39 -0
- data/test/plugin/test_in_node_exporter_metrics.rb +583 -0
- data/test/plugin/test_loadavg_collector.rb +41 -0
- data/test/plugin/test_meminfo_collector.rb +47 -0
- data/test/plugin/test_netdev_collector.rb +35 -0
- data/test/plugin/test_stat_collector.rb +37 -0
- data/test/plugin/test_time_collector.rb +15 -0
- data/test/plugin/test_uname_collector.rb +47 -0
- data/test/plugin/test_vmstat_collector.rb +53 -0
- metadata +273 -0
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
require "helper"
|
|
2
|
+
require "fluent/plugin/in_node_exporter_metrics.rb"
|
|
3
|
+
|
|
4
|
+
class NodeExporterMetricsInputTest < Test::Unit::TestCase
|
|
5
|
+
setup do
|
|
6
|
+
Fluent::Test.setup
|
|
7
|
+
@capability = Fluent::Capability.new(:current_process)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
teardown do
|
|
11
|
+
Fluent::Engine.stop
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
CONFIG = config_element("ROOT", "", {
|
|
15
|
+
"scrape_interval" => 5,
|
|
16
|
+
"procfs_path" => "/proc",
|
|
17
|
+
"sysfs_path" => "/sys",
|
|
18
|
+
"cpufreq" => false # assume linux capability is not set by default environment
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
ALL_COLLECTOR_NAMES = %w(cpu cpufreq diskstats filefd loadavg meminfo netdev stat time uname vmstat)
|
|
22
|
+
|
|
23
|
+
def create_driver(conf = CONFIG)
|
|
24
|
+
Fluent::Test::Driver::Input.new(Fluent::Plugin::NodeExporterMetricsInput).configure(conf)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def create_minimum_config_params
|
|
28
|
+
params = {"scrape_interval" => 1}
|
|
29
|
+
ALL_COLLECTOR_NAMES.each do |field|
|
|
30
|
+
params[field] = false
|
|
31
|
+
end
|
|
32
|
+
params
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def cpufreq_readable?
|
|
36
|
+
freq_path = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq"
|
|
37
|
+
Dir.exist?("/sys/devices/system/cpu/cpu0/cpufreq") and
|
|
38
|
+
File.exist?(freq_path) and
|
|
39
|
+
(File.readable?(freq_path) or cpufreq_capability?)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def cpufreq_capability?
|
|
43
|
+
@capability.have_capability?(:effective, :dac_read_search)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
sub_test_case "configure" do
|
|
47
|
+
def test_default_parameters
|
|
48
|
+
d = create_driver(CONFIG)
|
|
49
|
+
assert_equal([5, "/proc", "/sys"],
|
|
50
|
+
[d.instance.scrape_interval, d.instance.procfs_path, d.instance.sysfs_path])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_empty_collectors
|
|
54
|
+
params = {}
|
|
55
|
+
%w(cpu cpufreq diskstats filefd loadavg meminfo netdev stat time uname vmstat).each do |collector|
|
|
56
|
+
params[collector] = false
|
|
57
|
+
end
|
|
58
|
+
assert_raise(Fluent::ConfigError.new("all collectors are disabled. Enable at least one collector.")) do
|
|
59
|
+
create_driver(config_element("ROOT", "", params))
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_default_collectors_with_capability
|
|
64
|
+
omit "skip assertion when linux capability is not available" unless cpufreq_readable?
|
|
65
|
+
d = create_driver(config_element("ROOT", "", {}))
|
|
66
|
+
assert_equal([true] * 11,
|
|
67
|
+
[d.instance.cpu,
|
|
68
|
+
d.instance.cpufreq,
|
|
69
|
+
d.instance.diskstats,
|
|
70
|
+
d.instance.filefd,
|
|
71
|
+
d.instance.loadavg,
|
|
72
|
+
d.instance.meminfo,
|
|
73
|
+
d.instance.netdev,
|
|
74
|
+
d.instance.stat,
|
|
75
|
+
d.instance.time,
|
|
76
|
+
d.instance.uname,
|
|
77
|
+
d.instance.vmstat])
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_customizable
|
|
81
|
+
d = create_driver(config_element("ROOT", "", {
|
|
82
|
+
"scrape_interval" => 10,
|
|
83
|
+
"procfs_path" => "/proc/dummy",
|
|
84
|
+
"sysfs_path" => "/sys/dummy",
|
|
85
|
+
"cpu" => "true",
|
|
86
|
+
"cpufreq" => "false",
|
|
87
|
+
"diskstats" => "false",
|
|
88
|
+
"filefd" => "false",
|
|
89
|
+
"loadavg" => "false",
|
|
90
|
+
"meminfo" => "false",
|
|
91
|
+
"netdev" => "false",
|
|
92
|
+
"stat" => "false",
|
|
93
|
+
"time" => "false",
|
|
94
|
+
"uname" => "false",
|
|
95
|
+
"vmstat" => "false"
|
|
96
|
+
}))
|
|
97
|
+
assert_equal([10.0, "/proc/dummy", "/sys/dummy", true, false, false, false, false, false, false, false, false, false, false],
|
|
98
|
+
[d.instance.scrape_interval,
|
|
99
|
+
d.instance.procfs_path,
|
|
100
|
+
d.instance.sysfs_path,
|
|
101
|
+
d.instance.cpu,
|
|
102
|
+
d.instance.cpufreq,
|
|
103
|
+
d.instance.diskstats,
|
|
104
|
+
d.instance.filefd,
|
|
105
|
+
d.instance.loadavg,
|
|
106
|
+
d.instance.meminfo,
|
|
107
|
+
d.instance.netdev,
|
|
108
|
+
d.instance.stat,
|
|
109
|
+
d.instance.time,
|
|
110
|
+
d.instance.uname,
|
|
111
|
+
d.instance.vmstat])
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
sub_test_case "scrape interval" do
|
|
115
|
+
def test_shorter_interval
|
|
116
|
+
d = create_driver(config_element("ROOT", "", { "scrape_interval" => 2 , "cpufreq" => false}))
|
|
117
|
+
d.run(expect_records: 2, timeout: 5)
|
|
118
|
+
assert_equal(2, d.events.size)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_longer_interval
|
|
122
|
+
d = create_driver(config_element("ROOT", "", { "scrape_interval" => 10, "cpufreq" => false}))
|
|
123
|
+
d.run(expect_records: 1, timeout: 10)
|
|
124
|
+
assert_equal(1, d.events.size)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
sub_test_case "capability" do
|
|
130
|
+
def test_no_capability_error
|
|
131
|
+
unless @capability.have_capability?(:effective, :dac_read_search)
|
|
132
|
+
assert_raise(Fluent::ConfigError.new("Linux capability CAP_DAC_READ_SEARCH must be enabled")) do
|
|
133
|
+
d = create_driver(config_element("ROOT", "", {}))
|
|
134
|
+
d.run
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
sub_test_case "collectors" do
|
|
141
|
+
sub_test_case "cpu collector" do
|
|
142
|
+
def test_cpu_with_thermal_throttle
|
|
143
|
+
omit "thermal throttle requires specific sysfs" unless Dir.exist?("/sys/devices/system/cpu/cpu0/thermal_throttle")
|
|
144
|
+
|
|
145
|
+
params = create_minimum_config_params
|
|
146
|
+
params["cpu"] = true
|
|
147
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
148
|
+
d.run(expect_records: 1, timeout: 2)
|
|
149
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
150
|
+
# FIXME: size of core_throttles_total, package_throttles_total values
|
|
151
|
+
assert_equal([
|
|
152
|
+
4,
|
|
153
|
+
{"ns"=>"node", "ss"=>"cpu", "name"=>"core_throttles_total","desc"=>"Number of times this CPU core has been throttled."},
|
|
154
|
+
{"ns"=>"node", "ss"=>"cpu", "name"=>"package_throttles_total", "desc"=>"Number of times this CPU package has been throttled."},
|
|
155
|
+
{"ns"=>"node", "ss"=>"cpu", "name"=>"seconds_total", "desc"=>"Seconds the CPUs spent in each mode."},
|
|
156
|
+
{"ns"=>"node", "ss"=>"cpu", "name"=>"guest_seconds_total","desc"=>"Seconds the CPUs spent in guests (VMs) for each mode."},
|
|
157
|
+
Etc.nprocessors * ["idle", "iowait", "irq", "nice", "softirq", "steal", "system", "user"].size,
|
|
158
|
+
Etc.nprocessors * ["user", "nice"].size,
|
|
159
|
+
],
|
|
160
|
+
[
|
|
161
|
+
cmetrics.size,
|
|
162
|
+
cmetrics.collect do |metric|
|
|
163
|
+
metric["meta"]["opts"]
|
|
164
|
+
end,
|
|
165
|
+
cmetrics[2]["values"].size,
|
|
166
|
+
cmetrics[3]["values"].size
|
|
167
|
+
].flatten)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def test_cpu_without_thermal_throttle
|
|
171
|
+
omit "thermal throttle requires specific sysfs" if Dir.exist?("/sys/devices/system/cpu/cpu0/thermal_throttle")
|
|
172
|
+
|
|
173
|
+
params = create_minimum_config_params
|
|
174
|
+
params["cpu"] = true
|
|
175
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
176
|
+
d.run(expect_records: 1, timeout: 2)
|
|
177
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
178
|
+
assert_equal([
|
|
179
|
+
2,
|
|
180
|
+
{"ns"=>"node", "ss"=>"cpu", "name"=>"seconds_total", "desc"=>"Seconds the CPUs spent in each mode."},
|
|
181
|
+
Etc.nprocessors * ["idle", "iowait", "irq", "nice", "softirq", "steal", "system", "user"].size,
|
|
182
|
+
{"ns"=>"node", "ss"=>"cpu", "name"=>"guest_seconds_total", "desc"=>"Seconds the CPUs spent in guests (VMs) for each mode."},
|
|
183
|
+
Etc.nprocessors * ["nice", "user"].size,
|
|
184
|
+
],
|
|
185
|
+
[
|
|
186
|
+
cmetrics.size,
|
|
187
|
+
cmetrics.first["meta"]["opts"],
|
|
188
|
+
cmetrics.first["values"].size,
|
|
189
|
+
cmetrics.last["meta"]["opts"],
|
|
190
|
+
cmetrics.last["values"].size
|
|
191
|
+
])
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
sub_test_case "cpufreq collector" do
|
|
196
|
+
def test_cpufreq
|
|
197
|
+
omit "cpufreq collector requires linux capability" unless cpufreq_readable?
|
|
198
|
+
params = create_minimum_config_params
|
|
199
|
+
params["cpufreq"] = true
|
|
200
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
201
|
+
d.run(expect_records: 1, timeout: 2)
|
|
202
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
203
|
+
value_counts = if File.exist?("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq")
|
|
204
|
+
[Etc.nprocessors] * 6
|
|
205
|
+
else
|
|
206
|
+
[0, [Etc.nprocessors] * 5].flatten
|
|
207
|
+
end
|
|
208
|
+
assert_equal([
|
|
209
|
+
6,
|
|
210
|
+
{"desc"=>"Current cpu thread frequency in hertz.",
|
|
211
|
+
"name"=>"frequency_hertz",
|
|
212
|
+
"ns"=>"node",
|
|
213
|
+
"ss"=>"cpu"},
|
|
214
|
+
{"desc"=>"Maximum cpu thread frequency in hertz.",
|
|
215
|
+
"name"=>"frequency_max_hertz",
|
|
216
|
+
"ns"=>"node",
|
|
217
|
+
"ss"=>"cpu"},
|
|
218
|
+
{"desc"=>"Minimum cpu thread frequency in hertz.",
|
|
219
|
+
"name"=>"frequency_min_hertz",
|
|
220
|
+
"ns"=>"node",
|
|
221
|
+
"ss"=>"cpu"},
|
|
222
|
+
{"desc"=>"Current scaled CPU thread frequency in hertz.",
|
|
223
|
+
"name"=>"scaling_frequency_hertz",
|
|
224
|
+
"ns"=>"node",
|
|
225
|
+
"ss"=>"cpu"},
|
|
226
|
+
{"desc"=>"Maximum scaled CPU thread frequency in hertz.",
|
|
227
|
+
"name"=>"scaling_frequency_max_hertz",
|
|
228
|
+
"ns"=>"node",
|
|
229
|
+
"ss"=>"cpu"},
|
|
230
|
+
{"desc"=>"Minimum scaled CPU thread frequency in hertz.",
|
|
231
|
+
"name"=>"scaling_frequency_min_hertz",
|
|
232
|
+
"ns"=>"node",
|
|
233
|
+
"ss"=>"cpu"},
|
|
234
|
+
value_counts
|
|
235
|
+
].flatten,
|
|
236
|
+
[
|
|
237
|
+
cmetrics.size,
|
|
238
|
+
cmetrics.collect do |cmetric|
|
|
239
|
+
cmetric["meta"]["opts"]
|
|
240
|
+
end,
|
|
241
|
+
cmetrics.collect do |cmetric|
|
|
242
|
+
cmetric["values"].size
|
|
243
|
+
end,
|
|
244
|
+
].flatten)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def test_without_capability
|
|
248
|
+
omit "skip assertion if linux capability is enabled" if cpufreq_capability?
|
|
249
|
+
assert_raise(Fluent::ConfigError.new("Linux capability CAP_DAC_READ_SEARCH must be enabled")) do
|
|
250
|
+
params = create_minimum_config_params
|
|
251
|
+
params["cpufreq"] = true
|
|
252
|
+
create_driver(config_element("ROOT", "", params))
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
sub_test_case "diskstats collector" do
|
|
258
|
+
def test_diskstats
|
|
259
|
+
params = create_minimum_config_params
|
|
260
|
+
params["diskstats"] = true
|
|
261
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
262
|
+
d.run(expect_records: 1, timeout: 2)
|
|
263
|
+
c = Fluent::Plugin::NodeExporter::DiskstatsMetricsCollector.new
|
|
264
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
265
|
+
assert_equal([
|
|
266
|
+
true,
|
|
267
|
+
],
|
|
268
|
+
[
|
|
269
|
+
cmetrics.all? { |cmetric| cmetric["values"].size == c.target_devices.size }
|
|
270
|
+
])
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
sub_test_case "filefd collector" do
|
|
275
|
+
def test_filefd
|
|
276
|
+
params = create_minimum_config_params
|
|
277
|
+
params["filefd"] = true
|
|
278
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
279
|
+
d.run(expect_records: 1, timeout: 2)
|
|
280
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
281
|
+
assert_equal([
|
|
282
|
+
2,
|
|
283
|
+
{"ns"=>"node", "ss"=>"filefd", "name"=>"allocated", "desc"=>"File descriptor statistics: allocated."},
|
|
284
|
+
1,
|
|
285
|
+
{"ns"=>"node", "ss"=>"filefd", "name"=>"maximum", "desc"=>"File descriptor statistics: maximum."},
|
|
286
|
+
1
|
|
287
|
+
],
|
|
288
|
+
[
|
|
289
|
+
cmetrics.size,
|
|
290
|
+
cmetrics.first["meta"]["opts"],
|
|
291
|
+
cmetrics.first["values"].size,
|
|
292
|
+
cmetrics.last["meta"]["opts"],
|
|
293
|
+
cmetrics.last["values"].size
|
|
294
|
+
])
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
sub_test_case "loadavg collector" do
|
|
299
|
+
def test_loadavg
|
|
300
|
+
params = create_minimum_config_params
|
|
301
|
+
params["loadavg"] = true
|
|
302
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
303
|
+
d.run(expect_records: 1, timeout: 2)
|
|
304
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
305
|
+
assert_equal([
|
|
306
|
+
3,
|
|
307
|
+
{"ns"=>"node", "ss"=>"", "name"=>"load1", "desc"=>"1m load average."},
|
|
308
|
+
{"ns"=>"node", "ss"=>"", "name"=>"load5", "desc"=>"5m load average."},
|
|
309
|
+
{"ns"=>"node", "ss"=>"", "name"=>"load15", "desc"=>"15m load average."},
|
|
310
|
+
],
|
|
311
|
+
[
|
|
312
|
+
cmetrics.size,
|
|
313
|
+
cmetrics[0]["meta"]["opts"],
|
|
314
|
+
cmetrics[1]["meta"]["opts"],
|
|
315
|
+
cmetrics[2]["meta"]["opts"]
|
|
316
|
+
])
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
sub_test_case "meminfo collector" do
|
|
321
|
+
def meminfo_key_exist?(key)
|
|
322
|
+
File.readlines("/proc/meminfo").any? { |v| v.start_with?(key) }
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def test_meminfo
|
|
326
|
+
params = create_minimum_config_params
|
|
327
|
+
params["meminfo"] = true
|
|
328
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
329
|
+
d.run(expect_records: 1, timeout: 2)
|
|
330
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
331
|
+
fields = %w(
|
|
332
|
+
MemTotal_bytes
|
|
333
|
+
MemFree_bytes
|
|
334
|
+
MemAvailable_bytes
|
|
335
|
+
Buffers_bytes
|
|
336
|
+
Cached_bytes
|
|
337
|
+
SwapCached_bytes
|
|
338
|
+
Active_bytes
|
|
339
|
+
Inactive_bytes
|
|
340
|
+
Active_anon_bytes
|
|
341
|
+
Inactive_anon_bytes
|
|
342
|
+
Active_file_bytes
|
|
343
|
+
Inactive_file_bytes
|
|
344
|
+
Unevictable_bytes
|
|
345
|
+
Mlocked_bytes
|
|
346
|
+
SwapTotal_bytes
|
|
347
|
+
SwapFree_bytes
|
|
348
|
+
Dirty_bytes
|
|
349
|
+
Writeback_bytes
|
|
350
|
+
AnonPages_bytes
|
|
351
|
+
Mapped_bytes
|
|
352
|
+
Shmem_bytes
|
|
353
|
+
)
|
|
354
|
+
fields.concat(["KReclaimable_bytes"]) if meminfo_key_exist?("KReclaimable")
|
|
355
|
+
fields.concat(%w(
|
|
356
|
+
Slab_bytes
|
|
357
|
+
SReclaimable_bytes
|
|
358
|
+
SUnreclaim_bytes
|
|
359
|
+
KernelStack_bytes
|
|
360
|
+
PageTables_bytes
|
|
361
|
+
NFS_Unstable_bytes
|
|
362
|
+
Bounce_bytes
|
|
363
|
+
WritebackTmp_bytes
|
|
364
|
+
CommitLimit_bytes
|
|
365
|
+
Committed_AS_bytes
|
|
366
|
+
VmallocTotal_bytes
|
|
367
|
+
VmallocUsed_bytes
|
|
368
|
+
VmallocChunk_bytes
|
|
369
|
+
Percpu_bytes
|
|
370
|
+
HardwareCorrupted_bytes
|
|
371
|
+
AnonHugePages_bytes
|
|
372
|
+
))
|
|
373
|
+
fields.concat(["CmaTotal_bytes"]) if meminfo_key_exist?("CmaTotal")
|
|
374
|
+
fields.concat(["CmaFree_bytes"]) if meminfo_key_exist?("CmaFree")
|
|
375
|
+
fields.concat(["ShmemHugePages_bytes"]) if meminfo_key_exist?("ShmemHugePages")
|
|
376
|
+
fields.concat(["ShmemPmdMapped_bytes"]) if meminfo_key_exist?("ShmemPmdMapped")
|
|
377
|
+
fields.concat(["FileHugePages_bytes"]) if meminfo_key_exist?("FileHugePages")
|
|
378
|
+
fields.concat(["FilePmdMapped_bytes"]) if meminfo_key_exist?("FilePmdMapped")
|
|
379
|
+
fields.concat(%w(
|
|
380
|
+
HugePages_Total
|
|
381
|
+
HugePages_Free
|
|
382
|
+
HugePages_Rsvd
|
|
383
|
+
HugePages_Surp
|
|
384
|
+
Hugepagesize_bytes
|
|
385
|
+
))
|
|
386
|
+
fields.concat(["Hugetlb_bytes"]) if meminfo_key_exist?("Hugetlb")
|
|
387
|
+
fields.concat(%w(
|
|
388
|
+
DirectMap4k_bytes
|
|
389
|
+
DirectMap2M_bytes
|
|
390
|
+
DirectMap1G_bytes
|
|
391
|
+
))
|
|
392
|
+
opts = []
|
|
393
|
+
fields.each do |field|
|
|
394
|
+
opts << {"ns"=>"node", "ss"=>"memory", "name"=>field, "desc"=>"#{field}."}
|
|
395
|
+
end
|
|
396
|
+
assert_equal([
|
|
397
|
+
fields.size,
|
|
398
|
+
opts
|
|
399
|
+
].flatten,
|
|
400
|
+
[
|
|
401
|
+
cmetrics.size,
|
|
402
|
+
cmetrics.collect do |metric| metric["meta"]["opts"] end
|
|
403
|
+
].flatten)
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
sub_test_case "netdev collector" do
|
|
408
|
+
def test_netdev
|
|
409
|
+
params = create_minimum_config_params
|
|
410
|
+
params["netdev"] = true
|
|
411
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
412
|
+
d.run(expect_records: 1, timeout: 2)
|
|
413
|
+
c = Fluent::Plugin::NodeExporter::NetdevMetricsCollector.new
|
|
414
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
415
|
+
opts = []
|
|
416
|
+
Fluent::Plugin::NodeExporter::NetdevMetricsCollector::RECEIVE_FIELDS.each do |field|
|
|
417
|
+
opts << {"ns"=>"node", "ss"=>"network",
|
|
418
|
+
"name"=>"receive_#{field}_total", "desc"=>"Network device statistic receive_#{field}_total."}
|
|
419
|
+
end
|
|
420
|
+
Fluent::Plugin::NodeExporter::NetdevMetricsCollector::TRANSMIT_FIELDS.each do |field|
|
|
421
|
+
opts << {"ns"=>"node", "ss"=>"network",
|
|
422
|
+
"name"=>"transmit_#{field}_total", "desc"=>"Network device statistic transmit_#{field}_total."}
|
|
423
|
+
end
|
|
424
|
+
assert_equal([
|
|
425
|
+
16, # receive 8 + transmit 8 entries
|
|
426
|
+
opts,
|
|
427
|
+
[c.target_devices.size] * 16
|
|
428
|
+
].flatten,
|
|
429
|
+
[
|
|
430
|
+
cmetrics.size,
|
|
431
|
+
cmetrics.collect do |cmetric|
|
|
432
|
+
cmetric["meta"]["opts"]
|
|
433
|
+
end,
|
|
434
|
+
cmetrics.collect do |cmetric|
|
|
435
|
+
cmetric["values"].size
|
|
436
|
+
end
|
|
437
|
+
].flatten)
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
sub_test_case "stat collector" do
|
|
442
|
+
def test_stat
|
|
443
|
+
params = create_minimum_config_params
|
|
444
|
+
params["stat"] = true
|
|
445
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
446
|
+
d.run(expect_records: 1, timeout: 2)
|
|
447
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
448
|
+
assert_equal([
|
|
449
|
+
6,
|
|
450
|
+
{"desc"=>"Total number of interrupts serviced.",
|
|
451
|
+
"name"=>"intr_total",
|
|
452
|
+
"ns"=>"node",
|
|
453
|
+
"ss"=>""},
|
|
454
|
+
{"desc"=>"Total number of context switches.",
|
|
455
|
+
"name"=>"context_switches_total",
|
|
456
|
+
"ns"=>"node",
|
|
457
|
+
"ss"=>""},
|
|
458
|
+
{"desc"=>"Total number of forks.",
|
|
459
|
+
"name"=>"forks_total",
|
|
460
|
+
"ns"=>"node",
|
|
461
|
+
"ss"=>""},
|
|
462
|
+
{"desc"=>"Node boot time, in unixtime.",
|
|
463
|
+
"name"=>"boot_time_seconds",
|
|
464
|
+
"ns"=>"node",
|
|
465
|
+
"ss"=>""},
|
|
466
|
+
{"desc"=>"Number of processes in runnable state.",
|
|
467
|
+
"name"=>"procs_running",
|
|
468
|
+
"ns"=>"node",
|
|
469
|
+
"ss"=>""},
|
|
470
|
+
{"desc"=>"Number of processes blocked waiting for I/O to complete.",
|
|
471
|
+
"name"=>"procs_blocked",
|
|
472
|
+
"ns"=>"node",
|
|
473
|
+
"ss"=>""},
|
|
474
|
+
],
|
|
475
|
+
[
|
|
476
|
+
cmetrics.size,
|
|
477
|
+
cmetrics.collect do |cmetric|
|
|
478
|
+
cmetric["meta"]["opts"]
|
|
479
|
+
end,
|
|
480
|
+
].flatten)
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
sub_test_case "time collector" do
|
|
485
|
+
def test_time
|
|
486
|
+
params = create_minimum_config_params
|
|
487
|
+
params["time"] = true
|
|
488
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
489
|
+
d.run(expect_records: 1, timeout: 2)
|
|
490
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
491
|
+
assert_equal([
|
|
492
|
+
1,
|
|
493
|
+
{"desc"=>"System time in seconds since epoch (1970).",
|
|
494
|
+
"name"=>"time_seconds",
|
|
495
|
+
"ns"=>"node",
|
|
496
|
+
"ss"=>""}
|
|
497
|
+
],
|
|
498
|
+
[
|
|
499
|
+
cmetrics.size,
|
|
500
|
+
cmetrics.collect do |cmetric|
|
|
501
|
+
cmetric["meta"]["opts"]
|
|
502
|
+
end,
|
|
503
|
+
].flatten)
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
sub_test_case "uname collector" do
|
|
508
|
+
def test_uname
|
|
509
|
+
params = create_minimum_config_params
|
|
510
|
+
params["uname"] = true
|
|
511
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
512
|
+
d.run(expect_records: 1, timeout: 2)
|
|
513
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
514
|
+
assert_equal([
|
|
515
|
+
1,
|
|
516
|
+
{"desc"=>"Labeled system information as provided by the uname system call.",
|
|
517
|
+
"name"=>"info",
|
|
518
|
+
"ns"=>"node",
|
|
519
|
+
"ss"=>"uname"}
|
|
520
|
+
],
|
|
521
|
+
[
|
|
522
|
+
cmetrics.size,
|
|
523
|
+
cmetrics.collect do |cmetric|
|
|
524
|
+
cmetric["meta"]["opts"]
|
|
525
|
+
end,
|
|
526
|
+
].flatten)
|
|
527
|
+
end
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
sub_test_case "vmstat collector" do
|
|
531
|
+
def test_vmstat
|
|
532
|
+
params = create_minimum_config_params
|
|
533
|
+
params["vmstat"] = true
|
|
534
|
+
d = create_driver(config_element("ROOT", "", params))
|
|
535
|
+
d.run(expect_records: 1, timeout: 2)
|
|
536
|
+
cmetrics = MessagePack.unpack(d.events.first.last["cmetrics"])
|
|
537
|
+
expected = [
|
|
538
|
+
{"desc"=>"/proc/vmstat information field pgpgin.",
|
|
539
|
+
"name"=>"pgpgin",
|
|
540
|
+
"ns"=>"node",
|
|
541
|
+
"ss"=>"vmstat"},
|
|
542
|
+
{"desc"=>"/proc/vmstat information field pgpgout.",
|
|
543
|
+
"name"=>"pgpgout",
|
|
544
|
+
"ns"=>"node",
|
|
545
|
+
"ss"=>"vmstat"},
|
|
546
|
+
{"desc"=>"/proc/vmstat information field pswpin.",
|
|
547
|
+
"name"=>"pswpin",
|
|
548
|
+
"ns"=>"node",
|
|
549
|
+
"ss"=>"vmstat"},
|
|
550
|
+
{"desc"=>"/proc/vmstat information field pswpout.",
|
|
551
|
+
"name"=>"pswpout",
|
|
552
|
+
"ns"=>"node",
|
|
553
|
+
"ss"=>"vmstat"},
|
|
554
|
+
{"desc"=>"/proc/vmstat information field pgfault.",
|
|
555
|
+
"name"=>"pgfault",
|
|
556
|
+
"ns"=>"node",
|
|
557
|
+
"ss"=>"vmstat"},
|
|
558
|
+
{"desc"=>"/proc/vmstat information field pgmajfault.",
|
|
559
|
+
"name"=>"pgmajfault",
|
|
560
|
+
"ns"=>"node",
|
|
561
|
+
"ss"=>"vmstat"}
|
|
562
|
+
]
|
|
563
|
+
if Gem::Version.new(Etc.uname[:release].split("-", 2).first) >= Gem::Version.new("4.13.0")
|
|
564
|
+
# oom_kill counter since kernel 4.13+
|
|
565
|
+
expected << {"desc"=>"/proc/vmstat information field oom_kill.",
|
|
566
|
+
"name"=>"oom_kill",
|
|
567
|
+
"ns"=>"node",
|
|
568
|
+
"ss"=>"vmstat"}
|
|
569
|
+
end
|
|
570
|
+
assert_equal([
|
|
571
|
+
expected.size,
|
|
572
|
+
expected
|
|
573
|
+
].flatten,
|
|
574
|
+
[
|
|
575
|
+
cmetrics.size,
|
|
576
|
+
cmetrics.collect do |cmetric|
|
|
577
|
+
cmetric["meta"]["opts"]
|
|
578
|
+
end,
|
|
579
|
+
].flatten)
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require "helper"
|
|
2
|
+
require "fluent/plugin/in_node_exporter_metrics"
|
|
3
|
+
require "fluent/plugin/node_exporter/loadavg_collector"
|
|
4
|
+
|
|
5
|
+
class LoadavgColectorTest < Test::Unit::TestCase
|
|
6
|
+
sub_test_case "loadavg" do
|
|
7
|
+
|
|
8
|
+
def parse(input)
|
|
9
|
+
stub(File).read { input }
|
|
10
|
+
collector = Fluent::Plugin::NodeExporter::LoadavgMetricsCollector.new
|
|
11
|
+
collector.run
|
|
12
|
+
yield collector
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_invalid_fields
|
|
16
|
+
proc_loadavg = <<EOS
|
|
17
|
+
0.32 0.30 0.31 2/1880 70024 0
|
|
18
|
+
EOS
|
|
19
|
+
parse(proc_loadavg) do |collector|
|
|
20
|
+
loadavg1 = collector.cmetrics[:loadavg1]
|
|
21
|
+
loadavg5 = collector.cmetrics[:loadavg5]
|
|
22
|
+
loadavg15 = collector.cmetrics[:loadavg15]
|
|
23
|
+
assert_equal([0.0, 0.0, 0.0],
|
|
24
|
+
[loadavg1.val, loadavg5.val, loadavg15.val])
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_valid_fields
|
|
29
|
+
proc_loadavg = <<EOS
|
|
30
|
+
0.10 0.20 0.30 2/1880 70024
|
|
31
|
+
EOS
|
|
32
|
+
parse(proc_loadavg) do |collector|
|
|
33
|
+
loadavg1 = collector.cmetrics[:loadavg1]
|
|
34
|
+
loadavg5 = collector.cmetrics[:loadavg5]
|
|
35
|
+
loadavg15 = collector.cmetrics[:loadavg15]
|
|
36
|
+
assert_equal([0.10, 0.20, 0.30],
|
|
37
|
+
[loadavg1.val, loadavg5.val, loadavg15.val])
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require "helper"
|
|
2
|
+
require "fluent/plugin/in_node_exporter_metrics"
|
|
3
|
+
require "fluent/plugin/node_exporter/meminfo_collector"
|
|
4
|
+
|
|
5
|
+
class MeminfoColectorTest < Test::Unit::TestCase
|
|
6
|
+
sub_test_case "metric name" do
|
|
7
|
+
|
|
8
|
+
def parse(input)
|
|
9
|
+
stub(File).readlines { input.split("\n") }
|
|
10
|
+
collector = Fluent::Plugin::NodeExporter::MeminfoMetricsCollector.new
|
|
11
|
+
collector.run
|
|
12
|
+
yield collector
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_anon_file
|
|
16
|
+
proc_meminfo = <<EOS
|
|
17
|
+
Active(anon): 100 kB
|
|
18
|
+
Inactive(anon): 200 kB
|
|
19
|
+
Active(file): 300 kB
|
|
20
|
+
Inactive(file): 400 kB
|
|
21
|
+
EOS
|
|
22
|
+
parse(proc_meminfo) do |collector|
|
|
23
|
+
assert_equal([102400.0, 204800.0, 307200.0, 409600.0],
|
|
24
|
+
[collector.cmetrics[:node_memory_Active_anon_bytes].val,
|
|
25
|
+
collector.cmetrics[:node_memory_Inactive_anon_bytes].val,
|
|
26
|
+
collector.cmetrics[:node_memory_Active_file_bytes].val,
|
|
27
|
+
collector.cmetrics[:node_memory_Inactive_file_bytes].val])
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_non_kb
|
|
32
|
+
proc_meminfo = <<EOS
|
|
33
|
+
HugePages_Total: 100
|
|
34
|
+
HugePages_Free: 200
|
|
35
|
+
HugePages_Rsvd: 300
|
|
36
|
+
HugePages_Surp: 400
|
|
37
|
+
EOS
|
|
38
|
+
parse(proc_meminfo) do |collector|
|
|
39
|
+
assert_equal([100, 200, 300, 400],
|
|
40
|
+
[collector.cmetrics[:node_memory_HugePages_Total].val,
|
|
41
|
+
collector.cmetrics[:node_memory_HugePages_Free].val,
|
|
42
|
+
collector.cmetrics[:node_memory_HugePages_Rsvd].val,
|
|
43
|
+
collector.cmetrics[:node_memory_HugePages_Surp].val])
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|