logstash-core 5.6.12-java → 5.6.13-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 059464d65eab3cfffcfe8e64803a9f3aa62c4fcd
4
- data.tar.gz: dcee877fadbefd630152d65ac0ab20f51e7da40f
3
+ metadata.gz: f1fb7d5d2430aacfe5c50b4e058e1effe78df4be
4
+ data.tar.gz: 76e166dcf3df950e09ea92caa305077dbd55ef99
5
5
  SHA512:
6
- metadata.gz: 3616e8fc7f4c6f5c78148890c13d98f838cac0c5214b924facd347893f8d9e2896bb3d7dd4fbbab3e1608040c34c35a9f223c34e88da6abcbfd261b076774c93
7
- data.tar.gz: 7e1398292c18a8e30794b905268b67acf0e111b98ff43a7e0000af4d88637bccffec334881cec8a8311d5dcf9f04cd1029ca08d20c85236934c0018e06822926
6
+ metadata.gz: c357ba17c5cc8ccc9bc24a13edc8e383d68e1628991df92b1737bbe1ee5ea943876d707fcefe5bf9d62876afcc1e286b00601121b4a9cf2634410613b9a2a33a
7
+ data.tar.gz: 14201e4fc149d68cbe374c047a91216f9a9a200a9e0885c1f3958343ab700f20e0ba163572f9dd732e7dbf25e1ca39d68cc99d1a35b1fd1040fc257ef9044541
@@ -1,5 +1,4 @@
1
1
  # encoding: utf-8
2
- require "pathname"
3
2
  require "logstash/util/loggable"
4
3
 
5
4
  # Logic from elasticsearch/core/src/main/java/org/elasticsearch/monitor/os/OsProbe.java
@@ -7,130 +6,214 @@ require "logstash/util/loggable"
7
6
  module LogStash module Instrument module PeriodicPoller
8
7
  class Cgroup
9
8
  include LogStash::Util::Loggable
9
+ class Override
10
+ attr_reader :key, :value
11
+ def initialize(key)
12
+ @key = key
13
+ @value = java.lang.System.getProperty(@key)
14
+ end
10
15
 
11
- CONTROL_GROUP_RE = Regexp.compile("\\d+:([^:,]+(?:,[^:,]+)?):(/.*)");
12
- CONTROLLER_SEPARATOR_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"
16
+ def nil?
17
+ value.nil?
18
+ end
24
19
 
25
- CPU_STATS_FILE = "cpu.stat"
20
+ def override(other)
21
+ nil? ? other : value
22
+ end
23
+ end
26
24
 
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?
25
+ ## `/proc/self/cgroup` contents look like this
26
+ # 5:cpu,cpuacct:/
27
+ # 4:cpuset:/
28
+ # 2:net_cls,net_prio:/
29
+ # 0::/user.slice/user-1000.slice/session-932.scope
30
+ ## e.g. N:controller:/path-to-info
31
+ # we find the controller and path
32
+ # we skip the line without a controller e.g. 0::/path
33
+ # we assume there are these symlinks:
34
+ # `/sys/fs/cgroup/cpu` -> `/sys/fs/cgroup/cpu,cpuacct
35
+ # `/sys/fs/cgroup/cpuacct` -> `/sys/fs/cgroup/cpu,cpuacct
36
+
37
+ CGROUP_FILE = "/proc/self/cgroup"
38
+ CPUACCT_DIR = "/sys/fs/cgroup/cpuacct"
39
+ CPU_DIR = "/sys/fs/cgroup/cpu"
40
+ CRITICAL_PATHS = [CGROUP_FILE, CPUACCT_DIR, CPU_DIR]
41
+
42
+ CONTROLLER_CPUACCT_LABEL = "cpuacct"
43
+ CONTROLLER_CPU_LABEL = "cpu"
44
+
45
+ class CGroupResources
46
+ CONTROL_GROUP_RE = Regexp.compile("\\d+:([^:,]+(?:,[^:,]+)?):(/.*)")
47
+ CONTROLLER_SEPARATOR_RE = ","
48
+
49
+ def cgroup_available?
50
+ # don't cache to ivar, in case the files are mounted after logstash starts??
51
+ CRITICAL_PATHS.all?{|path| ::File.exist?(path)}
32
52
  end
33
53
 
34
- def control_groups
54
+ def controller_groups
35
55
  response = {}
