logstash-core 6.0.0.alpha1-java → 6.0.0.alpha2-java

Sign up to get free protection for your applications and to get access to all the features.
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