logstash-core 6.0.0.alpha1-java → 6.0.0.alpha2-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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core/logstash-core.jar +0 -0
  3. data/lib/logstash-core/version.rb +1 -1
  4. data/lib/logstash/agent.rb +81 -45
  5. data/lib/logstash/api/commands/hot_threads_reporter.rb +3 -3
  6. data/lib/logstash/api/commands/node.rb +13 -6
  7. data/lib/logstash/api/commands/stats.rb +18 -6
  8. data/lib/logstash/api/modules/node.rb +7 -0
  9. data/lib/logstash/api/modules/node_stats.rb +12 -5
  10. data/lib/logstash/bootstrap_check/default_config.rb +3 -7
  11. data/lib/logstash/compiler.rb +33 -15
  12. data/lib/logstash/compiler/lscl.rb +16 -8
  13. data/lib/logstash/config/mixin.rb +5 -42
  14. data/lib/logstash/config/pipeline_config.rb +1 -1
  15. data/lib/logstash/config/source/local.rb +28 -13
  16. data/lib/logstash/config/source/multi_local.rb +72 -0
  17. data/lib/logstash/config/source_loader.rb +1 -2
  18. data/lib/logstash/environment.rb +12 -3
  19. data/lib/logstash/execution_context.rb +7 -3
  20. data/lib/logstash/inputs/base.rb +2 -0
  21. data/lib/logstash/instrument/metric_type.rb +0 -2
  22. data/lib/logstash/instrument/periodic_poller/jvm.rb +5 -5
  23. data/lib/logstash/instrument/periodic_poller/pq.rb +1 -1
  24. data/lib/logstash/outputs/base.rb +2 -0
  25. data/lib/logstash/pipeline.rb +31 -14
  26. data/lib/logstash/pipeline_action/create.rb +1 -2
  27. data/lib/logstash/pipeline_action/reload.rb +2 -1
  28. data/lib/logstash/pipeline_settings.rb +50 -0
  29. data/lib/logstash/plugin.rb +1 -0
  30. data/lib/logstash/runner.rb +7 -5
  31. data/lib/logstash/settings.rb +11 -3
  32. data/lib/logstash/shutdown_watcher.rb +26 -0
  33. data/lib/logstash/state_resolver.rb +1 -3
  34. data/lib/logstash/util/dead_letter_queue_manager.rb +61 -0
  35. data/lib/logstash/util/environment_variables.rb +43 -0
  36. data/lib/logstash/util/thread_dump.rb +3 -1
  37. data/lib/logstash/version.rb +1 -1
  38. data/locales/en.yml +4 -0
  39. data/logstash-core.gemspec +4 -1
  40. data/spec/logstash/agent/converge_spec.rb +36 -35
  41. data/spec/logstash/agent_spec.rb +48 -177
  42. data/spec/{api/lib/commands/stats.rb → logstash/api/commands/stats_spec.rb} +7 -2
  43. data/spec/{api/lib → logstash/api}/errors_spec.rb +1 -1
  44. data/spec/{api/lib/api → logstash/api/modules}/logging_spec.rb +1 -10
  45. data/spec/{api/lib/api → logstash/api/modules}/node_plugins_spec.rb +1 -2
  46. data/spec/{api/lib/api → logstash/api/modules}/node_spec.rb +9 -8
  47. data/spec/{api/lib/api → logstash/api/modules}/node_stats_spec.rb +11 -9
  48. data/spec/{api/lib/api → logstash/api/modules}/plugins_spec.rb +4 -3
  49. data/spec/{api/lib/api → logstash/api/modules}/root_spec.rb +2 -2
  50. data/spec/{api/lib → logstash/api}/rack_app_spec.rb +0 -0
  51. data/spec/logstash/compiler/compiler_spec.rb +72 -9
  52. data/spec/logstash/config/source/local_spec.rb +20 -4
  53. data/spec/logstash/config/source/multi_local_spec.rb +113 -0
  54. data/spec/logstash/execution_context_spec.rb +14 -4
  55. data/spec/logstash/inputs/base_spec.rb +1 -1
  56. data/spec/logstash/instrument/wrapped_write_client_spec.rb +34 -19
  57. data/spec/logstash/output_delegator_spec.rb +1 -1
  58. data/spec/logstash/outputs/base_spec.rb +1 -1
  59. data/spec/logstash/pipeline_action/reload_spec.rb +1 -1
  60. data/spec/logstash/pipeline_action/stop_spec.rb +1 -1
  61. data/spec/logstash/pipeline_dlq_commit_spec.rb +107 -0
  62. data/spec/logstash/pipeline_pq_file_spec.rb +3 -1
  63. data/spec/logstash/pipeline_reporter_spec.rb +2 -1
  64. data/spec/logstash/pipeline_spec.rb +54 -43
  65. data/spec/logstash/runner_spec.rb +27 -36
  66. data/spec/logstash/settings/array_coercible_spec.rb +65 -0
  67. data/spec/logstash/settings_spec.rb +91 -0
  68. data/spec/logstash/shutdown_watcher_spec.rb +10 -16
  69. data/spec/logstash/state_resolver_spec.rb +6 -4
  70. data/spec/support/helpers.rb +16 -3
  71. data/spec/support/shared_contexts.rb +26 -2
  72. metadata +42 -39
  73. data/lib/logstash/instrument/metric_type/mean.rb +0 -33
  74. data/spec/api/lib/api/support/resource_dsl_methods.rb +0 -87
  75. data/spec/api/spec_helper.rb +0 -106