36
-
37
- read_proc_self_cgroup_lines.each do |line|
56
+ IO.readlines(CGROUP_FILE).each do |line|
38
57
  matches = CONTROL_GROUP_RE.match(line)
58
+ next if matches.nil?
39
59
  # multiples controls, same hierarchy
40
60
  controllers = matches[1].split(CONTROLLER_SEPARATOR_RE)
41
- controllers.each_with_object(response) { |controller| response[controller] = matches[2] }
61
+ controllers.each do |controller|
62
+ case controller
63
+ when CONTROLLER_CPU_LABEL
64
+ response[controller] = CpuResource.new(matches[2])
65
+ when CONTROLLER_CPUACCT_LABEL
66
+ response[controller] = CpuAcctResource.new(matches[2])
67
+ else
68
+ response[controller] = UnimplementedResource.new(controller, matches[2])
69
+ end
70
+ end
42
71
  end
43
-
44
72
  response
45
73
  end
74
+ end
46
75
 
47
- def read_first_line(path)
48
- IO.readlines(path).first
76
+ module ControllerResource
77
+ attr_reader :base_path, :override, :offset_path
78
+ def implemented?
79
+ true
49
80
  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
81
+ private
82
+ def common_initialize(base, override_key, original_path)
83
+ @base_path = base
84
+ # override is needed here for the logging statements
85
+ @override = Override.new(override_key)
86
+ @offset_path = @override.override(original_path)
87
+ @procs = {}
88
+ @procs[:read_int] = lambda {|path| IO.readlines(path).first.to_i }
89
+ @procs[:read_lines] = lambda {|path| IO.readlines(path) }
53
90
  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
91
+ def call_if_file_exists(call_key, file, not_found_value)
92
+ path = ::File.join(@base_path, @offset_path, file)
93
+ if ::File.exist?(path)
94
+ @procs[call_key].call(path)
95
+ else
96
+ message = "File #{path} cannot be found, "
97
+ if override.nil?
98
+ message.concat("try providing an override '#{override.key}' in the Logstash JAVA_OPTS environment variable")
99
+ else
100
+ message.concat("even though the '#{override.key}' override is: '#{override.value}'")
101
+ end
102
+ logger.debug(message)
103
+ not_found_value
104
+ end
57
105
  end
106
+ end
58
107
 
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
108
+ class CpuAcctResource
109
+ include LogStash::Util::Loggable
110
+ include ControllerResource
111
+ def initialize(original_path)
112
+ common_initialize(CPUACCT_DIR, "ls.cgroup.cpuacct.path.override", original_path)
61
113
  end
62
-
63
- def read_proc_self_cgroup_lines
64
- IO.readlines(PROC_SELF_CGROUP_FILE)
114
+ def to_hash
115
+ {:control_group => offset_path, :usage_nanos => cpuacct_usage}
65
116
  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
117
+ private
118
+ def cpuacct_usage
119
+ call_if_file_exists(:read_int, "cpuacct.usage", -1)
75
120
  end
121
+ end
76
122
 
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))
123
+ class CpuResource
124
+ include LogStash::Util::Loggable
125
+ include ControllerResource
126
+ def initialize(original_path)
127
+ common_initialize(CPU_DIR, "ls.cgroup.cpu.path.override", original_path)
79
128
  end
129
+ def to_hash
130
+ {
131
+ :control_group => offset_path,
132
+ :cfs_period_micros => cfs_period_us,
133
+ :cfs_quota_micros => cfs_quota_us,
134
+ :stat => build_cpu_stats_hash
135
+ }
136
+ end
137
+ private
138
+ def cfs_period_us
139
+ call_if_file_exists(:read_int, "cpu.cfs_period_us", -1)
140
+ end
141
+ def cfs_quota_us
142
+ call_if_file_exists(:read_int, "cpu.cfs_quota_us", -1)
143
+ end
144
+ def build_cpu_stats_hash
145
+ stats = CpuStats.new
146
+ lines = call_if_file_exists(:read_lines, "cpu.stat", [])
147
+ stats.update(lines)
148
+ stats.to_hash
149
+ end
150
+ end
80
151
 
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;
152
+ class UnimplementedResource
153
+ attr_reader :controller, :original_path
154
+ def initialize(controller, original_path)
155
+ @controller, @original_path = controller, original_path
156
+ end
157
+ def implemented?
158
+ false
159
+ end
160
+ end
87
161
 
