logstash-core 5.1.2-java → 5.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|