@@ -1,28 +1,38 @@
1
1
  # encoding: utf-8
2
2
  require "spec_helper"
3
+ require "logstash/util/dead_letter_queue_manager"
3
4
  require "logstash/execution_context"
4
5
 
5
6
  describe LogStash::ExecutionContext do
6
7
  let(:pipeline) { double("pipeline") }
7
8
  let(:pipeline_id) { :main }
8
9
  let(:agent) { double("agent") }
9
-
10
+ let(:plugin_id) { "plugin_id" }
11
+ let(:plugin_type) { "plugin_type" }
12
+ let(:dlq_writer) { LogStash::Util::DummyDeadLetterQueueWriter.new }
13
+
10
14
  before do
11
15
  allow(pipeline).to receive(:agent).and_return(agent)
12
16
  allow(pipeline).to receive(:pipeline_id).and_return(pipeline_id)
13
17
  end
14
18
 
15
- subject { described_class.new(pipeline, agent) }
19
+ subject { described_class.new(pipeline, agent, plugin_id, plugin_type, dlq_writer) }
16
20
 
17
21
  it "returns the `pipeline_id`" do
18
22
  expect(subject.pipeline_id).to eq(pipeline_id)
19
23
  end
20
-
24
+
21
25
  it "returns the pipeline" do
22
26
  expect(subject.pipeline).to eq(pipeline)
23
27
  end
24
-
28
+
25
29
  it "returns the agent" do
26
30
  expect(subject.agent).to eq(agent)
27
31
  end
32
+
33
+ it "returns the plugin-specific dlq writer" do
34
+ expect(subject.dlq_writer.plugin_type).to eq(plugin_type)
35
+ expect(subject.dlq_writer.plugin_id).to eq(plugin_id)
36
+ expect(subject.dlq_writer.inner_writer).to eq(dlq_writer)
37
+ end
28
38
  end
@@ -66,7 +66,7 @@ describe "LogStash::Inputs::Base#decorate" do
66
66
 
67
67
  context "execution context" do
68
68
  include_context "execution_context"
69
-
69
+
70
70
  let(:klass) { LogStash::Inputs::NOOP }
71
71
 
72
72
  subject(:instance) { klass.new({}) }
@@ -7,8 +7,8 @@ require_relative "../../support/mocks_classes"
7
7
  require "spec_helper"
8
8
 
9
9
  describe LogStash::Instrument::WrappedWriteClient do
10
- let(:write_client) { queue.write_client }
11
- let(:read_client) { queue.read_client }
10
+ let!(:write_client) { queue.write_client }
11
+ let!(:read_client) { queue.read_client }
12
12
  let(:pipeline) { double("pipeline", :pipeline_id => :main) }
13
13
  let(:collector) { LogStash::Instrument::Collector.new }
14
14
  let(:metric) { LogStash::Instrument::Metric.new(collector) }
@@ -18,39 +18,54 @@ describe LogStash::Instrument::WrappedWriteClient do
18
18
 
19
19
  subject { described_class.new(write_client, pipeline, metric, plugin) }
20
20
 
21
+ def threaded_read_client
22
+ Thread.new do
23
+ started_at = Time.now
24
+
25
+ batch_size = 0
26
+ loop {
27
+ if Time.now - started_at > 60
28
+ raise "Took too much time to read from the queue"
29
+ end
30
+ batch_size = read_client.read_batch.size
31
+
32
+ break if batch_size > 0
33
+ }
34
+ expect(batch_size).to eq(1)
35
+ end
36
+ end
21
37
 
22
38
  shared_examples "queue tests" do
23
39
  it "pushes single event to the `WriteClient`" do