162
+ class CpuStats
163
+ def initialize
164
+ @number_of_elapsed_periods = -1
165
+ @number_of_times_throttled = -1
166
+ @time_throttled_nanos = -1
167
+ end
168
+ def update(lines)
88
169
  lines.each do |line|
89
170
  fields = line.split(/\s+/)
171
+ next unless fields.size > 1
90
172
  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
173
+ when "nr_periods" then @number_of_elapsed_periods = fields[1].to_i
174
+ when "nr_throttled" then @number_of_times_throttled = fields[1].to_i
175
+ when "throttled_time" then @time_throttled_nanos = fields[1].to_i
94
176
  end
95
177
  end
96
-
97
- CpuStats.new(number_of_elapsed_periods, number_of_times_throttled, time_throttled_nanos)
98
178
  end
179
+ def to_hash
180
+ {
181
+ :number_of_elapsed_periods => @number_of_elapsed_periods,
182
+ :number_of_times_throttled => @number_of_times_throttled,
183
+ :time_throttled_nanos => @time_throttled_nanos
184
+ }
185
+ end
186
+ end
99
187
 
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)
188
+ CGROUP_RESOURCES = CGroupResources.new
112
189
 
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)
190
+ class << self
191
+ def get_all
192
+ unless CGROUP_RESOURCES.cgroup_available?
193
+ logger.debug("One or more required cgroup files or directories not found: #{CRITICAL_PATHS.join(', ')}")
194
+ return
195
+ end
117
196
 
118
- cpu_stats = cgroup_cpuacct_cpu_stat(cpu_group)
197
+ groups = CGROUP_RESOURCES.controller_groups
119
198
 
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
- }
199
+ if groups.empty?
200
+ logger.debug("The main cgroup file did not have any controllers: #{CGROUP_FILE}")
201
+ return
202
+ end
125
203
 
126
- cgroups_stats
204
+ cgroups_stats = {}
205
+ groups.each do |name, controller|
206
+ next unless controller.implemented?
207
+ cgroups_stats[name.to_sym] = controller.to_hash
208
+ end
209
+ cgroups_stats
127
210
  rescue => e
128
- logger.debug("Error, cannot retrieve cgroups information", :exception => e.class.name, :message => e.message) if logger.debug?
211
+ logger.debug("Error, cannot retrieve cgroups information", :exception => e.class.name, :message => e.message, :backtrace => e.backtrace.take(4)) if logger.debug?
129
212
  nil
130
213
  end
131
214
 
132
215
  def get
133
- are_cgroup_available? ? get_all : nil
216
+ get_all
134
217
  end
135
218
  end
136
219
  end
@@ -2,127 +2,258 @@
2
2
  require "logstash/instrument/periodic_poller/cgroup"
3
3
  require "spec_helper"
4
4
 
5
- describe LogStash::Instrument::PeriodicPoller::Cgroup do
6
- subject { described_class }
5
+ LogStash::Logging::Logger::configure_logging("DEBUG")
7
6
 
8
- context ".are_cgroup_available?" do
9
- context "all the file exist" do
7
+ module LogStash module Instrument module PeriodicPoller
8
+ describe "cgroup stats" do
9
+ let(:relative_path) { "/docker/a1f61" }
10
+ let(:proc_self_cgroup_content) do
11
+ %W(14:name=systemd,holaunlimited:#{relative_path}
12
+ 13:pids:#{relative_path}
13
+ 12:hugetlb:#{relative_path}
14
+ 11:net_prio:#{relative_path}
15
+ 10:perf_event:#{relative_path}
16
+ 9:net_cls:#{relative_path}
17
+ 8:freezer:#{relative_path}
18
+ 7:devices:#{relative_path}
19
+ 6:memory:#{relative_path}
20
+ 5:blkio:#{relative_path}
21
+ 4:cpuacct:#{relative_path}
22
+ 3:cpu:#{relative_path}
23
+ 2:cpuset:#{relative_path}
24
+ 1:name=openrc:/docker
25
+ 0::/docker)
26
+ end
27
+ describe Cgroup::CGroupResources do
28
+ subject(:cgroup_resources) { described_class.new }
29
+ context "method: cgroup_available?" do
30
+ context "resources exist" do
31
+ before do
32
+ allow(::File).to receive(:exist?).and_return(true)
33
+ end
34
+ it "returns true" do
35
+ expect(cgroup_resources.cgroup_available?).to be_truthy
36
+ end
37
+ end
38
+ context "resources do not exist" do
39
+ subject { described_class.new }
40
+ before do
41
+ allow(::File).to receive(:exist?).and_return(true)
42
+ allow(::File).to receive(:exist?).with("/proc/self/cgroup").and_return(false)
43
+ end
44
+ it "returns false" do
45
+ expect(cgroup_resources.cgroup_available?).to be_falsey
46
+ end
47
+ end
48
+ end
49
+
50
+ context "method: controller_groups" do
10
51
  before do
