logstash-core 5.1.2-java → 5.2.0-java
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 +4 -4
- data/gemspec_jars.rb +0 -1
- data/lib/logstash-core/logstash-core.jar +0 -0
- data/lib/logstash-core/version.rb +1 -1
- data/lib/logstash-core_jars.rb +0 -2
- data/lib/logstash/agent.rb +26 -10
- data/lib/logstash/api/commands/default_metadata.rb +3 -1
- data/lib/logstash/api/commands/stats.rb +17 -1
- data/lib/logstash/api/modules/node_stats.rb +9 -0
- data/lib/logstash/api/modules/stats.rb +3 -2
- data/lib/logstash/config/mixin.rb +5 -8
- data/lib/logstash/instrument/collector.rb +1 -46
- data/lib/logstash/instrument/periodic_poller/base.rb +2 -0
- data/lib/logstash/instrument/periodic_poller/cgroup.rb +137 -0
- data/lib/logstash/instrument/periodic_poller/jvm.rb +1 -2
- data/lib/logstash/instrument/periodic_poller/os.rb +21 -0
- data/lib/logstash/instrument/periodic_poller/pq.rb +20 -0
- data/lib/logstash/instrument/periodic_pollers.rb +4 -2
- data/lib/logstash/output_delegator.rb +2 -0
- data/lib/logstash/pipeline.rb +31 -2
- data/lib/logstash/runner.rb +6 -1
- data/lib/logstash/util/wrapped_acked_queue.rb +11 -0
- data/lib/logstash/util/wrapped_synchronous_queue.rb +9 -0
- data/lib/logstash/version.rb +1 -1
- data/lib/logstash/webserver.rb +9 -1
- data/locales/en.yml +0 -3
- data/spec/api/lib/api/node_stats_spec.rb +5 -1
- data/spec/api/spec_helper.rb +3 -1
- data/spec/logstash/agent_spec.rb +2 -0
- data/spec/logstash/instrument/collector_spec.rb +4 -0
- data/spec/logstash/instrument/periodic_poller/cgroup_spec.rb +148 -0
- data/spec/logstash/instrument/periodic_poller/os_spec.rb +85 -0
- data/spec/logstash/output_delegator_spec.rb +12 -4
- data/spec/logstash/pipeline_reporter_spec.rb +2 -26
- data/spec/logstash/pipeline_spec.rb +102 -40
- data/spec/logstash/plugin_spec.rb +2 -6
- data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +34 -4
- data/spec/support/mocks_classes.rb +2 -2
- metadata +12 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 50660404c5ec13b21a5dccc7fd62b0d282dea262
|
|
4
|
+
data.tar.gz: 5b5b44f759032fda3022a8d08f982cf35ef5179a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 134ef54d0f7ef058c201420d997e702775bf4520e747a6c40ec76a6593597192a6448a537bad0e1df236214d636b469c6d95faa4894492cb05c23c826b0ce4e9
|
|
7
|
+
data.tar.gz: fa146b9c7ccd8891ed64dc892026313ff6356d87511613e23a270b8a30fa33a664a87d39b586b51b3e94961a3a18dd3640087746bdf965a5a603ff3bfd514b21
|
data/gemspec_jars.rb
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
# runtime dependencies to generate this gemspec dependencies file to be eval'ed by the gemspec
|
|
3
3
|
# for the jar-dependencies requirements.
|
|
4
4
|
|
|
5
|
-
gem.requirements << "jar org.apache.logging.log4j:log4j-1.2-api, 2.6.2"
|
|
6
5
|
gem.requirements << "jar org.apache.logging.log4j:log4j-api, 2.6.2"
|
|
7
6
|
gem.requirements << "jar org.apache.logging.log4j:log4j-core, 2.6.2"
|
|
8
7
|
gem.requirements << "jar com.fasterxml.jackson.core:jackson-core, 2.7.4"
|
|
Binary file
|
data/lib/logstash-core_jars.rb
CHANGED
|
@@ -5,7 +5,6 @@ rescue LoadError
|
|
|
5
5
|
require 'org/apache/logging/log4j/log4j-core/2.6.2/log4j-core-2.6.2.jar'
|
|
6
6
|
require 'org/apache/logging/log4j/log4j-api/2.6.2/log4j-api-2.6.2.jar'
|
|
7
7
|
require 'com/fasterxml/jackson/core/jackson-core/2.7.4/jackson-core-2.7.4.jar'
|
|
8
|
-
require 'org/apache/logging/log4j/log4j-1.2-api/2.6.2/log4j-1.2-api-2.6.2.jar'
|
|
9
8
|
require 'com/fasterxml/jackson/core/jackson-annotations/2.7.0/jackson-annotations-2.7.0.jar'
|
|
10
9
|
require 'com/fasterxml/jackson/core/jackson-databind/2.7.4/jackson-databind-2.7.4.jar'
|
|
11
10
|
end
|
|
@@ -14,7 +13,6 @@ if defined? Jars
|
|
|
14
13
|
require_jar( 'org.apache.logging.log4j', 'log4j-core', '2.6.2' )
|
|
15
14
|
require_jar( 'org.apache.logging.log4j', 'log4j-api', '2.6.2' )
|
|
16
15
|
require_jar( 'com.fasterxml.jackson.core', 'jackson-core', '2.7.4' )
|
|
17
|
-
require_jar( 'org.apache.logging.log4j', 'log4j-1.2-api', '2.6.2' )
|
|
18
16
|
require_jar( 'com.fasterxml.jackson.core', 'jackson-annotations', '2.7.0' )
|
|
19
17
|
require_jar( 'com.fasterxml.jackson.core', 'jackson-databind', '2.7.4' )
|
|
20
18
|
end
|
data/lib/logstash/agent.rb
CHANGED
|
@@ -52,7 +52,8 @@ class LogStash::Agent
|
|
|
52
52
|
# Create the collectors and configured it with the library
|
|
53
53
|
configure_metrics_collectors
|
|
54
54
|
|
|
55
|
-
@
|
|
55
|
+
@pipeline_reload_metric = metric.namespace([:stats, :pipelines])
|
|
56
|
+
@instance_reload_metric = metric.namespace([:stats, :reloads])
|
|
56
57
|
|
|
57
58
|
@dispatcher = LogStash::EventDispatcher.new(self)
|
|
58
59
|
LogStash::PLUGIN_REGISTRY.hooks.register_emitter(self.class, dispatcher)
|
|
@@ -109,7 +110,8 @@ class LogStash::Agent
|
|
|
109
110
|
begin
|
|
110
111
|
reload_pipeline!(pipeline_id)
|
|
111
112
|
rescue => e
|
|
112
|
-
@
|
|
113
|
+
@instance_reload_metric.increment(:failures)
|
|
114
|
+
@pipeline_reload_metric.namespace([pipeline_id.to_sym, :reloads]).tap do |n|
|
|
113
115
|
n.increment(:failures)
|
|
114
116
|
n.gauge(:last_error, { :message => e.message, :backtrace => e.backtrace})
|
|
115
117
|
n.gauge(:last_failure_timestamp, LogStash::Timestamp.now)
|
|
@@ -128,7 +130,6 @@ class LogStash::Agent
|
|
|
128
130
|
end
|
|
129
131
|
|
|
130
132
|
def stop_collecting_metrics
|
|
131
|
-
@collector.stop
|
|
132
133
|
@periodic_pollers.stop
|
|
133
134
|
end
|
|
134
135
|
|
|
@@ -176,6 +177,12 @@ class LogStash::Agent
|
|
|
176
177
|
@id_path ||= ::File.join(settings.get("path.data"), "uuid")
|
|
177
178
|
end
|
|
178
179
|
|
|
180
|
+
def running_pipelines
|
|
181
|
+
@upgrade_mutex.synchronize do
|
|
182
|
+
@pipelines.select {|pipeline_id, _| running_pipeline?(pipeline_id) }
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
179
186
|
def running_pipelines?
|
|
180
187
|
@upgrade_mutex.synchronize do
|
|
181
188
|
@pipelines.select {|pipeline_id, _| running_pipeline?(pipeline_id) }.any?
|
|
@@ -207,7 +214,9 @@ class LogStash::Agent
|
|
|
207
214
|
end
|
|
208
215
|
|
|
209
216
|
|
|
210
|
-
@periodic_pollers = LogStash::Instrument::PeriodicPollers.new(@metric
|
|
217
|
+
@periodic_pollers = LogStash::Instrument::PeriodicPollers.new(@metric,
|
|
218
|
+
settings.get("queue.type"),
|
|
219
|
+
self)
|
|
211
220
|
@periodic_pollers.start
|
|
212
221
|
end
|
|
213
222
|
|
|
@@ -236,7 +245,8 @@ class LogStash::Agent
|
|
|
236
245
|
begin
|
|
237
246
|
LogStash::Pipeline.new(config, settings, metric)
|
|
238
247
|
rescue => e
|
|
239
|
-
@
|
|
248
|
+
@instance_reload_metric.increment(:failures)
|
|
249
|
+
@pipeline_reload_metric.namespace([settings.get("pipeline.id").to_sym, :reloads]).tap do |n|
|
|
240
250
|
n.increment(:failures)
|
|
241
251
|
n.gauge(:last_error, { :message => e.message, :backtrace => e.backtrace})
|
|
242
252
|
n.gauge(:last_failure_timestamp, LogStash::Timestamp.now)
|
|
@@ -291,7 +301,8 @@ class LogStash::Agent
|
|
|
291
301
|
begin
|
|
292
302
|
pipeline.run
|
|
293
303
|
rescue => e
|
|
294
|
-
@
|
|
304
|
+
@instance_reload_metric.increment(:failures)
|
|
305
|
+
@pipeline_reload_metric.namespace([id.to_sym, :reloads]).tap do |n|
|
|
295
306
|
n.increment(:failures)
|
|
296
307
|
n.gauge(:last_error, { :message => e.message, :backtrace => e.backtrace})
|
|
297
308
|
n.gauge(:last_failure_timestamp, LogStash::Timestamp.now)
|
|
@@ -302,7 +313,7 @@ class LogStash::Agent
|
|
|
302
313
|
while true do
|
|
303
314
|
if !t.alive?
|
|
304
315
|
return false
|
|
305
|
-
elsif pipeline.
|
|
316
|
+
elsif pipeline.running?
|
|
306
317
|
return true
|
|
307
318
|
else
|
|
308
319
|
sleep 0.01
|
|
@@ -319,8 +330,11 @@ class LogStash::Agent
|
|
|
319
330
|
end
|
|
320
331
|
|
|
321
332
|
def start_pipelines
|
|
322
|
-
@
|
|
333
|
+
@instance_reload_metric.increment(:successes, 0)
|
|
334
|
+
@instance_reload_metric.increment(:failures, 0)
|
|
335
|
+
@pipelines.each do |id, pipeline|
|
|
323
336
|
start_pipeline(id)
|
|
337
|
+
pipeline.collect_stats
|
|
324
338
|
# no reloads yet, initalize all the reload metrics
|
|
325
339
|
init_pipeline_reload_metrics(id)
|
|
326
340
|
end
|
|
@@ -340,10 +354,12 @@ class LogStash::Agent
|
|
|
340
354
|
reset_pipeline_metrics(pipeline_id)
|
|
341
355
|
@pipelines[pipeline_id] = new_pipeline
|
|
342
356
|
if start_pipeline(pipeline_id) # pipeline started successfuly
|
|
343
|
-
@
|
|
357
|
+
@instance_reload_metric.increment(:successes)
|
|
358
|
+
@pipeline_reload_metric.namespace([pipeline_id.to_sym, :reloads]).tap do |n|
|
|
344
359
|
n.increment(:successes)
|
|
345
360
|
n.gauge(:last_success_timestamp, LogStash::Timestamp.now)
|
|
346
361
|
end
|
|
362
|
+
|
|
347
363
|
end
|
|
348
364
|
end
|
|
349
365
|
|
|
@@ -356,7 +372,7 @@ class LogStash::Agent
|
|
|
356
372
|
end
|
|
357
373
|
|
|
358
374
|
def init_pipeline_reload_metrics(id)
|
|
359
|
-
@
|
|
375
|
+
@pipeline_reload_metric.namespace([id.to_sym, :reloads]).tap do |n|
|
|
360
376
|
n.increment(:successes, 0)
|
|
361
377
|
n.increment(:failures, 0)
|
|
362
378
|
n.gauge(:last_error, nil)
|
|
@@ -3,6 +3,9 @@ require "logstash/api/commands/base"
|
|
|
3
3
|
require 'logstash/util/thread_dump'
|
|
4
4
|
require_relative "hot_threads_reporter"
|
|
5
5
|
|
|
6
|
+
java_import java.nio.file.Files
|
|
7
|
+
java_import java.nio.file.Paths
|
|
8
|
+
|
|
6
9
|
module LogStash
|
|
7
10
|
module Api
|
|
8
11
|
module Commands
|
|
@@ -16,10 +19,14 @@ module LogStash
|
|
|
16
19
|
),
|
|
17
20
|
:mem => memory,
|
|
18
21
|
:gc => gc,
|
|
19
|
-
:uptime_in_millis => service.get_shallow(:jvm, :uptime_in_millis)
|
|
22
|
+
:uptime_in_millis => service.get_shallow(:jvm, :uptime_in_millis),
|
|
20
23
|
}
|
|
21
24
|
end
|
|
22
25
|
|
|
26
|
+
def reloads
|
|
27
|
+
service.get_shallow(:stats, :reloads)
|
|
28
|
+
end
|
|
29
|
+
|
|
23
30
|
def process
|
|
24
31
|
extract_metrics(
|
|
25
32
|
[:jvm, :process],
|
|
@@ -61,6 +68,14 @@ module LogStash
|
|
|
61
68
|
}
|
|
62
69
|
end
|
|
63
70
|
|
|
71
|
+
def os
|
|
72
|
+
service.get_shallow(:os)
|
|
73
|
+
rescue
|
|
74
|
+
# The only currently fetch OS information is about the linux
|
|
75
|
+
# containers.
|
|
76
|
+
{}
|
|
77
|
+
end
|
|
78
|
+
|
|
64
79
|
def gc
|
|
65
80
|
service.get_shallow(:jvm, :gc)
|
|
66
81
|
end
|
|
@@ -94,6 +109,7 @@ module LogStash
|
|
|
94
109
|
:outputs => plugin_stats(stats, :outputs)
|
|
95
110
|
},
|
|
96
111
|
:reloads => stats[:reloads],
|
|
112
|
+
:queue => stats[:queue]
|
|
97
113
|
}
|
|
98
114
|
end
|
|
99
115
|
end # module PluginsStats
|
|
@@ -13,11 +13,16 @@ module LogStash
|
|
|
13
13
|
:jvm => jvm_payload,
|
|
14
14
|
:process => process_payload,
|
|
15
15
|
:pipeline => pipeline_payload,
|
|
16
|
+
:reloads => reloads,
|
|
17
|
+
:os => os_payload
|
|
16
18
|
}
|
|
17
19
|
respond_with(payload, {:filter => params["filter"]})
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
private
|
|
23
|
+
def os_payload
|
|
24
|
+
@stats.os
|
|
25
|
+
end
|
|
21
26
|
|
|
22
27
|
def events_payload
|
|
23
28
|
@stats.events
|
|
@@ -27,6 +32,10 @@ module LogStash
|
|
|
27
32
|
@stats.jvm
|
|
28
33
|
end
|
|
29
34
|
|
|
35
|
+
def reloads
|
|
36
|
+
@stats.reloads
|
|
37
|
+
end
|
|
38
|
+
|
|
30
39
|
def process_payload
|
|
31
40
|
@stats.process
|
|
32
41
|
end
|
|
@@ -30,8 +30,9 @@ module LogStash
|
|
|
30
30
|
:jvm => {
|
|
31
31
|
:timestamp => stats_command.started_at,
|
|
32
32
|
:uptime_in_millis => stats_command.uptime,
|
|
33
|
-
:memory => stats_command.memory
|
|
34
|
-
}
|
|
33
|
+
:memory => stats_command.memory,
|
|
34
|
+
},
|
|
35
|
+
:os => stats_command.os
|
|
35
36
|
}
|
|
36
37
|
respond_with(payload, {:filter => params["filter"]})
|
|
37
38
|
end
|
|
@@ -268,6 +268,7 @@ module LogStash::Config::Mixin
|
|
|
268
268
|
return is_valid
|
|
269
269
|
end # def validate
|
|
270
270
|
|
|
271
|
+
# TODO: Remove in 6.0
|
|
271
272
|
def print_version_notice
|
|
272
273
|
return if @@version_notice_given
|
|
273
274
|
|
|
@@ -288,14 +289,10 @@ module LogStash::Config::Mixin
|
|
|
288
289
|
end
|
|
289
290
|
end
|
|
290
291
|
rescue LogStash::PluginNoVersionError
|
|
291
|
-
#
|
|
292
|
-
#
|
|
293
|
-
#
|
|
294
|
-
|
|
295
|
-
:type => @plugin_type,
|
|
296
|
-
:name => @config_name,
|
|
297
|
-
:LOGSTASH_VERSION => LOGSTASH_VERSION))
|
|
298
|
-
ensure
|
|
292
|
+
# This can happen because of one of the following:
|
|
293
|
+
# - The plugin is loaded from the plugins.path and contains no gemspec.
|
|
294
|
+
# - The plugin is defined in a universal plugin, so the loaded plugin doesn't correspond to an actual gemspec.
|
|
295
|
+
ensure
|
|
299
296
|
@@version_notice_given = true
|
|
300
297
|
end
|
|
301
298
|
end
|
|
@@ -11,12 +11,8 @@ module LogStash module Instrument
|
|
|
11
11
|
# The Collector is the single point of reference for all
|
|
12
12
|
# the metrics collection inside logstash, the metrics library will make
|
|
13
13
|
# direct calls to this class.
|
|
14
|
-
#
|
|
15
|
-
# This class is an observable responsable of periodically emitting view of the system
|
|
16
|
-
# to other components like the internal metrics pipelines.
|
|
17
14
|
class Collector
|
|
18
15
|
include LogStash::Util::Loggable
|
|
19
|
-
include Observable
|
|
20
16
|
|
|
21
17
|
SNAPSHOT_ROTATION_TIME_SECS = 1 # seconds
|
|
22
18
|
SNAPSHOT_ROTATION_TIMEOUT_INTERVAL_SECS = 10 * 60 # seconds
|
|
@@ -26,7 +22,6 @@ module LogStash module Instrument
|
|
|
26
22
|
def initialize
|
|
27
23
|
@metric_store = MetricStore.new
|
|
28
24
|
@agent = nil
|
|
29
|
-
start_periodic_snapshotting
|
|
30
25
|
end
|
|
31
26
|
|
|
32
27
|
# The metric library will call this unique interface
|
|
@@ -43,8 +38,6 @@ module LogStash module Instrument
|
|
|
43
38
|
end
|
|
44
39
|
|
|
45
40
|
metric.execute(*metric_type_params)
|
|
46
|
-
|
|
47
|
-
changed # we had changes coming in so we can notify the observers
|
|
48
41
|
rescue MetricStore::NamespacesExpectedError => e
|
|
49
42
|
logger.error("Collector: Cannot record metric", :exception => e)
|
|
50
43
|
rescue NameError => e
|
|
@@ -58,51 +51,13 @@ module LogStash module Instrument
|
|
|
58
51
|
end
|
|
59
52
|
end
|
|
60
53
|
|
|
61
|
-
# Monitor the `Concurrent::TimerTask` this update is triggered on every successful or not
|
|
62
|
-
# run of the task, TimerTask implement Observable and the collector acts as
|
|
63
|
-
# the observer and will keep track if something went wrong in the execution.
|
|
64
|
-
#
|
|
65
|
-
# @param [Time] Time of execution
|
|
66
|
-
# @param [result] Result of the execution
|
|
67
|
-
# @param [Exception] Exception
|
|
68
|
-
def update(time_of_execution, result, exception)
|
|
69
|
-
return true if exception.nil?
|
|
70
|
-
logger.error("Collector: Something went wrong went sending data to the observers",
|
|
71
|
-
:execution_time => time_of_execution,
|
|
72
|
-
:result => result,
|
|
73
|
-
:exception => exception.class.name)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
54
|
# Snapshot the current Metric Store and return it immediately,
|
|
77
55
|
# This is useful if you want to get access to the current metric store without
|
|
78
56
|
# waiting for a periodic call.
|
|
79
57
|
#
|
|
80
58
|
# @return [LogStash::Instrument::MetricStore]
|
|
81
59
|
def snapshot_metric
|
|
82
|
-
Snapshot.new(@metric_store)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Configure and start the periodic task for snapshotting the `MetricStore`
|
|
86
|
-
def start_periodic_snapshotting
|
|
87
|
-
@snapshot_task = Concurrent::TimerTask.new { publish_snapshot }
|
|
88
|
-
@snapshot_task.execution_interval = SNAPSHOT_ROTATION_TIME_SECS
|
|
89
|
-
@snapshot_task.timeout_interval = SNAPSHOT_ROTATION_TIMEOUT_INTERVAL_SECS
|
|
90
|
-
@snapshot_task.add_observer(self)
|
|
91
|
-
@snapshot_task.execute
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def stop
|
|
95
|
-
@snapshot_task.shutdown
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Create a snapshot of the MetricStore and send it to to the registered observers
|
|
99
|
-
# The observer will receive the following signature in the update methode.
|
|
100
|
-
#
|
|
101
|
-
# `#update(created_at, metric_store)`
|
|
102
|
-
def publish_snapshot
|
|
103
|
-
created_at = Time.now
|
|
104
|
-
logger.debug("Collector: Sending snapshot to observers", :created_at => created_at) if logger.debug?
|
|
105
|
-
notify_observers(snapshot_metric)
|
|
60
|
+
Snapshot.new(@metric_store.dup)
|
|
106
61
|
end
|
|
107
62
|
|
|
108
63
|
def clear(keypath)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require "pathname"
|
|
3
|
+
require "logstash/util/loggable"
|
|
4
|
+
|
|
5
|
+
# Logic from elasticsearch/core/src/main/java/org/elasticsearch/monitor/os/OsProbe.java
|
|
6
|
+
# Move to ruby to remove any existing dependency
|
|
7
|
+
module LogStash module Instrument module PeriodicPoller
|
|
8
|
+
class Cgroup
|
|
9
|
+
include LogStash::Util::Loggable
|
|
10
|
+
|
|
11
|
+
CONTROL_GROUP_RE = Regexp.compile("\\d+:([^:,]+(?:,[^:,]+)?):(/.*)");
|
|
12
|
+
CONTROLLER_SEPERATOR_RE = ","
|
|
13
|
+
|
|
14
|
+
PROC_SELF_CGROUP_FILE = Pathname.new("/proc/self/cgroup")
|
|
15
|
+
PROC_CGROUP_CPU_DIR = Pathname.new("/sys/fs/cgroup/cpu")
|
|
16
|
+
PROC_CGROUP_CPUACCT_DIR = Pathname.new("/sys/fs/cgroup/cpuacct")
|
|
17
|
+
|
|
18
|
+
GROUP_CPUACCT = "cpuacct"
|
|
19
|
+
CPUACCT_USAGE_FILE = "cpuacct.usage"
|
|
20
|
+
|
|
21
|
+
GROUP_CPU = "cpu"
|
|
22
|
+
CPU_FS_PERIOD_US_FILE = "cpu.cfs_period_us"
|
|
23
|
+
CPU_FS_QUOTA_US_FILE = "cpu.cfs_quota_us"
|
|
24
|
+
|
|
25
|
+
CPU_STATS_FILE = "cpu.stat"
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
def are_cgroup_available?
|
|
29
|
+
[::File.exist?(PROC_SELF_CGROUP_FILE),
|
|
30
|
+
Dir.exist?(PROC_CGROUP_CPU_DIR),
|
|
31
|
+
Dir.exist?(PROC_CGROUP_CPUACCT_DIR)].all?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def control_groups
|
|
35
|
+
response = {}
|
|
36
|
+
|
|
37
|
+
read_proc_self_cgroup_lines.each do |line|
|
|
38
|
+
matches = CONTROL_GROUP_RE.match(line)
|
|
39
|
+
# multiples controlles, same hierachy
|
|
40
|
+
controllers = matches[1].split(CONTROLLER_SEPERATOR_RE)
|
|
41
|
+
controllers.each_with_object(response) { |controller| response[controller] = matches[2] }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
response
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def read_first_line(path)
|
|
48
|
+
IO.readlines(path).first
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def cgroup_cpuacct_usage_nanos(control_group)
|
|
52
|
+
read_first_line(::File.join(PROC_CGROUP_CPUACCT_DIR, control_group, CPUACCT_USAGE_FILE)).to_i
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def cgroup_cpu_fs_period_micros(control_group)
|
|
56
|
+
read_first_line(::File.join(PROC_CGROUP_CPUACCT_DIR, control_group, CPU_FS_PERIOD_US_FILE)).to_i
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def cgroup_cpu_fs_quota_micros(control_group)
|
|
60
|
+
read_first_line(::File.join(PROC_CGROUP_CPUACCT_DIR, control_group, CPU_FS_QUOTA_US_FILE)).to_i
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def read_proc_self_cgroup_lines
|
|
64
|
+
IO.readlines(PROC_SELF_CGROUP_FILE)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class CpuStats
|
|
68
|
+
attr_reader :number_of_elapsed_periods, :number_of_times_throttled, :time_throttled_nanos
|
|
69
|
+
|
|
70
|
+
def initialize(number_of_elapsed_periods, number_of_times_throttled, time_throttled_nanos)
|
|
71
|
+
@number_of_elapsed_periods = number_of_elapsed_periods
|
|
72
|
+
@number_of_times_throttled = number_of_times_throttled
|
|
73
|
+
@time_throttled_nanos = time_throttled_nanos
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def read_sys_fs_cgroup_cpuacct_cpu_stat(control_group)
|
|
78
|
+
IO.readlines(::File.join(PROC_CGROUP_CPU_DIR, control_group, CPU_STATS_FILE))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def cgroup_cpuacct_cpu_stat(control_group)
|
|
82
|
+
lines = read_sys_fs_cgroup_cpuacct_cpu_stat(control_group);
|
|
83
|
+
|
|
84
|
+
number_of_elapsed_periods = -1;
|
|
85
|
+
number_of_times_throttled = -1;
|
|
86
|
+
time_throttled_nanos = -1;
|
|
87
|
+
|
|
88
|
+
lines.each do |line|
|
|
89
|
+
fields = line.split(/\s+/)
|
|
90
|
+
case fields.first
|
|
91
|
+
when "nr_periods" then number_of_elapsed_periods = fields[1].to_i
|
|
92
|
+
when "nr_throttled" then number_of_times_throttled= fields[1].to_i
|
|
93
|
+
when "throttled_time" then time_throttled_nanos = fields[1].to_i
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
CpuStats.new(number_of_elapsed_periods, number_of_times_throttled, time_throttled_nanos)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def get_all
|
|
101
|
+
groups = control_groups
|
|
102
|
+
return if groups.empty?
|
|
103
|
+
|
|
104
|
+
cgroups_stats = {
|
|
105
|
+
:cpuacct => {},
|
|
106
|
+
:cpu => {}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
cpuacct_group = groups[GROUP_CPUACCT]
|
|
110
|
+
cgroups_stats[:cpuacct][:control_group] = cpuacct_group
|
|
111
|
+
cgroups_stats[:cpuacct][:usage_nanos] = cgroup_cpuacct_usage_nanos(cpuacct_group)
|
|
112
|
+
|
|
113
|
+
cpu_group = groups[GROUP_CPU]
|
|
114
|
+
cgroups_stats[:cpu][:control_group] = cpu_group
|
|
115
|
+
cgroups_stats[:cpu][:cfs_period_micros] = cgroup_cpu_fs_period_micros(cpu_group)
|
|
116
|
+
cgroups_stats[:cpu][:cfs_quota_micros] = cgroup_cpu_fs_quota_micros(cpu_group)
|
|
117
|
+
|
|
118
|
+
cpu_stats = cgroup_cpuacct_cpu_stat(cpu_group)
|
|
119
|
+
|
|
120
|
+
cgroups_stats[:cpu][:stat] = {
|
|
121
|
+
:number_of_elapsed_periods => cpu_stats.number_of_elapsed_periods,
|
|
122
|
+
:number_of_times_throttled => cpu_stats.number_of_times_throttled,
|
|
123
|
+
:time_throttled_nanos => cpu_stats.time_throttled_nanos
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
cgroups_stats
|
|
127
|
+
rescue => e
|
|
128
|
+
logger.debug("Error, cannot retrieve cgroups information", :exception => e.class.name, :message => e.message) if logger.debug?
|
|
129
|
+
nil
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def get
|
|
133
|
+
are_cgroup_available? ? get_all : nil
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end end end
|