24
- t = Thread.new do
25
- subject.push(event)
40
+ pusher_thread = Thread.new(subject, event) do |_subject, _event|
41
+ _subject.push(_event)
26
42
  end
27
- sleep(0.01) while !t.status
28
- expect(read_client.read_batch.size).to eq(1)
29
- t.kill rescue nil
43
+
44
+ reader_thread = threaded_read_client
45
+
46
+ [pusher_thread, reader_thread].collect(&:join)
30
47
  end
31
48
 
32
49
  it "pushes batch to the `WriteClient`" do
33
50
  batch = write_client.get_new_batch
34
51
  batch << event
35
52
 
36
- t = Thread.new do
37
- subject.push_batch(batch)
53
+ pusher_thread = Thread.new(subject, batch) do |_subject, _batch|
54
+ _subject.push_batch(_batch)
38
55
  end
39
56
 
40
- sleep(0.01) while !t.status
41
- expect(read_client.read_batch.size).to eq(1)
42
- t.kill rescue nil
57
+ reader_thread = threaded_read_client
58
+ [pusher_thread, reader_thread].collect(&:join)
43
59
  end
44
60
 
45
61
  context "recorded metrics" do
46
62
  before do
47
- t = Thread.new do
48
- subject.push(event)
63
+ pusher_thread = Thread.new(subject, event) do |_subject, _event|
64
+ _subject.push(_event)
49
65
  end
50
- sleep(0.01) while !t.status
51
- sleep(0.250) # make it block for some time, so duration isn't 0
52
- read_client.read_batch.size
53
- t.kill rescue nil
66
+
67
+ reader_thread = threaded_read_client
68
+ [pusher_thread, reader_thread].collect(&:join)
54
69
  end
55
70
 
56
71
  let(:snapshot_store) { collector.snapshot_metric.metric_store }
@@ -97,7 +112,7 @@ describe LogStash::Instrument::WrappedWriteClient do
97
112
  end
98
113
 
99
114
  context "AckedMemoryQueue" do
100
- let(:queue) { LogStash::Util::WrappedAckedQueue.create_memory_based("", 1024, 10, 1024) }
115
+ let(:queue) { LogStash::Util::WrappedAckedQueue.create_memory_based("", 1024, 10, 4096) }
101
116
 
102
117
  before do
103
118
  read_client.set_events_metric(metric.namespace([:stats, :events]))
@@ -10,7 +10,7 @@ describe LogStash::OutputDelegator do
10
10
  let(:plugin_args) { {"id" => "foo", "arg1" => "val1"} }
11
11
  let(:collector) { [] }
12
12
  let(:metric) { LogStash::Instrument::NamespacedNullMetric.new(collector, :null) }
13
-
13
+
14
14
  include_context "execution_context"
15
15
 
16
16
  subject { described_class.new(logger, out_klass, metric, execution_context, ::LogStash::OutputDelegatorStrategyRegistry.instance, plugin_args) }
@@ -82,7 +82,7 @@ describe "LogStash::Outputs::Base#new" do
82
82
 
83
83
  context "execution context" do
84
84
  include_context "execution_context"
85
-
85
+
86
86
  let(:klass) { LogStash::Outputs::NOOPSingle }
87
87
 
88
88
  subject(:instance) { klass.new(params.dup) }
@@ -10,7 +10,7 @@ describe LogStash::PipelineAction::Reload do
10
10
  let(:pipeline_id) { :main }
11
11
  let(:new_pipeline_config) { mock_pipeline_config(pipeline_id, "input { generator { id => 'new' } } output { null {} }", { "pipeline.reloadable" => true}) }
12
12
  let(:pipeline_config) { "input { generator {} } output { null {} }" }
13
- let(:pipeline) { LogStash::Pipeline.new(pipeline_config, mock_settings("pipeline.reloadable" => true)) }
13
+ let(:pipeline) { mock_pipeline_from_string(pipeline_config, mock_settings("pipeline.reloadable" => true)) }
14
14
  let(:pipelines) { { pipeline_id => pipeline } }
15
15
  let(:agent) { double("agent") }
16
16
 
@@ -8,7 +8,7 @@ require "logstash/instrument/null_metric"
8
8
  describe LogStash::PipelineAction::Stop do
9
9
  let(:pipeline_config) { "input { generator {} } output { null {} }" }
10
10
  let(:pipeline_id) { :main }
11
- let(:pipeline) { LogStash::Pipeline.new(pipeline_config) }
11
+ let(:pipeline) { mock_pipeline_from_string(pipeline_config) }
12
12
  let(:pipelines) { { :main => pipeline } }
13
13
  let(:agent) { double("agent") }
14
14
 