11
- allow(::File).to receive(:exist?).with(subject::PROC_SELF_CGROUP_FILE).and_return(true)
12
- allow(::Dir).to receive(:exist?).with(subject::PROC_CGROUP_CPU_DIR).and_return(true)
13
- allow(::Dir).to receive(:exist?).with(subject::PROC_CGROUP_CPUACCT_DIR).and_return(true)
52
+ allow(IO).to receive(:readlines).with("/proc/self/cgroup").and_return(proc_self_cgroup_content)
14
53
  end
15
54
 
16
- it "returns true" do
17
- expect(subject.are_cgroup_available?).to be_truthy
55
+ it "returns the control groups" do
56
+ controllers = cgroup_resources.controller_groups
57
+
58
+ controller = controllers["cpuacct"]
59
+ expect(controller).to be_a(Cgroup::CpuAcctResource)
60
+ expect(controller.base_path).to eq("/sys/fs/cgroup/cpuacct")
61
+ expect(controller.offset_path).to eq(relative_path)
62
+ expect(controller.override).to be_a(Cgroup::Override)
63
+ expect(controller.override.nil?).to be_truthy
64
+
65
+ controller = controllers["cpu"]
66
+ expect(controller).to be_a(Cgroup::CpuResource)
67
+ expect(controller.base_path).to eq("/sys/fs/cgroup/cpu")
68
+ expect(controller.offset_path).to eq(relative_path)
69
+ expect(controller.override).to be_a(Cgroup::Override)
70
+ expect(controller.override.nil?).to be_truthy
71
+
72
+ controller = controllers["name=systemd"]
73
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
74
+ expect(controller.controller).to eq("name=systemd")
75
+ expect(controller.original_path).to eq(relative_path)
76
+
77
+ controller = controllers["holaunlimited"]
78
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
79
+ expect(controller.controller).to eq("holaunlimited")
80
+ expect(controller.original_path).to eq(relative_path)
81
+
82
+ controller = controllers["pids"]
83
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
84
+ expect(controller.controller).to eq("pids")
85
+ expect(controller.original_path).to eq(relative_path)
86
+
87
+ controller = controllers["hugetlb"]
88
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
89
+ expect(controller.controller).to eq("hugetlb")
90
+ expect(controller.original_path).to eq(relative_path)
91
+
92
+ controller = controllers["net_prio"]
93
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
94
+ expect(controller.controller).to eq("net_prio")
95
+ expect(controller.original_path).to eq(relative_path)
96
+
97
+ controller = controllers["perf_event"]
98
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
99
+ expect(controller.controller).to eq("perf_event")
100
+ expect(controller.original_path).to eq(relative_path)
101
+
102
+ controller = controllers["net_cls"]
103
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
104
+ expect(controller.controller).to eq("net_cls")
105
+ expect(controller.original_path).to eq(relative_path)
106
+
107
+ controller = controllers["freezer"]
108
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
109
+ expect(controller.controller).to eq("freezer")
110
+ expect(controller.original_path).to eq(relative_path)
111
+
112
+ controller = controllers["devices"]
113
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
114
+ expect(controller.controller).to eq("devices")
115
+ expect(controller.original_path).to eq(relative_path)
116
+
117
+ controller = controllers["memory"]
118
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
119
+ expect(controller.controller).to eq("memory")
120
+ expect(controller.original_path).to eq(relative_path)
121
+
122
+ controller = controllers["blkio"]
123
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
124
+ expect(controller.controller).to eq("blkio")
125
+ expect(controller.original_path).to eq(relative_path)
126
+
127
+ controller = controllers["cpuset"]
128
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
129
+ expect(controller.controller).to eq("cpuset")
130
+ expect(controller.original_path).to eq(relative_path)
131
+
132
+ controller = controllers["name=openrc"]
133
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
134
+ expect(controller.controller).to eq("name=openrc")
135
+ expect(controller.original_path).to eq("/docker")
18
136
  end
