logstash-core 5.0.0.alpha5.snapshot1-java → 5.0.0.alpha6.snapshot1-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of logstash-core might be problematic. Click here for more details.

Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core/version.rb +1 -1
  3. data/lib/logstash/agent.rb +1 -1
  4. data/lib/logstash/api/commands/default_metadata.rb +1 -1
  5. data/lib/logstash/api/commands/hot_threads_reporter.rb +4 -7
  6. data/lib/logstash/api/commands/node.rb +5 -4
  7. data/lib/logstash/api/commands/stats.rb +8 -3
  8. data/lib/logstash/api/modules/base.rb +5 -0
  9. data/lib/logstash/api/modules/node.rb +1 -2
  10. data/lib/logstash/api/modules/node_stats.rb +1 -2
  11. data/lib/logstash/codecs/base.rb +29 -1
  12. data/lib/logstash/config/mixin.rb +1 -1
  13. data/lib/logstash/environment.rb +5 -5
  14. data/lib/logstash/filter_delegator.rb +4 -5
  15. data/lib/logstash/instrument/periodic_poller/jvm.rb +43 -10
  16. data/lib/logstash/output_delegator.rb +33 -168
  17. data/lib/logstash/output_delegator_strategies/legacy.rb +29 -0
  18. data/lib/logstash/output_delegator_strategies/shared.rb +20 -0
  19. data/lib/logstash/output_delegator_strategies/single.rb +23 -0
  20. data/lib/logstash/output_delegator_strategy_registry.rb +36 -0
  21. data/lib/logstash/outputs/base.rb +39 -26
  22. data/lib/logstash/patches/clamp.rb +6 -0
  23. data/lib/logstash/pipeline.rb +42 -14
  24. data/lib/logstash/pipeline_reporter.rb +2 -8
  25. data/lib/logstash/plugin.rb +6 -10
  26. data/lib/logstash/runner.rb +12 -9
  27. data/lib/logstash/settings.rb +124 -21
  28. data/lib/logstash/util/wrapped_synchronous_queue.rb +17 -1
  29. data/lib/logstash/version.rb +1 -1
  30. data/lib/logstash/webserver.rb +44 -33
  31. data/locales/en.yml +5 -1
  32. data/logstash-core.gemspec +2 -2
  33. data/spec/api/lib/api/node_spec.rb +62 -10
  34. data/spec/api/lib/api/node_stats_spec.rb +16 -3
  35. data/spec/api/lib/api/support/resource_dsl_methods.rb +11 -1
  36. data/spec/api/spec_helper.rb +1 -1
  37. data/spec/conditionals_spec.rb +12 -1
  38. data/spec/logstash/agent_spec.rb +3 -0
  39. data/spec/logstash/codecs/base_spec.rb +74 -0
  40. data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +37 -10
  41. data/spec/logstash/output_delegator_spec.rb +64 -89
  42. data/spec/logstash/outputs/base_spec.rb +91 -15
  43. data/spec/logstash/pipeline_reporter_spec.rb +1 -6
  44. data/spec/logstash/pipeline_spec.rb +20 -22
  45. data/spec/logstash/plugin_spec.rb +3 -3
  46. data/spec/logstash/runner_spec.rb +86 -3
  47. data/spec/logstash/settings/integer_spec.rb +20 -0
  48. data/spec/logstash/settings/numeric_spec.rb +28 -0
  49. data/spec/logstash/settings/port_range_spec.rb +93 -0
  50. data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +6 -0
  51. data/spec/logstash/webserver_spec.rb +95 -0
  52. metadata +20 -6
@@ -2,9 +2,9 @@
2
2
  require "spec_helper"
3
3
 
4
4
  # use a dummy NOOP output to test Outputs::Base
5
- class LogStash::Outputs::NOOP < LogStash::Outputs::Base
5
+ class LogStash::Outputs::NOOPSingle < LogStash::Outputs::Base
6
6
  config_name "noop"
7
- milestone 2
7
+ concurrency :single
8
8
 