@@ -0,0 +1,107 @@
1
+ # encoding: utf-8
2
+ require "tmpdir"
3
+ require "spec_helper"
4
+ require "logstash/codecs/plain"
5
+ require_relative "../support/mocks_classes"
6
+
7
+ class SingleGeneratorInput < LogStash::Inputs::Base
8
+ config_name "singlegenerator"
9
+ milestone 2
10
+
11
+ def register
12
+ end
13
+
14
+ def run(queue)
15
+ queue << LogStash::Event.new
16
+ end
17
+
18
+ def close
19
+ end
20
+ end
21
+
22
+ class DLQCommittingFilter < LogStash::Filters::Base
23
+ config_name "dlq_commit"
24
+ milestone 2
25
+
26
+ def register()
27
+ end
28
+
29
+ def filter(event)
30
+ execution_context.dlq_writer.write(event, "my reason")
31
+ end
32
+
33
+ def threadsafe?() true; end
34
+
35
+ def close() end
36
+ end
37
+
38
+ describe LogStash::Pipeline do
39
+ let(:pipeline_settings_obj) { LogStash::SETTINGS }
40
+ let(:pipeline_settings) do
41
+ {
42
+ "pipeline.workers" => 2,
43
+ "pipeline.id" => pipeline_id,
44
+ "dead_letter_queue.enable" => enable_dlq,
45
+ "path.dead_letter_queue" => Dir.mktmpdir
46
+ }
47
+ end
48
+ let(:metric) { LogStash::Instrument::Metric.new(LogStash::Instrument::Collector.new) }
49
+ let(:test_config) {
50
+ <<-eos
51
+ input { singlegenerator { id => input_id } }
52
+
53
+ filter { dlq_commit { id => filter_id } }
54
+
55
+ output { dummyoutput { id => output_id } }
56
+ eos
57
+ }
58
+
59
+ subject { mock_pipeline_from_string(test_config, pipeline_settings_obj, metric) }
60
+
61
+ before(:each) do
62
+ pipeline_settings.each {|k, v| pipeline_settings_obj.set(k, v) }
63
+ allow(LogStash::Plugin).to receive(:lookup).with("input", "singlegenerator").and_return(SingleGeneratorInput)
64
+ allow(LogStash::Plugin).to receive(:lookup).with("codec", "plain").and_return(LogStash::Codecs::Plain)
65
+ allow(LogStash::Plugin).to receive(:lookup).with("filter", "dlq_commit").and_return(DLQCommittingFilter)
66
+ allow(LogStash::Plugin).to receive(:lookup).with("output", "dummyoutput").and_return(::LogStash::Outputs::DummyOutput)
67
+ end
68
+
69
+ after(:each) do
70
+ FileUtils.remove_entry pipeline_settings["path.dead_letter_queue"]
71
+ end
72
+
73
+ context "dlq is enabled" do
74
+ let(:enable_dlq) { true }
75
+ let(:pipeline_id) { "test-dlq" }
76
+
77
+ it "retrieves proper pipeline-level DLQ writer" do
78
+ expect(LogStash::Util::PluginDeadLetterQueueWriter).to receive(:new).with(anything, "input_id", "singlegenerator").and_call_original
79
+ expect(LogStash::Util::PluginDeadLetterQueueWriter).to receive(:new).with(anything, "filter_id", "dlq_commit").and_call_original
80
+ expect(LogStash::Util::PluginDeadLetterQueueWriter).to receive(:new).with(anything, "output_id", "dummyoutput").and_call_original
81
+ expect_any_instance_of(org.logstash.common.io.DeadLetterQueueWriter).to receive(:close).and_call_original
82
+ subject.run
83
+ dlq_path = java.nio.file.Paths.get(pipeline_settings_obj.get("path.dead_letter_queue"), pipeline_id)
84
+ dlq_reader = org.logstash.common.io.DeadLetterQueueReader.new(dlq_path)
85
+ entry = dlq_reader.pollEntry(40)
86
+ expect(entry).to_not be_nil
87
+ expect(entry.reason).to eq("my reason")
88
+ end
89
+ end
90
+
91
+ context "dlq is disabled" do
92
+ let(:enable_dlq) { false }
93
+ let(:pipeline_id) { "test-without-dlq" }
94
+
95
+ it "does not write to the DLQ" do
96
+ expect(LogStash::Util::PluginDeadLetterQueueWriter).to receive(:new).with(anything, "input_id", "singlegenerator").and_call_original
97
+ expect(LogStash::Util::PluginDeadLetterQueueWriter).to receive(:new).with(anything, "filter_id", "dlq_commit").and_call_original
98
+ expect(LogStash::Util::PluginDeadLetterQueueWriter).to receive(:new).with(anything, "output_id", "dummyoutput").and_call_original
99
+ expect(LogStash::Util::DummyDeadLetterQueueWriter).to receive(:new).and_call_original
100
+ expect_any_instance_of(LogStash::Util::DummyDeadLetterQueueWriter).to receive(:close).and_call_original
101
+ subject.run
102
+ dlq_path = java.nio.file.Paths.get(pipeline_settings_obj.get("path.dead_letter_queue"), pipeline_id)
103
+ expect(java.nio.file.Files.exists(dlq_path)).to eq(false)
104
+ end
105
+ end
106
+
107
+ end
@@ -2,6 +2,7 @@
2
2
  require "spec_helper"