19
137
  end
20
138
 
21
- context "not all the file exist" do
139
+ context "method: controller_groups with override" do
22
140
  before do
23
- allow(::File).to receive(:exist?).with(subject::PROC_SELF_CGROUP_FILE).and_return(true)
24
- allow(::Dir).to receive(:exist?).with(subject::PROC_CGROUP_CPU_DIR).and_return(false)
25
- allow(::Dir).to receive(:exist?).with(subject::PROC_CGROUP_CPUACCT_DIR).and_return(true)
141
+ java.lang.System.setProperty("ls.cgroup.cpu.path.override", "/foo")
142
+ java.lang.System.setProperty("ls.cgroup.cpuacct.path.override", "/bar")
143
+ allow(IO).to receive(:readlines).with("/proc/self/cgroup").and_return(proc_self_cgroup_content)
26
144
  end
145
+ after do
146
+ java.lang.System.clearProperty("ls.cgroup.cpu.path.override")
147
+ java.lang.System.clearProperty("ls.cgroup.cpuacct.path.override")
148
+ end
149
+ it "returns overridden control groups" do
150
+ controllers = cgroup_resources.controller_groups
151
+ controller = controllers["cpuacct"]
152
+ expect(controller).to be_a(Cgroup::CpuAcctResource)
153
+ expect(controller.override.nil?).to be_falsey
154
+ expect(controller.base_path).to eq("/sys/fs/cgroup/cpuacct")
155
+ expect(controller.offset_path).to eq("/bar")
156
+ expect(controller.override).to be_a(Cgroup::Override)
157
+
158
+ controller = controllers["cpu"]
159
+ expect(controller).to be_a(Cgroup::CpuResource)
160
+ expect(controller.override.nil?).to be_falsey
161
+ expect(controller.base_path).to eq("/sys/fs/cgroup/cpu")
162
+ expect(controller.offset_path).to eq("/foo")
163
+ expect(controller.override).to be_a(Cgroup::Override)
27
164
 
28
- it "returns false" do
29
- expect(subject.are_cgroup_available?).to be_falsey
165
+ controller = controllers["cpuset"]
166
+ expect(controller).to be_a(Cgroup::UnimplementedResource)
167
+ expect(controller.controller).to eq("cpuset")
168
+ expect(controller.original_path).to eq(relative_path)
30
169
  end
31
170
  end
32
171
  end
33
172
 
34
- context ".control_groups" do
35
- let(:proc_self_cgroup_content) {
36
- %w(14:name=systemd,holaunlimited:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
37
- 13:pids:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
38
- 12:hugetlb:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
39
- 11:net_prio:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
40
- 10:perf_event:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
41
- 9:net_cls:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
42
- 8:freezer:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
43
- 7:devices:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
44
- 6:memory:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
45
- 5:blkio:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
46
- 4:cpuacct:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
47
- 3:cpu:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
48
- 2:cpuset:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
49
- 1:name=openrc:/docker) }
50
-
51
- before do
52
- allow(subject).to receive(:read_proc_self_cgroup_lines).and_return(proc_self_cgroup_content)
173
+ describe Cgroup::CpuAcctResource do
174
+ subject(:cpuacct_resource) { described_class.new("/bar") }
175
+ describe "method: to_hash, without override" do
176
+ context "when the files cannot be found" do
177
+ it "fills in the hash with minus one" do
178
+ expect(cpuacct_resource.base_path).to eq("/sys/fs/cgroup/cpuacct")
179
+ expect(cpuacct_resource.offset_path).to eq("/bar")
180
+ expect(cpuacct_resource.to_hash).to eq({:control_group=>"/bar", :usage_nanos=>-1})
181
+ end
182
+ end
183
+ end
184
+ describe "method: to_hash, with override" do
185
+ before do
186
+ java.lang.System.setProperty("ls.cgroup.cpuacct.path.override", "/quux")
187
+ end
188
+ after do
189
+ java.lang.System.clearProperty("ls.cgroup.cpuacct.path.override")
190
+ end
191
+ context "when the files cannot be found" do
192
+ it "fills in the hash with minus one" do
193
+ expect(cpuacct_resource.base_path).to eq("/sys/fs/cgroup/cpuacct")
194
+ expect(cpuacct_resource.offset_path).to eq("/quux")
195
+ expect(cpuacct_resource.to_hash).to eq({:control_group=>"/quux", :usage_nanos=>-1})
196
+ end
197
+ end
53
198
  end