9
9
  config :dummy_option, :validate => :string
10
10
 
@@ -15,26 +15,102 @@ class LogStash::Outputs::NOOP < LogStash::Outputs::Base
15
15
  end
16
16
  end
17
17
 
18
- class LogStash::Outputs::NOOPLegacyNoWorkers < ::LogStash::Outputs::Base
19
- LEGACY_WORKERS_NOT_SUPPORTED_REASON = "legacy reason"
18
+ class LogStash::Outputs::NOOPShared < ::LogStash::Outputs::Base
19
+ concurrency :shared
20
+
21
+ def register; end
22
+ end
23
+
24
+ class LogStash::Outputs::NOOPLegacy < ::LogStash::Outputs::Base
25
+ def register; end
26
+ end
20
27
 
21
- def register
22
- workers_not_supported(LEGACY_WORKERS_NOT_SUPPORTED_REASON)
28
+ class LogStash::Outputs::NOOPMultiReceiveEncoded < ::LogStash::Outputs::Base
29
+ concurrency :single
30
+
31
+ def register; end
32
+
33
+ def multi_receive_encoded(events_and_encoded)
23
34
  end
24
35
  end
25
36
 
37
+
26
38
  describe "LogStash::Outputs::Base#new" do
27
- it "should instantiate cleanly" do
28
- params = { "dummy_option" => "potatoes", "codec" => "json", "workers" => 2 }
29
- worker_params = params.dup; worker_params["workers"] = 1
39
+ let(:params) { {} }
40
+ subject(:instance) { klass.new(params.dup) }
41
+
42
+ context "single" do
43
+ let(:klass) { LogStash::Outputs::NOOPSingle }
44
+
45
+ it "should instantiate cleanly" do
46
+ params = { "dummy_option" => "potatoes", "codec" => "json", "workers" => 2 }
47
+ worker_params = params.dup; worker_params["workers"] = 1
48
+
49
+ expect{ subject }.not_to raise_error
50
+ end
30
51
 
31
- expect do
32
- LogStash::Outputs::NOOP.new(params.dup)
33
- end.not_to raise_error
52
+ it "should set concurrency correctly" do
53
+ expect(subject.concurrency).to eq(:single)
54
+ end
34
55
  end
35
56
 
36
- it "should move workers_not_supported declarations up to the class level" do
37
- LogStash::Outputs::NOOPLegacyNoWorkers.new.register
38
- expect(LogStash::Outputs::NOOPLegacyNoWorkers.workers_not_supported?).to eql(true)
57
+ context "shared" do
58
+ let(:klass) { LogStash::Outputs::NOOPShared }
59
+
60
+ it "should set concurrency correctly" do
61
+ expect(subject.concurrency).to eq(:shared)
62
+ end
63
+ end
64
+
65
+ context "legacy" do
66
+ let(:klass) { LogStash::Outputs::NOOPLegacy }
67
+
68
+ it "should set concurrency correctly" do
69
+ expect(subject.concurrency).to eq(:legacy)
70
+ end
71
+
72
+ it "should default the # of workers to 1" do
73
+ expect(subject.workers).to eq(1)
74
+ end
75
+
76
+ it "should default concurrency to :legacy" do
77
+ expect(subject.concurrency).to eq(:legacy)
78
+ end
79
+ end
80
+
81
+ describe "dispatching multi_receive" do
82
+ let(:event) { double("event") }
83
+ let(:events) { [event] }
84
+
85
+ context "with multi_receive_encoded" do
86
+ let(:klass) { LogStash::Outputs::NOOPMultiReceiveEncoded }
87
+ let(:codec) { double("codec") }
88
+ let(:encoded) { double("encoded") }
89
+
90
+ before do
91
+ allow(codec).to receive(:multi_encode).with(events).and_return(encoded)
92
+ allow(instance).to receive(:codec).and_return(codec)
93
+ allow(instance).to receive(:multi_receive_encoded)
94
+ instance.multi_receive(events)
95
+ end
96
+
97
+ it "should invoke multi_receive_encoded if it exists" do
98
+ expect(instance).to have_received(:multi_receive_encoded).with(encoded)
99
+ end
100
+ end
101
+
102
+ context "with plain #receive" do
103
+ let(:klass) { LogStash::Outputs::NOOPSingle }
104
+
105
+ before do
106
+ allow(instance).to receive(:multi_receive).and_call_original
107
+ allow(instance).to receive(:receive).with(event)
108
+ instance.multi_receive(events)
109
+ end
110
+
111
+ it "should receive the event by itself" do
112
+ expect(instance).to have_received(:receive).with(event)
113
+ end
114
+ end
39
115
  end