3
3
  require "logstash/inputs/generator"
4
4
  require "logstash/filters/multiline"
5
+ require_relative "../support/helpers"
5
6
 
6
7
  class PipelinePqFileOutput < LogStash::Outputs::Base
7
8
  config_name "pipelinepqfileoutput"
@@ -67,7 +68,8 @@ describe LogStash::Pipeline do
67
68
 
68
69
  let(:pipeline_settings) { { "queue.type" => queue_type, "pipeline.workers" => worker_thread_count, "pipeline.id" => pipeline_id} }
69
70
 
70
- subject { described_class.new(config, pipeline_settings_obj, metric) }
71
+ let(:pipeline_config) { mock_pipeline_config(pipeline_id, config, pipeline_settings_obj) }
72
+ subject { described_class.new(pipeline_config, metric) }
71
73
 
72
74
  let(:counting_output) { PipelinePqFileOutput.new({ "id" => output_id }) }
73
75
  let(:metric_store) { subject.metric.collector.snapshot_metric.metric_store }
@@ -2,6 +2,7 @@
2
2
  require "spec_helper"
3
3
  require "logstash/pipeline"
4
4
  require "logstash/pipeline_reporter"
5
+ require_relative "../support/helpers"
5
6
  require_relative "../support/mocks_classes"
6
7
 
7
8
  #TODO: Figure out how to add more tests that actually cover inflight events
@@ -11,7 +12,7 @@ describe LogStash::PipelineReporter do
11
12
  let(:config) do
12
13
  "input { generator { count => #{generator_count} } } output { dummyoutput {} } "
13
14
  end
14
- let(:pipeline) { LogStash::Pipeline.new(config)}
15
+ let(:pipeline) { mock_pipeline_from_string(config)}
15
16
  let(:reporter) { pipeline.reporter }
16
17
 
17
18
  before do
@@ -81,6 +81,21 @@ class DummySafeFilter < LogStash::Filters::Base
81
81
  def close() end
82
82
  end
83
83
 
84
+ class DummyFlushingFilter < LogStash::Filters::Base
85
+ config_name "dummyflushingfilter"
86
+ milestone 2
87
+
88
+ def register() end
89
+ def filter(event) end
90
+ def periodic_flush
91
+ true
92
+ end
93
+ def flush(options)
94
+ return [::LogStash::Event.new("message" => "dummy_flush")]
95
+ end
96
+ def close() end
97
+ end
98
+
84
99
  class TestPipeline < LogStash::Pipeline
85
100
  attr_reader :outputs, :settings
86
101
  end
@@ -139,7 +154,7 @@ describe LogStash::Pipeline do
139
154
  abort_on_exception_state = Thread.abort_on_exception
140
155
  Thread.abort_on_exception = true
141
156
 
142
- pipeline = LogStash::Pipeline.new(config, pipeline_settings_obj)
157
+ pipeline = mock_pipeline_from_string(config, pipeline_settings_obj)
143
158
  t = Thread.new { pipeline.run }
144
159
  sleep(0.1) until pipeline.ready?
145
160
  wait(3).for do
@@ -187,21 +202,21 @@ describe LogStash::Pipeline do
187
202
  let(:logger) { double("pipeline logger").as_null_object }
188
203
 
189
204
  before do
190
- expect(TestPipeline).to receive(:logger).and_return(logger)
205
+ expect(::LogStash::Pipeline).to receive(:logger).and_return(logger)
191
206
  allow(logger).to receive(:debug?).and_return(true)
192
207
  end
193
208
 
194
209
  it "should not receive a debug message with the compiled code" do
195
210
  pipeline_settings_obj.set("config.debug", false)
196
211
  expect(logger).not_to receive(:debug).with(/Compiled pipeline/, anything)
197
- pipeline = TestPipeline.new(test_config_with_filters)
212
+ pipeline = mock_pipeline_from_string(test_config_with_filters)
198
213
  pipeline.close