199
+ end
54
200
 
55
- it "returns the control groups" do
56
- expect(subject.control_groups).to match({
57
- "name=systemd" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
58
- "holaunlimited" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
59
- "pids" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
60
- "hugetlb" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
61
- "net_prio" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
62
- "perf_event" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
63
- "net_cls" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
64
- "freezer" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
65
- "devices" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
66
- "memory" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
67
- "blkio" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
68
- "cpuacct" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
69
- "cpu" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
70
- "cpuset" => "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61",
71
- "name=openrc" => "/docker"
72
- })
201
+ describe Cgroup::CpuResource do
202
+ subject(:cpu_resource) { described_class.new("/bar") }
203
+ describe "method: fill, without override" do
204
+ context "when the files cannot be found" do
205
+ it "fills in the hash with minus one" do
206
+ expect(cpu_resource.base_path).to eq("/sys/fs/cgroup/cpu")
207
+ expect(cpu_resource.offset_path).to eq("/bar")
208
+ expect(cpu_resource.to_hash).to eq({:cfs_period_micros=>-1, :cfs_quota_micros=>-1, :control_group=>"/bar", :stat=>{:number_of_elapsed_periods=>-1, :number_of_times_throttled=>-1, :time_throttled_nanos=>-1}})
209
+ end
210
+ end
211
+ end
212
+ describe "method: fill, with override" do
213
+ before do
214
+ java.lang.System.setProperty("ls.cgroup.cpu.path.override", "/quux")
215
+ end
216
+ after do
217
+ java.lang.System.clearProperty("ls.cgroup.cpu.path.override")
218
+ end
219
+ let(:target) { Hash.new }
220
+ context "when the files cannot be found" do
221
+ it "fills in the hash with minus one" do
222
+ expect(cpu_resource.base_path).to eq("/sys/fs/cgroup/cpu")
223
+ expect(cpu_resource.offset_path).to eq("/quux")
224
+ expect(cpu_resource.to_hash).to eq({:cfs_period_micros=>-1, :cfs_quota_micros=>-1, :control_group=>"/quux", :stat=>{:number_of_elapsed_periods=>-1, :number_of_times_throttled=>-1, :time_throttled_nanos=>-1}})
225
+ end
226
+ end
73
227
  end
74
228
  end
75
229
 
76
- context ".get_all" do
77
- context "when we can retrieve the stats" do
78
- let(:cpuacct_control_group) { "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61" }
230
+ describe Cgroup do
231
+ describe "class method: get_all" do
79
232
  let(:cpuacct_usage) { 1982 }
80
- let(:cpu_control_group) { "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61" }
81
233
  let(:cfs_period_micros) { 500 }
82
234
  let(:cfs_quota_micros) { 98 }
83
235
  let(:cpu_stats_number_of_periods) { 1 }
84
236
  let(:cpu_stats_number_of_time_throttled) { 2 }
85
237
  let(:cpu_stats_time_throttled_nanos) { 3 }
86
- let(:proc_self_cgroup_content) {
87
- %W(14:name=systemd,holaunlimited:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
88
- 13:pids:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
89
- 12:hugetlb:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
90
- 11:net_prio:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
91
- 10:perf_event:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
92
- 9:net_cls:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
93
- 8:freezer:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
94
- 7:devices:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
95
- 6:memory:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
96
- 5:blkio:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
97
- 4:cpuacct:#{cpuacct_control_group}
98
- 3:cpu:#{cpu_control_group}
99
- 2:cpuset:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
100
- 1:name=openrc:/docker) }
101
- let(:cpu_stat_file_content) {
102
- [
103
- "nr_periods #{cpu_stats_number_of_periods}",
104
- "nr_throttled #{cpu_stats_number_of_time_throttled}",
105
- "throttled_time #{cpu_stats_time_throttled_nanos}"
106
- ]
107
- }
108
-
238
+ let(:cpu_stat_file_content) do
239
+ ["nr_periods #{cpu_stats_number_of_periods}", "nr_throttled #{cpu_stats_number_of_time_throttled}", "throttled_time #{cpu_stats_time_throttled_nanos}"]
240
+ end
109
241
  before do