40
116
  end
@@ -43,6 +43,7 @@ describe LogStash::PipelineReporter do
43
43
  allow(LogStash::Plugin).to receive(:lookup).with("codec", "plain").and_call_original
44
44
 
45
45
  @pre_snapshot = reporter.snapshot
46
+
46
47
  pipeline.run
47
48
  @post_snapshot = reporter.snapshot
48
49
  end
@@ -80,10 +81,4 @@ describe LogStash::PipelineReporter do
80
81
  expect(@post_snapshot.inflight_count).to eql(0)
81
82
  end
82
83
  end
83
-
84
- describe "output states" do
85
- it "should include the count of received events" do
86
- expect(@post_snapshot.output_info.first[:events_received]).to eql(generator_count)
87
- end
88
- end
89
84
  end
@@ -235,31 +235,21 @@ describe LogStash::Pipeline do
235
235
  }
236
236
 
237
237
  context "output close" do
238
- it "should call close of output without output-workers" do
239
- pipeline = TestPipeline.new(test_config_without_output_workers)
240
- pipeline.run
238
+ let(:pipeline) { TestPipeline.new(test_config_without_output_workers) }
239
+ let(:output) { pipeline.outputs.first }
241
240
 
242
- expect(pipeline.outputs.size ).to eq(1)
243
- expect(pipeline.outputs.first.workers.size ).to eq(::LogStash::SETTINGS.get("pipeline.output.workers"))
244
- expect(pipeline.outputs.first.workers.first.num_closes ).to eq(1)
245
- pipeline.shutdown
241
+ before do
242
+ allow(output).to receive(:do_close)
246
243
  end
247
244
 
248
- it "should call output close correctly with output workers" do
249
- pipeline = TestPipeline.new(test_config_with_output_workers)
245
+ after do
246
+ pipeline.shutdown
247
+ end
248
+
249
+ it "should call close of output without output-workers" do
250
250
  pipeline.run
251
251
 
252
- expect(pipeline.outputs.size ).to eq(1)
253
- # We even close the parent output worker, even though it doesn't receive messages
254
-
255
- output_delegator = pipeline.outputs.first
256
- output = output_delegator.workers.first
257
-
258
- expect(output.num_closes).to eq(1)
259
- output_delegator.workers.each do |plugin|
260
- expect(plugin.num_closes ).to eq(1)
261
- end
262
- pipeline.shutdown
252
+ expect(output).to have_received(:do_close).once
263
253
  end
264
254
  end
265
255
  end
@@ -604,7 +594,13 @@ describe LogStash::Pipeline do
604
594
 
605
595
  Thread.new { subject.run }
606
596
  # make sure we have received all the generated events
607
- sleep 0.25 while dummyoutput.events.size < number_of_events
597
+
598
+ times = 0
599
+ while dummyoutput.events.size < number_of_events
600
+ times += 1
601
+ sleep 0.25
602
+ raise "Waited too long" if times > 4
603
+ end
608
604
  end
609
605
 
610
606
  after :each do
@@ -615,6 +611,7 @@ describe LogStash::Pipeline do
615
611
  let(:collected_metric) { metric_store.get_with_path("stats/events") }
616
612
 
617
613
  it "populates the different metrics" do