199
214
  end
200
215
 
201
216
  it "should print the compiled code if config.debug is set to true" do
202
217
  pipeline_settings_obj.set("config.debug", true)
203
218
  expect(logger).to receive(:debug).with(/Compiled pipeline/, anything)
204
- pipeline = TestPipeline.new(test_config_with_filters, pipeline_settings_obj)
219
+ pipeline = mock_pipeline_from_string(test_config_with_filters, pipeline_settings_obj)
205
220
  pipeline.close
206
221
  end
207
222
  end
@@ -209,7 +224,7 @@ describe LogStash::Pipeline do
209
224
  context "when there is no command line -w N set" do
210
225
  it "starts one filter thread" do
211
226
  msg = "Defaulting pipeline worker threads to 1 because there are some filters that might not work with multiple worker threads"
212
- pipeline = TestPipeline.new(test_config_with_filters)
227
+ pipeline = mock_pipeline_from_string(test_config_with_filters)
213
228
  expect(pipeline.logger).to receive(:warn).with(msg,
214
229
  hash_including({:count_was=>worker_thread_count, :filters=>["dummyfilter"]}))
215
230
  pipeline.run
@@ -223,7 +238,7 @@ describe LogStash::Pipeline do
223
238
  it "starts multiple filter thread" do
224
239
  msg = "Warning: Manual override - there are filters that might" +
225
240
  " not work with multiple worker threads"
226
- pipeline = TestPipeline.new(test_config_with_filters, pipeline_settings_obj)
241
+ pipeline = mock_pipeline_from_string(test_config_with_filters, pipeline_settings_obj)
227
242
  expect(pipeline.logger).to receive(:warn).with(msg, hash_including({:worker_threads=> override_thread_count, :filters=>["dummyfilter"]}))
228
243
  pipeline.run
229
244
  expect(pipeline.worker_threads.size).to eq(override_thread_count)
@@ -250,7 +265,8 @@ describe LogStash::Pipeline do
250
265
  }
251
266
 
252
267
  it "starts multiple filter threads" do
253
- pipeline = TestPipeline.new(test_config_with_filters)
268
+ skip("This test has been failing periodically since November 2016. Tracked as https://github.com/elastic/logstash/issues/6245")
269
+ pipeline = mock_pipeline_from_string(test_config_with_filters)
254
270
  pipeline.run
255
271
  expect(pipeline.worker_threads.size).to eq(worker_thread_count)
256
272
  pipeline.shutdown
@@ -293,7 +309,7 @@ describe LogStash::Pipeline do
293
309
  }
294
310
 
295
311
  context "output close" do
296
- let(:pipeline) { TestPipeline.new(test_config_without_output_workers) }
312
+ let(:pipeline) { mock_pipeline_from_string(test_config_without_output_workers) }
297
313
  let(:output) { pipeline.outputs.first }
298
314
 
299
315
  before do
@@ -323,7 +339,7 @@ describe LogStash::Pipeline do
323
339
  let(:config) { "input { dummyinput {} } output { dummyoutput {} }"}
324
340
 
325
341
  it "should start the flusher thread only after the pipeline is running" do
326
- pipeline = TestPipeline.new(config)
342
+ pipeline = mock_pipeline_from_string(config)
327
343
 
328
344
  expect(pipeline).to receive(:transition_to_running).ordered.and_call_original
329
345
  expect(pipeline).to receive(:start_flusher).ordered.and_call_original
@@ -379,7 +395,7 @@ describe LogStash::Pipeline do
379
395
  let(:config) { "input { dummyinput {} } output { dummyoutput {} }" }
380
396
  let(:batch_size) { 1 }
381
397
  let(:pipeline_settings) { { "pipeline.batch.size" => batch_size, "pipeline.workers" => 1 } }
382
- let(:pipeline) { LogStash::Pipeline.new(config, pipeline_settings_obj) }
398
+ let(:pipeline) { mock_pipeline_from_string(config, pipeline_settings_obj) }
383
399
  let(:logger) { pipeline.logger }
384
400
  let(:warning_prefix) { Regexp.new("CAUTION: Recommended inflight events max exceeded!") }
385
401
 
@@ -446,7 +462,7 @@ describe LogStash::Pipeline do
446
462
  config = "input { } filter { } output { }"
447
463
 
448
464
  let(:settings) { LogStash::SETTINGS.clone }
449
- subject { LogStash::Pipeline.new(config, settings, metric) }
465
+ subject { mock_pipeline_from_string(config, settings, metric) }
450
466
 
451
467
  after :each do
452
468
  subject.close
