logstash-core 5.6.12-java → 5.6.13-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 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