614
+ expect(collected_metric[:stats][:events][:duration_in_millis].value).not_to be_nil
618
615
  expect(collected_metric[:stats][:events][:in].value).to eq(number_of_events)
619
616
  expect(collected_metric[:stats][:events][:filtered].value).to eq(number_of_events)
620
617
  expect(collected_metric[:stats][:events][:out].value).to eq(number_of_events)
@@ -625,6 +622,7 @@ describe LogStash::Pipeline do
625
622
  let(:collected_metric) { metric_store.get_with_path("stats/pipelines/") }
626
623
 
627
624
  it "populates the pipelines core metrics" do
625
+ expect(collected_metric[:stats][:pipelines][:main][:events][:duration_in_millis].value).not_to be_nil
628
626
  expect(collected_metric[:stats][:pipelines][:main][:events][:in].value).to eq(number_of_events)
629
627
  expect(collected_metric[:stats][:pipelines][:main][:events][:filtered].value).to eq(number_of_events)
630
628
  expect(collected_metric[:stats][:pipelines][:main][:events][:out].value).to eq(number_of_events)
@@ -640,7 +638,7 @@ describe LogStash::Pipeline do
640
638
  end
641
639
 
642
640
  it "populates the output metrics" do
643
- plugin_name = "dummyoutput_#{dummy_output_id}".to_sym
641
+ plugin_name = dummy_output_id.to_sym
644
642
  expect(collected_metric[:stats][:pipelines][:main][:plugins][:outputs][plugin_name][:events][:out].value).to eq(number_of_events)
645
643
  end
646
644
  end
@@ -236,7 +236,7 @@ describe LogStash::Plugin do
236
236
  end
237
237
  end
238
238
 
239
- describe "#plugin_unique_name" do
239
+ describe "#id" do
240
240
  let(:plugin) do
241
241
  Class.new(LogStash::Filters::Base,) do
242
242
  config_name "simple_plugin"
@@ -258,7 +258,7 @@ describe LogStash::Plugin do
258
258
  subject { plugin.new(config) }
259
259
 
260
260
  it "return a human readable ID" do
261
- expect(subject.plugin_unique_name).to eq("simple_plugin_#{my_id}")
261
+ expect(subject.id).to eq(my_id)
262
262
  end
263
263
  end
264
264
 
@@ -266,7 +266,7 @@ describe LogStash::Plugin do
266
266
  subject { plugin.new(config) }
267
267
 
268
268
  it "return a human readable ID" do
269
- expect(subject.plugin_unique_name).to match(/^simple_plugin_/)
269
+ expect(subject.id).to match(/^simple_plugin_/)
270
270
  end
271
271
  end
272
272
  end
@@ -189,21 +189,86 @@ describe LogStash::Runner do
189
189
  allow(pipeline).to receive(:shutdown)
190
190
  end
191
191
 