110
- allow(subject).to receive(:read_proc_self_cgroup_lines).and_return(proc_self_cgroup_content)
111
- allow(subject).to receive(:read_sys_fs_cgroup_cpuacct_cpu_stat).and_return(cpu_stat_file_content)
112
-
113
- allow(subject).to receive(:cgroup_cpuacct_usage_nanos).with(cpuacct_control_group).and_return(cpuacct_usage)
114
- allow(subject).to receive(:cgroup_cpu_fs_period_micros).with(cpu_control_group).and_return(cfs_period_micros)
115
- allow(subject).to receive(:cgroup_cpu_fs_quota_micros).with(cpu_control_group).and_return(cfs_quota_micros)
242
+ allow(::File).to receive(:exist?).and_return(true)
243
+ allow(IO).to receive(:readlines).with("/sys/fs/cgroup/cpuacct#{relative_path}/cpuacct.usage").and_return([cpuacct_usage])
244
+ allow(IO).to receive(:readlines).with("/sys/fs/cgroup/cpu#{relative_path}/cpu.cfs_period_us").and_return([cfs_period_micros])
245
+ allow(IO).to receive(:readlines).with("/sys/fs/cgroup/cpu#{relative_path}/cpu.cfs_quota_us").and_return([cfs_quota_micros])
246
+ allow(IO).to receive(:readlines).with("/sys/fs/cgroup/cpu#{relative_path}/cpu.stat").and_return(cpu_stat_file_content)
247
+ allow(IO).to receive(:readlines).with("/proc/self/cgroup").and_return(proc_self_cgroup_content)
116
248
  end
117
-
118
249
  it "returns all the stats" do
