logstash-core 5.0.0.alpha5.snapshot1-java → 5.0.0.alpha6.snapshot1-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.

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