192
+ context "when :http.host is defined by the user" do
193
+ it "should pass the value to the webserver" do
194
+ expect(LogStash::Agent).to receive(:new) do |settings|
195
+ expect(settings.set?("http.host")).to be(true)
196
+ expect(settings.get("http.host")).to eq("localhost")
197
+ end
198
+
199
+ args = ["--http.host", "localhost", "-e", pipeline_string]
200
+ subject.run("bin/logstash", args)
201
+ end
202
+ end
203
+
204
+ context "when :http.host is not defined by the user" do
205
+ it "should pass the value to the webserver" do
206
+ expect(LogStash::Agent).to receive(:new) do |settings|
207
+ expect(settings.set?("http.host")).to be_falsey
208
+ expect(settings.get("http.host")).to eq("127.0.0.1")
209
+ end
210
+
211
+ args = ["-e", pipeline_string]
212
+ subject.run("bin/logstash", args)
213
+ end
214
+ end
215
+
216
+ context "when :http.port is defined by the user" do
217
+ it "should pass a single value to the webserver" do
218
+ expect(LogStash::Agent).to receive(:new) do |settings|
219
+ expect(settings.set?("http.port")).to be(true)
220
+ expect(settings.get("http.port")).to eq(10000..10000)
221
+ end
222
+
223
+ args = ["--http.port", "10000", "-e", pipeline_string]
224
+ subject.run("bin/logstash", args)
225
+ end
226
+
227
+ it "should pass a range value to the webserver" do
228
+ expect(LogStash::Agent).to receive(:new) do |settings|
229
+ expect(settings.set?("http.port")).to be(true)
230
+ expect(settings.get("http.port")).to eq(10000..20000)
231
+ end
232
+
233
+ args = ["--http.port", "10000-20000", "-e", pipeline_string]
234
+ subject.run("bin/logstash", args)
235
+ end
236
+ end
237
+
238
+ context "when no :http.port is not defined by the user" do
239
+ it "should use the default settings" do
240
+ expect(LogStash::Agent).to receive(:new) do |settings|
241
+ expect(settings.set?("http.port")).to be_falsey
242
+ expect(settings.get("http.port")).to eq(9600..9700)
243
+ end
244
+
245
+ args = ["-e", pipeline_string]
246
+ subject.run("bin/logstash", args)
247
+ end
248
+ end
249
+
192
250
  context "when :pipeline_workers is not defined by the user" do
193
251
  it "should not pass the value to the pipeline" do
194
252
  expect(LogStash::Agent).to receive(:new) do |settings|
195
- expect(settings.set?("pipeline.workers")).to be(false)
253
+ expect(settings.set?("pipeline.workers")).to be(false)
196
254
  end
197
255
  args = ["-e", pipeline_string]
198
256
  subject.run("bin/logstash", args)
199
257
  end
200
258
  end
201
259
 
260
+ context "when :pipeline_workers flag is passed without a value" do
261
+ it "should raise an error" do
262
+ args = ["-e", pipeline_string, "-w"]
263
+ expect { subject.run("bin/logstash", args) }.to raise_error
264
+ end
265
+ end
266
+
202
267
  context "when :pipeline_workers is defined by the user" do
203
268
  it "should pass the value to the pipeline" do
204
269
  expect(LogStash::Agent).to receive(:new) do |settings|
205
- expect(settings.set?("pipeline.workers")).to be(true)
206
- expect(settings.get("pipeline.workers")).to be(2)
270
+ expect(settings.set?("pipeline.workers")).to be(true)
271
+ expect(settings.get("pipeline.workers")).to be(2)
207
272
  end
208
273
 
209
274
  args = ["-w", "2", "-e", pipeline_string]
@@ -264,4 +329,22 @@ describe LogStash::Runner do
264
329
  end
265
330
  end
266
331
 
332
+ describe "path.settings" do
333
+ subject { LogStash::Runner.new("") }
334
+ context "if does not exist" do
335
+ let(:args) { ["--path.settings", "/tmp/a/a/a/a", "-e", "input {} output {}"] }
336
+
337
+ it "should terminate logstash" do
338
+ expect(subject.run(args)).to eq(1)
339
+ end
340
+
341
+ context "but if --help is passed" do
342
+ let(:args) { ["--path.settings", "/tmp/a/a/a/a", "--help"] }
343
+
344
+ it "should show help" do
345
+ expect { subject.run(args) }.to raise_error(Clamp::HelpWanted)
346
+ end
347
+ end
348
+ end
349
+ end
267
350
  end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/settings"