119
- expect(subject.get_all).to match(
250
+ expect(described_class.get_all).to match(
120
251
  :cpuacct => {
121
- :control_group => cpuacct_control_group,
252
+ :control_group => relative_path,
122
253
  :usage_nanos => cpuacct_usage,
123
254
  },
124
255
  :cpu => {
125
- :control_group => cpu_control_group,
256
+ :control_group => relative_path,
126
257
  :cfs_period_micros => cfs_period_micros,
127
258
  :cfs_quota_micros => cfs_quota_micros,
128
259
  :stat => {
@@ -137,12 +268,14 @@ describe LogStash::Instrument::PeriodicPoller::Cgroup do
137
268
 
138
269
  context "when an exception is raised" do
139
270
  before do
140
- allow(subject).to receive(:control_groups).and_raise("Something went wrong")
271
+ allow(::File).to receive(:exist?).and_return(true)
272
+ allow(Cgroup::CGROUP_RESOURCES).to receive(:controller_groups).and_raise("Something went wrong")
141
273
  end
142
274
 
143
- it "returns nil" do
144
- expect(subject.get_all).to be_nil
275
+ it "method: get_all returns nil" do
276
+ expect(described_class.get_all).to be_nil
145
277
  end
146
278
  end
147
279
  end
148
280
  end
281
+ end end end
@@ -12,46 +12,43 @@ describe LogStash::Instrument::PeriodicPoller::Os do
12
12
  let(:snapshot_store) { metric.collector.snapshot_metric.metric_store }
13
13
  let(:os_metrics) { snapshot_store.get_shallow(:os) }
14
14
 
15
- let(:cpuacct_control_group) { "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61" }
15
+ let(:relative_path) { "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61" }
16
+ let(:proc_self_cgroup_content) do
17
+ %W(14:name=systemd,holaunlimited:#{relative_path}
18
+ 13:pids:#{relative_path}
19
+ 12:hugetlb:#{relative_path}
20
+ 11:net_prio:#{relative_path}
21
+ 10:perf_event:#{relative_path}
22
+ 9:net_cls:#{relative_path}
23
+ 8:freezer:#{relative_path}
24
+ 7:devices:#{relative_path}
25
+ 6:memory:#{relative_path}
26
+ 5:blkio:#{relative_path}
27
+ 4:cpuacct:#{relative_path}
28
+ 3:cpu:#{relative_path}
29
+ 2:cpuset:#{relative_path}
30
+ 1:name=openrc:/docker
31
+ 0::/docker)
32
+ end
33
+
16
34
  let(:cpuacct_usage) { 1982 }
17
- let(:cpu_control_group) { "/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61" }
18
35
  let(:cpu_period_micros) { 500 }
19
36
  let(:cpu_quota_micros) { 98 }
20
37
  let(:cpu_stats_number_of_periods) { 1 }
21
38
  let(:cpu_stats_number_of_time_throttled) { 2 }
22
39
  let(:cpu_stats_time_throttled_nanos) { 3 }
23
- let(:proc_self_cgroup_content) {
24
- %W(14:name=systemd,holaunlimited:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
25
- 13:pids:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
26
- 12:hugetlb:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
27
- 11:net_prio:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
28
- 10:perf_event:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
29
- 9:net_cls:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
30
- 8:freezer:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
31
- 7:devices:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
32
- 6:memory:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
33
- 5:blkio:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
34
- 4:cpuacct:#{cpuacct_control_group}
35
- 3:cpu:#{cpu_control_group}
36
- 2:cpuset:/docker/a10687343f90e97bbb1f7181bd065a42de96c40c4aa91764a9d526ea30475f61
37
- 1:name=openrc:/docker) }
38
- let(:cpu_stat_file_content) {
39
- [
40
- "nr_periods #{cpu_stats_number_of_periods}",
41
- "nr_throttled #{cpu_stats_number_of_time_throttled}",
42
- "throttled_time #{cpu_stats_time_throttled_nanos}"
43
- ]
44
- }
45
-
46
- before do
47
- allow(LogStash::Instrument::PeriodicPoller::Cgroup).to receive(:are_cgroup_available?).and_return(true)
48
40
 
49
- allow(LogStash::Instrument::PeriodicPoller::Cgroup).to receive(:read_proc_self_cgroup_lines).and_return(proc_self_cgroup_content)
50
- allow(LogStash::Instrument::PeriodicPoller::Cgroup).to receive(:read_sys_fs_cgroup_cpuacct_cpu_stat).and_return(cpu_stat_file_content)
41
+ let(:cpu_stat_file_content) do
42
+ ["nr_periods #{cpu_stats_number_of_periods}", "nr_throttled #{cpu_stats_number_of_time_throttled}", "throttled_time #{cpu_stats_time_throttled_nanos}"]
43
+ end
51
44
 
52
- allow(LogStash::Instrument::PeriodicPoller::Cgroup).to receive(:cgroup_cpuacct_usage_nanos).with(cpuacct_control_group).and_return(cpuacct_usage)
53
- allow(LogStash::Instrument::PeriodicPoller::Cgroup).to receive(:cgroup_cpu_fs_period_micros).with(cpu_control_group).and_return(cpu_period_micros)
54
- allow(LogStash::Instrument::PeriodicPoller::Cgroup).to receive(:cgroup_cpu_fs_quota_micros).with(cpu_control_group).and_return(cpu_quota_micros)
45
+ before do
46
+ allow(::File).to receive(:exist?).and_return(true)
47
+ allow(IO).to receive(:readlines).with("/sys/fs/cgroup/cpuacct#{relative_path}/cpuacct.usage").and_return([cpuacct_usage])
48
+ allow(IO).to receive(:readlines).with("/sys/fs/cgroup/cpu#{relative_path}/cpu.cfs_period_us").and_return([cpu_period_micros])
49
+ allow(IO).to receive(:readlines).with("/sys/fs/cgroup/cpu#{relative_path}/cpu.cfs_quota_us").and_return([cpu_quota_micros])
50
+ allow(IO).to receive(:readlines).with("/sys/fs/cgroup/cpu#{relative_path}/cpu.stat").and_return(cpu_stat_file_content)
51
+ allow(IO).to receive(:readlines).with("/proc/self/cgroup").and_return(proc_self_cgroup_content)
55
52
 
56
53
  subject.collect
57
54
  end
@@ -1,6 +1,6 @@
1
1
  ---
2
- logstash: 5.6.12
3
- logstash-core: 5.6.12
2
+ logstash: 5.6.13
3
+ logstash-core: 5.6.13
4
4
  logstash-core-plugin-api: 2.1.29
5
5
 
6
6
  # Note: this file is copied to the root of logstash-core because its gemspec needs it when
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.12
4
+ version: 5.6.13
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-10 00:00:00.000000000 Z
11
+ date: 2018-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement