fluent-plugin-node-exporter-metrics 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,280 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 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 "fluent/plugin/input"
|
18
|
+
require "fluent/plugin/node_exporter/collector"
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module Plugin
|
22
|
+
module NodeExporter
|
23
|
+
class DiskstatsMetricsCollector < MetricsCollector
|
24
|
+
|
25
|
+
IGNORED_DEVICES = /^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\d+n\d+p)\d+$/
|
26
|
+
# https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
|
27
|
+
# major number ... time spent flushing
|
28
|
+
DISKSTATS_KNOWN_FIELDS = 20
|
29
|
+
# assume sector size = 512
|
30
|
+
SECTOR_SIZE = 512
|
31
|
+
|
32
|
+
METRIC_NAMES = %w(
|
33
|
+
reads_completed_total
|
34
|
+
reads_merged_total
|
35
|
+
read_bytes_total
|
36
|
+
read_time_seconds_total
|
37
|
+
writes_completed_total
|
38
|
+
writes_merged_total
|
39
|
+
written_bytes_total
|
40
|
+
write_time_seconds_total
|
41
|
+
io_now
|
42
|
+
io_time_seconds_total
|
43
|
+
io_time_weighted_seconds_total
|
44
|
+
discards_completed_total
|
45
|
+
discards_merged_total
|
46
|
+
discarded_sectors_total
|
47
|
+
discard_time_seconds_total
|
48
|
+
flush_requests_total
|
49
|
+
flush_requests_time_seconds_total
|
50
|
+
)
|
51
|
+
|
52
|
+
DISCARD_METRIC_NAMES = %w(
|
53
|
+
discards_completed_total
|
54
|
+
discards_merged_total
|
55
|
+
discarded_sectors_total
|
56
|
+
discard_time_seconds_total
|
57
|
+
)
|
58
|
+
|
59
|
+
FLUSH_METRIC_NAMES = %w(
|
60
|
+
flush_requests_total
|
61
|
+
flush_requests_time_seconds_total
|
62
|
+
)
|
63
|
+
|
64
|
+
def initialize(config={})
|
65
|
+
super(config)
|
66
|
+
|
67
|
+
@reads_completed_total = CMetrics::Counter.new
|
68
|
+
@reads_completed_total.create("node", "disk", "reads_completed_total",
|
69
|
+
"The total number of reads completed successfully.",
|
70
|
+
["device"])
|
71
|
+
|
72
|
+
@reads_merged_total = CMetrics::Counter.new
|
73
|
+
@reads_merged_total.create("node", "disk", "reads_merged_total",
|
74
|
+
"The total number of reads merged.",
|
75
|
+
["device"])
|
76
|
+
|
77
|
+
@read_bytes_total = CMetrics::Counter.new
|
78
|
+
@read_bytes_total.create("node", "disk", "read_bytes_total",
|
79
|
+
"The total number of bytes read successfully.",
|
80
|
+
["device"])
|
81
|
+
|
82
|
+
@read_time_seconds_total = CMetrics::Counter.new
|
83
|
+
@read_time_seconds_total.create("node", "disk", "reads_time_seconds_total",
|
84
|
+
"The total number of seconds spent by all reads.",
|
85
|
+
["device"])
|
86
|
+
|
87
|
+
@writes_completed_total = CMetrics::Counter.new
|
88
|
+
@writes_completed_total.create("node", "disk", "writes_completed_total",
|
89
|
+
"The total number of writes completed successfully.",
|
90
|
+
["device"])
|
91
|
+
|
92
|
+
@writes_merged_total = CMetrics::Counter.new
|
93
|
+
@writes_merged_total.create("node", "disk", "writes_merged_total",
|
94
|
+
"The number of writes merged.",
|
95
|
+
["device"])
|
96
|
+
|
97
|
+
@written_bytes_total = CMetrics::Counter.new
|
98
|
+
@written_bytes_total.create("node", "disk", "written_bytes_total",
|
99
|
+
"The total number of bytes written successfully.",
|
100
|
+
["device"])
|
101
|
+
|
102
|
+
@write_time_seconds_total = CMetrics::Counter.new
|
103
|
+
@write_time_seconds_total.create("node", "disk", "write_time_seconds_total",
|
104
|
+
"This is the total number of seconds spent by all writes.",
|
105
|
+
["device"])
|
106
|
+
|
107
|
+
@io_now = CMetrics::Gauge.new
|
108
|
+
@io_now.create("node", "disk", "io_now",
|
109
|
+
"The number of I/Os currently in progress.",
|
110
|
+
["device"])
|
111
|
+
|
112
|
+
@io_time_seconds_total = CMetrics::Counter.new
|
113
|
+
@io_time_seconds_total.create("node", "disk", "io_time_seconds_total",
|
114
|
+
"Total seconds spent doing I/Os.",
|
115
|
+
["device"])
|
116
|
+
|
117
|
+
@io_time_weighted_seconds_total = CMetrics::Counter.new
|
118
|
+
@io_time_weighted_seconds_total.create("node", "disk", "io_time_weighted_seconds_total",
|
119
|
+
"The number of I/Os currently in progress.",
|
120
|
+
["device"])
|
121
|
+
|
122
|
+
if kernel_version_over4_18?
|
123
|
+
# Kernel >= 4.18
|
124
|
+
@discards_completed_total = CMetrics::Counter.new
|
125
|
+
@discards_completed_total.create("node", "disk", "discards_completed_total",
|
126
|
+
"The total number of discards completed successfully.",
|
127
|
+
["device"])
|
128
|
+
|
129
|
+
@discards_merged_total = CMetrics::Counter.new
|
130
|
+
@discards_merged_total.create("node", "disk", "discards_merged_total",
|
131
|
+
"The total number of discards merged.", ["device"])
|
132
|
+
|
133
|
+
@discarded_sectors_total = CMetrics::Counter.new
|
134
|
+
@discarded_sectors_total.create("node", "disk", "discards_sectors_total",
|
135
|
+
"The total number of sectors discarded successfully.",
|
136
|
+
["device"])
|
137
|
+
|
138
|
+
@discard_time_seconds_total = CMetrics::Counter.new
|
139
|
+
@discard_time_seconds_total.create("node", "disk", "discard_time_seconds_total",
|
140
|
+
"The total number of seconds spent by all discards.",
|
141
|
+
["device"])
|
142
|
+
end
|
143
|
+
|
144
|
+
if kernel_version_over5_5?
|
145
|
+
@flush_requests_total = CMetrics::Counter.new
|
146
|
+
@flush_requests_total.create("node", "disk", "flush_requests_total",
|
147
|
+
"The total number of flush requests completed successfully",
|
148
|
+
["device"])
|
149
|
+
|
150
|
+
@flush_requests_time_seconds_total = CMetrics::Counter.new
|
151
|
+
@flush_requests_time_seconds_total.create("node", "disk", "flush_requests_time_seconds_total",
|
152
|
+
"This is the total number of seconds spent by all flush requests.",
|
153
|
+
["device"])
|
154
|
+
end
|
155
|
+
|
156
|
+
@metrics = {}
|
157
|
+
end
|
158
|
+
|
159
|
+
def kernel_version_over4_18?
|
160
|
+
Gem::Version.new(Etc.uname[:release].split('-', 2).first) >= Gem::Version.new("4.18")
|
161
|
+
end
|
162
|
+
|
163
|
+
def kernel_version_over5_5?
|
164
|
+
Gem::Version.new(Etc.uname[:release].split('-', 2).first) >= Gem::Version.new("5.5.0")
|
165
|
+
end
|
166
|
+
|
167
|
+
def target_devices
|
168
|
+
devices = []
|
169
|
+
diskstats_path = File.join(@procfs_path, "diskstats")
|
170
|
+
File.readlines(diskstats_path).each do |line|
|
171
|
+
_, _, device, _ = line.split(' ', DISKSTATS_KNOWN_FIELDS)
|
172
|
+
unless IGNORED_DEVICES.match?(device)
|
173
|
+
devices << device
|
174
|
+
end
|
175
|
+
end
|
176
|
+
devices
|
177
|
+
end
|
178
|
+
|
179
|
+
def run
|
180
|
+
diskstats_update
|
181
|
+
end
|
182
|
+
|
183
|
+
def diskstats_update
|
184
|
+
diskstats_path = File.join(@procfs_path, "diskstats")
|
185
|
+
File.readlines(diskstats_path).each do |line|
|
186
|
+
_, _, device,
|
187
|
+
reads_completed_value, reads_merged_value, read_bytes_value, read_time_seconds_value,
|
188
|
+
writes_completed_value, writes_merged_value, written_bytes_value, write_time_seconds_value,
|
189
|
+
io_now_value, io_time_seconds_value, io_time_weighted_seconds_value,
|
190
|
+
discards_completed_value, discards_merged_value, discarded_sectors_value, discard_time_seconds_value,
|
191
|
+
flush_requests_value, flush_requests_time_seconds_value = line.split(' ', DISKSTATS_KNOWN_FIELDS)
|
192
|
+
unless IGNORED_DEVICES.match?(device)
|
193
|
+
METRIC_NAMES.each do |field|
|
194
|
+
case field
|
195
|
+
when "reads_completed_total"
|
196
|
+
@reads_completed_total.set(reads_completed_value.to_f, [device])
|
197
|
+
when "reads_merged_total"
|
198
|
+
@reads_merged_total.set(reads_merged_value.to_f, [device])
|
199
|
+
when "read_bytes_total"
|
200
|
+
@read_bytes_total.set(read_bytes_value.to_f * SECTOR_SIZE, [device])
|
201
|
+
when "read_time_seconds_total"
|
202
|
+
@read_time_seconds_total.set(read_time_seconds_value.to_f * 0.001, [device])
|
203
|
+
when "writes_completed_total"
|
204
|
+
@writes_completed_total.set(writes_completed_value.to_f, [device])
|
205
|
+
when "writes_merged_total"
|
206
|
+
@writes_merged_total.set(writes_merged_value.to_f, [device])
|
207
|
+
when "written_bytes_total"
|
208
|
+
@written_bytes_total.set(written_bytes_value.to_f * SECTOR_SIZE, [device])
|
209
|
+
when "write_time_seconds_total"
|
210
|
+
@write_time_seconds_total.set(write_time_seconds_value.to_f * 0.001, [device])
|
211
|
+
when "io_now"
|
212
|
+
@io_now.set(io_now_value.to_f, [device])
|
213
|
+
when "io_time_seconds_total"
|
214
|
+
@io_time_seconds_total.set(io_time_seconds_value.to_f * 0.001, [device])
|
215
|
+
when "io_time_weighted_seconds_total"
|
216
|
+
@io_time_weighted_seconds_total.set(io_time_weighted_seconds_value.to_f * 0.001, [device])
|
217
|
+
when "discards_completed_total"
|
218
|
+
if kernel_version_over4_18?
|
219
|
+
@discards_completed_total.set(discards_completed_value.to_f, [device])
|
220
|
+
end
|
221
|
+
when "discards_merged_total"
|
222
|
+
if kernel_version_over4_18?
|
223
|
+
@discards_merged_total.set(discards_merged_value.to_f, [device])
|
224
|
+
end
|
225
|
+
when "discarded_sectors_total"
|
226
|
+
if kernel_version_over4_18?
|
227
|
+
@discarded_sectors_total.set(discarded_sectors_value.to_f, [device])
|
228
|
+
end
|
229
|
+
when "discard_time_seconds_total"
|
230
|
+
if kernel_version_over4_18?
|
231
|
+
@discard_time_seconds_total.set(discard_time_seconds_value.to_f * 0.001, [device])
|
232
|
+
end
|
233
|
+
when "flush_requests_total"
|
234
|
+
if kernel_version_over5_5?
|
235
|
+
@flush_requests_total.set(flush_requests_value.to_f, [device])
|
236
|
+
end
|
237
|
+
when "flush_requests_time_seconds_total"
|
238
|
+
if kernel_version_over5_5?
|
239
|
+
@flush_requests_time_seconds_total.set(flush_requests_time_seconds_value.to_f * 0.001, [device])
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
@metrics = {
|
244
|
+
reads_completed_total: @reads_completed_total,
|
245
|
+
reads_merged_total: @reads_merged_total,
|
246
|
+
read_bytes_total: @read_bytes_total,
|
247
|
+
read_time_seconds_total: @read_time_seconds_total,
|
248
|
+
writes_completed_total: @writes_completed_total,
|
249
|
+
writes_merged_total: @writes_merged_total,
|
250
|
+
written_bytes_total: @written_bytes_total,
|
251
|
+
write_time_seconds_total: @write_time_seconds_total,
|
252
|
+
io_now: @io_now,
|
253
|
+
io_time_seconds_total: @io_time_seconds_total,
|
254
|
+
io_time_weighted_seconds_total: @io_time_weighted_seconds_total
|
255
|
+
}
|
256
|
+
if kernel_version_over4_18?
|
257
|
+
@metrics.merge!({
|
258
|
+
discards_completed_total: @discards_completed_total,
|
259
|
+
discards_merged_total: @discards_merged_total,
|
260
|
+
discarded_sectors_total: @discarded_sectors_total,
|
261
|
+
discard_time_seconds_total: @discard_time_seconds_total
|
262
|
+
})
|
263
|
+
end
|
264
|
+
if kernel_version_over5_5?
|
265
|
+
@metrics.merge!({
|
266
|
+
flush_requests_total: @flush_requests_total,
|
267
|
+
flush_requests_time_seconds_total: @flush_requests_time_seconds_total
|
268
|
+
})
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def cmetrics
|
275
|
+
@metrics
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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 "fluent/plugin/input"
|
18
|
+
require "fluent/plugin/node_exporter/collector"
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module Plugin
|
22
|
+
module NodeExporter
|
23
|
+
class FilefdMetricsCollector < MetricsCollector
|
24
|
+
def initialize(config={})
|
25
|
+
super(config)
|
26
|
+
|
27
|
+
@allocated = CMetrics::Gauge.new
|
28
|
+
@allocated.create("node", "filefd", "allocated", "File descriptor statistics: allocated.")
|
29
|
+
|
30
|
+
@maximum = CMetrics::Gauge.new
|
31
|
+
@maximum.create("node", "filefd", "maximum", "File descriptor statistics: maximum.")
|
32
|
+
end
|
33
|
+
|
34
|
+
def run
|
35
|
+
filefd_update
|
36
|
+
end
|
37
|
+
|
38
|
+
def filefd_update
|
39
|
+
# Etc.uname returns at least sysname,release,version,machine,nodename
|
40
|
+
# but it is not guaranteed to return domainname.
|
41
|
+
file_nr_path = File.join(@procfs_path, "/sys/fs/file-nr")
|
42
|
+
entry = File.read(file_nr_path).split
|
43
|
+
unless entry.size == 3
|
44
|
+
$log.warn("invalid number of field <#{file_nr_path}>: #{entry.size}")
|
45
|
+
return
|
46
|
+
end
|
47
|
+
@allocated.set(entry.first.to_f)
|
48
|
+
@maximum.set(entry.last.to_f)
|
49
|
+
end
|
50
|
+
|
51
|
+
def cmetrics
|
52
|
+
{
|
53
|
+
filefd_allocated: @allocated,
|
54
|
+
filefd_maximum: @maximum
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,64 @@
|
|
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 "fluent/plugin/input"
|
18
|
+
require "fluent/plugin/node_exporter/collector"
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module Plugin
|
22
|
+
module NodeExporter
|
23
|
+
class LoadavgMetricsCollector < MetricsCollector
|
24
|
+
def initialize(config={})
|
25
|
+
super(config)
|
26
|
+
|
27
|
+
@load1 = CMetrics::Gauge.new
|
28
|
+
@load1.create("node", "", "load1", "1m load average.")
|
29
|
+
|
30
|
+
@load5 = CMetrics::Gauge.new
|
31
|
+
@load5.create("node", "", "load5", "5m load average.")
|
32
|
+
|
33
|
+
@load15 = CMetrics::Gauge.new
|
34
|
+
@load15.create("node", "", "load15", "15m load average.")
|
35
|
+
end
|
36
|
+
|
37
|
+
def run
|
38
|
+
loadavg_update
|
39
|
+
end
|
40
|
+
|
41
|
+
def loadavg_update
|
42
|
+
loadavg_path = File.join(@procfs_path, "/loadavg")
|
43
|
+
# Use 1 explicitly for default gauge value
|
44
|
+
fields = File.read(loadavg_path).split
|
45
|
+
unless fields.size == 5
|
46
|
+
$log.warn("invalid number of fields <#{loadavg_path}>: <#{fields.size}>")
|
47
|
+
return
|
48
|
+
end
|
49
|
+
@load1.set(fields[0].to_f)
|
50
|
+
@load5.set(fields[1].to_f)
|
51
|
+
@load15.set(fields[2].to_f)
|
52
|
+
end
|
53
|
+
|
54
|
+
def cmetrics
|
55
|
+
{
|
56
|
+
loadavg1: @load1,
|
57
|
+
loadavg5: @load5,
|
58
|
+
loadavg15: @load15
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,61 @@
|
|
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 "fluent/plugin/input"
|
18
|
+
require "fluent/plugin/node_exporter/collector"
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module Plugin
|
22
|
+
module NodeExporter
|
23
|
+
class MeminfoMetricsCollector < MetricsCollector
|
24
|
+
|
25
|
+
def initialize(config={})
|
26
|
+
super(config)
|
27
|
+
|
28
|
+
@metrics = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def run
|
32
|
+
meminfo_update
|
33
|
+
end
|
34
|
+
|
35
|
+
def meminfo_update
|
36
|
+
meminfo_path = File.join(@procfs_path, "meminfo")
|
37
|
+
File.readlines(meminfo_path).each do |line|
|
38
|
+
name, value, unit = line.split
|
39
|
+
name.delete!(":")
|
40
|
+
if name.end_with?("(anon)") or name.end_with?("(file)")
|
41
|
+
name.sub!(/\((anon)\)|\((file)\)/, "_\\1\\2")
|
42
|
+
end
|
43
|
+
if unit
|
44
|
+
name << "_bytes"
|
45
|
+
value = value.to_f * 1024
|
46
|
+
end
|
47
|
+
metric_name = "node_memory_#{name}"
|
48
|
+
@gauge = CMetrics::Gauge.new
|
49
|
+
@gauge.create("node", "memory", name, "#{name}.")
|
50
|
+
@gauge.set(value.to_f)
|
51
|
+
@metrics[metric_name.intern] = @gauge
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def cmetrics
|
56
|
+
@metrics
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,92 @@
|
|
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 "fluent/plugin/input"
|
18
|
+
require "fluent/plugin/node_exporter/collector"
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module Plugin
|
22
|
+
module NodeExporter
|
23
|
+
class NetdevMetricsCollector < MetricsCollector
|
24
|
+
|
25
|
+
def initialize(config={})
|
26
|
+
super(config)
|
27
|
+
|
28
|
+
@metrics = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def run
|
32
|
+
netdev_update
|
33
|
+
end
|
34
|
+
|
35
|
+
RECEIVE_FIELDS = %w(bytes packets errs drop fifo frame compressed multicast)
|
36
|
+
TRANSMIT_FIELDS = %w(bytes packets errs drop fifo colls carrier compressed)
|
37
|
+
|
38
|
+
def target_devices
|
39
|
+
devices = []
|
40
|
+
netdev_path = File.join(@procfs_path, "net/dev")
|
41
|
+
File.readlines(netdev_path).each_with_index do |line, index|
|
42
|
+
next if index < 2
|
43
|
+
interface, _ = line.split
|
44
|
+
interface.delete!(":")
|
45
|
+
devices << interface
|
46
|
+
end
|
47
|
+
devices
|
48
|
+
end
|
49
|
+
|
50
|
+
def netdev_update
|
51
|
+
netdev_path = File.join(@procfs_path, "net/dev")
|
52
|
+
RECEIVE_FIELDS.each_with_index do |field, index|
|
53
|
+
metric_name = "receive_#{field}_total"
|
54
|
+
@counter = CMetrics::Counter.new
|
55
|
+
@counter.create("node", "network", metric_name, "Network device statistic #{metric_name}.", ["device"])
|
56
|
+
@metrics[metric_name.intern] = @counter
|
57
|
+
end
|
58
|
+
TRANSMIT_FIELDS.each_with_index do |field, index|
|
59
|
+
metric_name = "transmit_#{field}_total"
|
60
|
+
@counter = CMetrics::Counter.new
|
61
|
+
@counter.create("node", "network", metric_name, "Network device statistic #{metric_name}.", ["device"])
|
62
|
+
@metrics[metric_name.intern] = @counter
|
63
|
+
end
|
64
|
+
File.readlines(netdev_path).each_with_index do |line, index|
|
65
|
+
# net/dev must be 3 columns
|
66
|
+
if index == 0 and line.split("|").size != 3
|
67
|
+
break
|
68
|
+
end
|
69
|
+
# first 2 line are header (Inter-face/Receive/Transmit)
|
70
|
+
next if index < 2
|
71
|
+
|
72
|
+
interface, *values = line.split
|
73
|
+
interface.delete!(":")
|
74
|
+
|
75
|
+
RECEIVE_FIELDS.each_with_index do |field, index|
|
76
|
+
metric_name = "receive_#{field}_total"
|
77
|
+
@metrics[metric_name.intern].set(values[index].to_f, [interface])
|
78
|
+
end
|
79
|
+
TRANSMIT_FIELDS.each_with_index do |field, index|
|
80
|
+
metric_name = "transmit_#{field}_total"
|
81
|
+
@metrics[metric_name.intern].set(values[index + RECEIVE_FIELDS.size].to_f, [interface])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def cmetrics
|
87
|
+
@metrics
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,84 @@
|
|
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 "fluent/plugin/input"
|
18
|
+
require "fluent/plugin/node_exporter/collector"
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module Plugin
|
22
|
+
module NodeExporter
|
23
|
+
class StatMetricsCollector < MetricsCollector
|
24
|
+
def initialize(config={})
|
25
|
+
super(config)
|
26
|
+
|
27
|
+
@intr_total = CMetrics::Counter.new
|
28
|
+
@intr_total.create("node", "", "intr_total", "Total number of interrupts serviced.")
|
29
|
+
|
30
|
+
@context_switches_total = CMetrics::Counter.new
|
31
|
+
@context_switches_total.create("node", "", "context_switches_total", "Total number of context switches.")
|
32
|
+
|
33
|
+
@forks_total = CMetrics::Counter.new
|
34
|
+
@forks_total.create("node", "", "forks_total", "Total number of forks.")
|
35
|
+
|
36
|
+
@boot_time_seconds = CMetrics::Gauge.new
|
37
|
+
@boot_time_seconds.create("node", "", "boot_time_seconds", "Node boot time, in unixtime.")
|
38
|
+
|
39
|
+
@procs_running = CMetrics::Gauge.new
|
40
|
+
@procs_running.create("node", "", "procs_running", "Number of processes in runnable state.")
|
41
|
+
|
42
|
+
@procs_blocked = CMetrics::Gauge.new
|
43
|
+
@procs_blocked.create("node", "", "procs_blocked", "Number of processes blocked waiting for I/O to complete.")
|
44
|
+
end
|
45
|
+
|
46
|
+
def run
|
47
|
+
stat_update
|
48
|
+
end
|
49
|
+
|
50
|
+
def stat_update
|
51
|
+
stat_path = File.join(@procfs_path, "stat")
|
52
|
+
File.readlines(stat_path).each do |line|
|
53
|
+
entry, value, _ = line.split
|
54
|
+
case entry
|
55
|
+
when "intr"
|
56
|
+
@intr_total.set(value.to_f)
|
57
|
+
when "ctxt"
|
58
|
+
@context_switches_total.set(value.to_f)
|
59
|
+
when "btime"
|
60
|
+
@boot_time_seconds.set(value.to_f)
|
61
|
+
when "processes"
|
62
|
+
@forks_total.set(value.to_f)
|
63
|
+
when "procs_running"
|
64
|
+
@procs_running.set(value.to_f)
|
65
|
+
when "procs_blocked"
|
66
|
+
@procs_blocked.set(value.to_f)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def cmetrics
|
72
|
+
{
|
73
|
+
intr_total: @intr_total,
|
74
|
+
context_switches_total: @context_switches_total,
|
75
|
+
forks_total: @forks_total,
|
76
|
+
boot_time_seconds: @boot_time_seconds,
|
77
|
+
procs_running: @procs_running,
|
78
|
+
procs_blocked: @procs_blocked
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|