@@ -547,8 +563,8 @@ describe LogStash::Pipeline do
547
563
  pipeline_settings.each {|k, v| pipeline_settings_obj.set(k, v) }
548
564
  end
549
565
 
550
- let(:pipeline1) { LogStash::Pipeline.new("input { dummyinputgenerator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
551
- let(:pipeline2) { LogStash::Pipeline.new("input { dummyinputgenerator {} } filter { dummyfilter {} } output { dummyoutputmore {}}") }
566
+ let(:pipeline1) { mock_pipeline_from_string("input { dummyinputgenerator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
567
+ let(:pipeline2) { mock_pipeline_from_string("input { dummyinputgenerator {} } filter { dummyfilter {} } output { dummyoutputmore {}}") }
552
568
 
553
569
  after do
554
570
  pipeline1.close
@@ -564,23 +580,16 @@ describe LogStash::Pipeline do
564
580
  end
565
581
 
566
582
  context "Periodic Flush" do
567
- let(:number_of_events) { 100 }
568
583
  let(:config) do
569
584
  <<-EOS
570
585
  input {
571
- generator {
572
- count => #{number_of_events}
573
- }
586
+ dummy_input {}
574
587
  }
575
588
  filter {
576
- multiline {
577
- pattern => "^NeverMatch"
578
- negate => true
579
- what => "previous"
580
- }
589
+ dummy_flushing_filter {}
581
590
  }
582
591
  output {
583
- dummyoutput {}
592
+ dummy_output {}
584
593
  }
585
594
  EOS
586
595
  end
@@ -588,24 +597,26 @@ describe LogStash::Pipeline do
588
597
 
589
598
  before do
590
599
  allow(::LogStash::Outputs::DummyOutput).to receive(:new).with(any_args).and_return(output)
591
- allow(LogStash::Plugin).to receive(:lookup).with("input", "generator").and_return(LogStash::Inputs::Generator)
600
+ allow(LogStash::Plugin).to receive(:lookup).with("input", "dummy_input").and_return(DummyInput)
601
+ allow(LogStash::Plugin).to receive(:lookup).with("filter", "dummy_flushing_filter").and_return(DummyFlushingFilter)
602
+ allow(LogStash::Plugin).to receive(:lookup).with("output", "dummy_output").and_return(::LogStash::Outputs::DummyOutput)
592
603
  allow(LogStash::Plugin).to receive(:lookup).with("codec", "plain").and_return(LogStash::Codecs::Plain)
593
- allow(LogStash::Plugin).to receive(:lookup).with("filter", "multiline").and_return(LogStash::Filters::Multiline)
594
- allow(LogStash::Plugin).to receive(:lookup).with("output", "dummyoutput").and_return(::LogStash::Outputs::DummyOutput)
595
604
  end
596
605
 
597
- it "flushes the buffered contents of the filter" do
606
+ it "flush periodically" do
598
607
  Thread.abort_on_exception = true
599
- pipeline = LogStash::Pipeline.new(config, pipeline_settings_obj)
608
+ pipeline = mock_pipeline_from_string(config, pipeline_settings_obj)
600
609
  t = Thread.new { pipeline.run }
601
610
  sleep(0.1) until pipeline.ready?
602
- wait(3).for do
611
+ wait(10).for do
603
612
  # give us a bit of time to flush the events
604
613
  output.events.empty?
605
614
  end.to be_falsey
606
- event = output.events.pop
607
- expect(event.get("message").count("\n")).to eq(99)
615
+
616
+ expect(output.events.any? {|e| e.get("message") == "dummy_flush"}).to eq(true)
617
+
608
618
  pipeline.shutdown
619
+
609
620
  t.join
610
621
  end
611
622
  end
@@ -618,8 +629,8 @@ describe LogStash::Pipeline do
618
629
  allow(LogStash::Plugin).to receive(:lookup).with("output", "dummyoutput").and_return(::LogStash::Outputs::DummyOutput)
619
630
  end
620
631
 
621
- let(:pipeline1) { LogStash::Pipeline.new("input { generator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
622
- let(:pipeline2) { LogStash::Pipeline.new("input { generator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
632
+ let(:pipeline1) { mock_pipeline_from_string("input { generator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
633
+ let(:pipeline2) { mock_pipeline_from_string("input { generator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
623
634
 
624
635
  # multiple pipelines cannot be instantiated using the same PQ settings, force memory queue
625
636
  before :each do
@@ -656,7 +667,7 @@ describe LogStash::Pipeline do
656
667
  EOS
657
668
  end
658
669
 
659
- subject { described_class.new(config) }
670
+ subject { mock_pipeline_from_string(config) }
660
671
 
661
672
  context "when the pipeline is not started" do
662
673
  after :each do
@@ -683,7 +694,7 @@ describe LogStash::Pipeline do
683
694
  }
684
695
  EOS
685
696
  end
686
- subject { described_class.new(config) }
697
+ subject { mock_pipeline_from_string(config) }
687
698
 
688
699
  context "when the pipeline is not started" do
689
700
  after :each do
@@ -713,7 +724,7 @@ describe LogStash::Pipeline do
713
724
  context "when collecting metrics in the pipeline" do
714
725
  let(:metric) { LogStash::Instrument::Metric.new(LogStash::Instrument::Collector.new) }
715
726
 
716
- subject { described_class.new(config, pipeline_settings_obj, metric) }
727
+ subject { mock_pipeline_from_string(config, pipeline_settings_obj, metric) }
717
728
 
718
729
  let(:pipeline_settings) { { "pipeline.id" => pipeline_id } }
719
730
  let(:pipeline_id) { "main" }
@@ -840,8 +851,8 @@ describe LogStash::Pipeline do
840
851
  allow(LogStash::Plugin).to receive(:lookup).with("output", "dummyoutput").and_return(::LogStash::Outputs::DummyOutput)
841
852
  end
842
853
 
843
- let(:pipeline1) { LogStash::Pipeline.new("input { generator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
844
- let(:pipeline2) { LogStash::Pipeline.new("input { generator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
854
+ let(:pipeline1) { mock_pipeline_from_string("input { generator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
855
+ let(:pipeline2) { mock_pipeline_from_string("input { generator {} } filter { dummyfilter {} } output { dummyoutput {}}") }
845
856
 
846
857
  # multiple pipelines cannot be instantiated using the same PQ settings, force memory queue
847
858
  before :each do
@@ -861,14 +872,14 @@ describe LogStash::Pipeline do
861
872
  end
862
873
 
863
874
  context "when the pipeline is a system pipeline" do
864
- let(:pipeline) { LogStash::Pipeline.new("input { generator {} } output { null {} }", mock_settings("pipeline.system" => true)) }
875
+ let(:pipeline) { mock_pipeline_from_string("input { generator {} } output { null {} }", mock_settings("pipeline.system" => true)) }
865
876
  it "returns true" do
866
877
  expect(pipeline.system?).to be_truthy
867
878
  end
868
879
  end
869
880
 
870
881
  context "when the pipeline is not a system pipeline" do
871
- let(:pipeline) { LogStash::Pipeline.new("input { generator {} } output { null {} }", mock_settings("pipeline.system" => false)) }
882
+ let(:pipeline) { mock_pipeline_from_string("input { generator {} } output { null {} }", mock_settings("pipeline.system" => false)) }
872
883
  it "returns true" do
873
884
  expect(pipeline.system?).to be_falsey
874
885
  end
@@ -881,7 +892,7 @@ describe LogStash::Pipeline do
881
892
  end
882
893
 
883
894
  context "when all plugins are reloadable and pipeline is configured as reloadable" do
884
- let(:pipeline) { LogStash::Pipeline.new("input { generator {} } output { null {} }", mock_settings("pipeline.reloadable" => true)) }
895
+ let(:pipeline) { mock_pipeline_from_string("input { generator {} } output { null {} }", mock_settings("pipeline.reloadable" => true)) }
885
896
 
886
897
  it "returns true" do
887
898
  expect(pipeline.reloadable?).to be_truthy
@@ -889,7 +900,7 @@ describe LogStash::Pipeline do
889
900
  end
890
901
 
891
902
  context "when the plugins are not reloadable and pipeline is configured as reloadable" do
892
- let(:pipeline) { LogStash::Pipeline.new("input { stdin {} } output { null {} }", mock_settings("pipeline.reloadable" => true)) }
903
+ let(:pipeline) { mock_pipeline_from_string("input { stdin {} } output { null {} }", mock_settings("pipeline.reloadable" => true)) }
893
904
 
894
905
  it "returns true" do
895
906
  expect(pipeline.reloadable?).to be_falsey
@@ -897,7 +908,7 @@ describe LogStash::Pipeline do
897
908
  end
898
909
 
899
910
  context "when all plugins are reloadable and pipeline is configured as non-reloadable" do
900
- let(:pipeline) { LogStash::Pipeline.new("input { generator {} } output { null {} }", mock_settings("pipeline.reloadable" => false)) }
911
+ let(:pipeline) { mock_pipeline_from_string("input { generator {} } output { null {} }", mock_settings("pipeline.reloadable" => false)) }
901
912
 
902
913
  it "returns true" do
903
914
  expect(pipeline.reloadable?).to be_falsey