4
+
5
+ describe LogStash::Setting::Integer do
6
+ subject { described_class.new("a number", nil, false) }
7
+ describe "#set" do
8
+ context "when giving a number which is not an integer" do
9
+ it "should raise an exception" do
10
+ expect { subject.set(1.1) }.to raise_error(ArgumentError)
11
+ end
12
+ end
13
+ context "when giving a number which is an integer" do
14
+ it "should set the number" do
15
+ expect { subject.set(100) }.to_not raise_error
16
+ expect(subject.value).to eq(100)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/settings"
4
+
5
+ describe LogStash::Setting::Numeric do
6
+ subject { described_class.new("a number", nil, false) }
7
+ describe "#set" do
8
+ context "when giving a string which doesn't represent a string" do
9
+ it "should raise an exception" do
10
+ expect { subject.set("not-a-number") }.to raise_error(ArgumentError)
11
+ end
12
+ end
13
+ context "when giving a string which represents a " do
14
+ context "float" do
15
+ it "should coerce that string to the number" do
16
+ subject.set("1.1")
17
+ expect(subject.value).to eq(1.1)
18
+ end
19
+ end
20
+ context "int" do
21
+ it "should coerce that string to the number" do
22
+ subject.set("1")
23
+ expect(subject.value).to eq(1)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+ #
3
+ require "logstash/settings"
4
+ require "spec_helper"
5
+
6
+ describe LogStash::Setting::PortRange do
7
+
8
+ context "When the value is a Fixnum" do
9
+ subject { LogStash::Setting::PortRange.new("mynewtest", 9000) }
10
+
11
+ it "coerces the value in a range" do
12
+ expect { subject }.not_to raise_error
13
+ end
14
+
15
+ it "returns a range" do
16
+ expect(subject.value).to eq(9000..9000)
17
+ end
18
+
19
+ it "can update the range" do
20
+ subject.set(10000)
21
+ expect(subject.value).to eq(10000..10000)
22
+ end
23
+ end
24
+
25
+ context "When the value is a string" do
26
+ subject { LogStash::Setting::PortRange.new("mynewtest", "9000-10000") }
27
+
28
+ it "coerces a string range with the format (9000-10000)" do
29
+ expect { subject }.not_to raise_error
30
+ end
31
+
32
+ it "refuses when then upper port is out of range" do
33
+ expect { LogStash::Setting::PortRange.new("mynewtest", "1000-95000") }.to raise_error
34
+ end
35
+
36
+ it "returns a range" do
37
+ expect(subject.value).to eq(9000..10000)
38
+ end
39
+
40
+ it "can update the range" do
41
+ subject.set("500-1000")
42
+ expect(subject.value).to eq(500..1000)
43
+ end
44
+ end
45
+
46
+ context "when the value is a garbage string" do
47
+ subject { LogStash::Setting::PortRange.new("mynewtest", "fsdfnsdkjnfjs") }
48
+
49
+ it "raises an argument error" do
50
+ expect { subject }.to raise_error
51
+ end
52
+
53
+
54
+ it "raises an exception on update" do
55
+ expect { LogStash::Setting::PortRange.new("mynewtest", 10000).set("dsfnsdknfksdnfjksdnfjns") }.to raise_error
56
+ end
57
+ end
58
+
59
+ context "when the value is an unkown type" do
60
+ subject { LogStash::Setting::PortRange.new("mynewtest", 0.1) }
61
+
62
+
63
+ it "raises an argument error" do
64
+ expect { subject }.to raise_error
65
+ end
66
+
67
+
68
+ it "raises an exception on update" do
69
+ expect { LogStash::Setting::PortRange.new("mynewtest", 10000).set(0.1) }.to raise_error
70
+ end
71
+ end
72
+
73
+ context "When value is a range" do
74
+ subject { LogStash::Setting::PortRange.new("mynewtest", 9000..10000) }
75
+
76
+ it "accepts a ruby range as the default value" do
77
+ expect { subject }.not_to raise_error
78
+ end
79
+
80
+ it "can update the range" do
81
+ subject.set(500..1000)
82
+ expect(subject.value).to eq(500..1000)
83
+ end
84
+
85
+ it "refuses when then upper port is out of range" do
86
+ expect { LogStash::Setting::PortRange.new("mynewtest", 9000..1000000) }.to raise_error
87
+ end
88
+
89
+ it "raise an exception on when port are out of range" do
90
+ expect { LogStash::Setting::PortRange.new("mynewtest", -1000..1000) }.to raise_error
91
+ end
92
+ end
93
+ end