logstash-core 2.3.0.snapshot3-java → 2.3.0.snapshot4-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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75d090462d8c05728226be1cff308e149ae54e27
4
- data.tar.gz: 322a66722d833de679b086e946bb01a7d9168966
3
+ metadata.gz: dacf1faefe3817fb4158d35c81709879f3753206
4
+ data.tar.gz: 92ab29d4716a1569922a30bb11e88444de71472a
5
5
  SHA512:
6
- metadata.gz: b28f06d3063faa64d8526298319c0c5f12f2ceaf0aef7071360d3011718c4c62acbc8bde2d80a6a5e8418e0c7b23138c52223f691c8fcf8e9d091632ec79dd31
7
- data.tar.gz: 443aa26815d0ca0e0d9199b622934dcba1e98bb0fb24e55dfbd79746d40024c913a0be424028ad203f639075cd68a609c726a112489302928512d10f11154aad
6
+ metadata.gz: 701b4d572012650152f1af359d8a91a3837344dde79a8c8afabec771105550fc01f7fb9959e6c4516573587f662c8aeca5bec8e70c6b0e2066e4721e2cf2c83d
7
+ data.tar.gz: 1e1957c427e027b467c47cd1fabcbecee272118b5d7f7bffe10b7b7fb7ee07d5427d7f64ffd8d55879de5856e5e05a960afb55281e31fe9c4783d0a59c8c1dff
@@ -83,10 +83,6 @@ class LogStash::Agent < Clamp::Command
83
83
  I18n.t("logstash.agent.flag.reload_interval"),
84
84
  :attribute_name => :reload_interval, :default => 3, &:to_i
85
85
 
86
- option ["-n", "--node-name"], "NAME",
87
- I18n.t("logstash.runner.flag.node_name"),
88
- :attribute_name => :node_name, :default => Socket.gethostname
89
-
90
86
  def initialize(*params)
91
87
  super(*params)
92
88
  @logger = Cabin::Channel.get(LogStash)
@@ -342,6 +338,12 @@ class LogStash::Agent < Clamp::Command
342
338
  def register_pipeline(pipeline_id, settings)
343
339
  pipeline = create_pipeline(settings.merge(:pipeline_id => pipeline_id))
344
340
  return unless pipeline.is_a?(LogStash::Pipeline)
341
+ if @auto_reload && pipeline.non_reloadable_plugins.any?
342
+ @logger.error(I18n.t("logstash.agent.non_reloadable_config_register"),
343
+ :pipeline_id => pipeline_id,
344
+ :plugins => pipeline.non_reloadable_plugins.map(&:class))
345
+ return
346
+ end
345
347
  @pipelines[pipeline_id] = pipeline
346
348
  end
347
349
 
@@ -424,6 +426,10 @@ class LogStash::Agent < Clamp::Command
424
426
  if old_pipeline.config_str == new_pipeline.config_str
425
427
  @logger.debug("no configuration change for pipeline",
426
428
  :pipeline => id, :config => old_pipeline.config_str)
429
+ elsif new_pipeline.non_reloadable_plugins.any?
430
+ @logger.error(I18n.t("logstash.agent.non_reloadable_config_reload"),
431
+ :pipeline_id => id,
432
+ :plugins => new_pipeline.non_reloadable_plugins.map(&:class))
427
433
  else
428
434
  @logger.log("fetched new config for pipeline. upgrading..",
429
435
  :pipeline => id, :config => new_pipeline.config_str)
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  require "concurrent/atomic/atomic_fixnum"
3
+ java_import "java.util.concurrent.CopyOnWriteArrayList"
3
4
 
4
5
  # This class goes hand in hand with the pipeline to provide a pool of
5
6
  # free workers to be used by pipeline worker threads. The pool is
@@ -8,63 +9,19 @@ require "concurrent/atomic/atomic_fixnum"
8
9
  #
9
10
  # This plugin also records some basic statistics
10
11
  module LogStash class OutputDelegator
11
- attr_reader :workers, :config, :worker_count, :threadsafe
12
+ attr_reader :workers, :config, :threadsafe
12
13
 
13
14
  # The *args this takes are the same format that a Outputs::Base takes. A list of hashes with parameters in them
14
15
  # Internally these just get merged together into a single hash
15
- def initialize(logger, klass, default_worker_count, *args)
16
+ def initialize(logger, klass, default_worker_count, *plugin_args)
16
17
  @logger = logger
17
18
  @threadsafe = klass.threadsafe?
18
- @config = args.reduce({}, :merge)
19
+ @config = plugin_args.reduce({}, :merge)
19
20
  @klass = klass
20
-
21
- # We define this as an array regardless of threadsafety
22
- # to make reporting simpler, even though a threadsafe plugin will just have
23
- # a single instance
24
- #
25
- # Older plugins invoke the instance method Outputs::Base#workers_not_supported
26
- # To detect these we need an instance to be created first :()
27
- # TODO: In the next major version after 2.x remove support for this
28
- @workers = [@klass.new(*args)]
29
- @workers.first.register # Needed in case register calls `workers_not_supported`
30
-
31
- # DO NOT move this statement before the instantiation of the first single instance
32
- # Read the note above to understand why
33
- @worker_count = calculate_worker_count(default_worker_count)
34
- @logger.debug("Will start workers for output", :worker_count => @worker_count, :class => klass)
35
-
36
- warn_on_worker_override!
37
- # This queue is used to manage sharing across threads
38
- @worker_queue = SizedQueue.new(@worker_count)
39
-
40
- @workers += (@worker_count - 1).times.map do
41
- inst = @klass.new(*args)
42
- inst.register
43
- inst
44
- end
45
-
46
- @workers.each { |w| @worker_queue << w }
47
-
21
+ @workers = java.util.concurrent.CopyOnWriteArrayList.new
22
+ @default_worker_count = default_worker_count
23
+ @registered = false
48
24
  @events_received = Concurrent::AtomicFixnum.new(0)
49
-
50
-
51
- # One might wonder why we don't use something like
52
- # define_singleton_method(:multi_receive, method(:threadsafe_multi_receive)
53
- # and the answer is this is buggy on Jruby 1.7.x . It works 98% of the time!
54
- # The other 2% you get weird errors about rebinding to the same object
55
- # Until we switch to Jruby 9.x keep the define_singleton_method parts
56
- # the way they are, with a block
57
- # See https://github.com/jruby/jruby/issues/3582
58
- if threadsafe?
59
- @threadsafe_worker = @workers.first
60
- define_singleton_method(:multi_receive) do |events|
61
- threadsafe_multi_receive(events)
62
- end
63
- else
64
- define_singleton_method(:multi_receive) do |events|
65
- worker_multi_receive(events)
66
- end
67
- end
68
25
  end
69
26
 
70
27
  def threadsafe?
@@ -89,11 +46,14 @@ module LogStash class OutputDelegator
89
46
  @config["workers"] && @config["workers"] > 1 && @klass.workers_not_supported?
90
47
  end
91
48
 
92
- def calculate_worker_count(default_worker_count)
49
+ def target_worker_count
50
+ # Remove in 5.0 after all plugins upgraded to use class level declarations
51
+ raise ArgumentError, "Attempted to detect target worker count before instantiating a worker to test for legacy workers_not_supported!" if @workers.size == 0
52
+
93
53
  if @threadsafe || @klass.workers_not_supported?
94
54
  1
95
55
  else
96
- @config["workers"] || default_worker_count
56
+ @config["workers"] || @default_worker_count
97
57
  end
98
58
  end
99
59
 
@@ -102,7 +62,58 @@ module LogStash class OutputDelegator
102
62
  end
103
63
 
104
64
  def register
105
- @workers.each {|w| w.register}
65
+ raise ArgumentError, "Attempted to register #{self} twice!" if @registered
66
+ @registered = true
67
+ # We define this as an array regardless of threadsafety
68
+ # to make reporting simpler, even though a threadsafe plugin will just have
69
+ # a single instance
70
+ #
71
+ # Older plugins invoke the instance method Outputs::Base#workers_not_supported
72
+ # To detect these we need an instance to be created first :()
73
+ # TODO: In the next major version after 2.x remove support for this
74
+ @workers << @klass.new(@config)
75
+ @workers.first.register # Needed in case register calls `workers_not_supported`
76
+
77
+ @logger.debug("Will start workers for output", :worker_count => target_worker_count, :class => @klass)
78
+
79
+ # Threadsafe versions don't need additional workers
80
+ setup_additional_workers!(target_worker_count) unless @threadsafe
81
+ # We skip the first worker because that's pre-registered to deal with legacy workers_not_supported
82
+ @workers.subList(1,@workers.size).each(&:register)
83
+ setup_multi_receive!
84
+ end
85
+
86
+ def setup_additional_workers!(target_worker_count)
87
+ warn_on_worker_override!
88
+
89
+ (target_worker_count - 1).times do
90
+ inst = @klass.new(@config)
91
+ @workers << inst
92
+ end
93
+
94
+ # This queue is used to manage sharing across threads
95
+ @worker_queue = SizedQueue.new(target_worker_count)
96
+ @workers.each {|w| @worker_queue << w }
97
+ end
98
+
99
+ def setup_multi_receive!
100
+ # One might wonder why we don't use something like
101
+ # define_singleton_method(:multi_receive, method(:threadsafe_multi_receive)
102
+ # and the answer is this is buggy on Jruby 1.7.x . It works 98% of the time!
103
+ # The other 2% you get weird errors about rebinding to the same object
104
+ # Until we switch to Jruby 9.x keep the define_singleton_method parts
105
+ # the way they are, with a block
106
+ # See https://github.com/jruby/jruby/issues/3582
107
+ if threadsafe?
108
+ @threadsafe_worker = @workers.first
109
+ define_singleton_method(:multi_receive) do |events|
110
+ threadsafe_multi_receive(events)
111
+ end
112
+ else
113
+ define_singleton_method(:multi_receive) do |events|
114
+ worker_multi_receive(events)
115
+ end
116
+ end
106
117
  end
107
118
 
108
119
  def threadsafe_multi_receive(events)
@@ -125,9 +136,13 @@ module LogStash class OutputDelegator
125
136
  def do_close
126
137
  @logger.debug("closing output delegator", :klass => self)
127
138
 
128
- @worker_count.times do
129
- worker = @worker_queue.pop
130
- worker.do_close
139
+ if @threadsafe
140
+ @workers.each(&:do_close)
141
+ else
142
+ worker_count.times do
143
+ worker = @worker_queue.pop
144
+ worker.do_close
145
+ end
131
146
  end
132
147
  end
133
148
 
@@ -140,10 +155,17 @@ module LogStash class OutputDelegator
140
155
  if @threadsafe
141
156
  0
142
157
  else
158
+ # The pipeline reporter can run before the outputs are registered trying to pull a value here
159
+ # In that case @worker_queue is empty, we just return 0
160
+ return 0 unless @worker_queue
143
161
  @workers.size - @worker_queue.size
144
162
  end
145
163
  end
146
164
 
165
+ def worker_count
166
+ @workers.size
167
+ end
168
+
147
169
  private
148
170
  # Needed for testing, so private
149
171
  attr_reader :threadsafe_worker, :worker_queue
@@ -28,6 +28,10 @@ module LogStash; class Pipeline
28
28
  }
29
29
  MAX_INFLIGHT_WARN_THRESHOLD = 10_000
30
30
 
31
+ RELOAD_INCOMPATIBLE_PLUGINS = [
32
+ "LogStash::Inputs::Stdin"
33
+ ]
34
+
31
35
  def self.validate_config(config_str, settings = {})
32
36
  begin
33
37
  # There should be a better way to test this
@@ -488,4 +492,11 @@ module LogStash; class Pipeline
488
492
  .each {|t| t.delete("blocked_on") }
489
493
  .each {|t| t.delete("status") }
490
494
  end
495
+
496
+ def non_reloadable_plugins
497
+ (inputs + filters + outputs).select do |plugin|
498
+ RELOAD_INCOMPATIBLE_PLUGINS.include?(plugin.class.name)
499
+ end
500
+ end
501
+
491
502
  end end
@@ -11,4 +11,4 @@
11
11
  # eventually this file should be in the root logstash lib fir and dependencies in logstash-core should be
12
12
  # fixed.
13
13
 
14
- LOGSTASH_VERSION = "2.3.0.snapshot3"
14
+ LOGSTASH_VERSION = "2.3.0.snapshot4"
@@ -5,4 +5,4 @@
5
5
  # Note to authors: this should not include dashes because 'gem' barfs if
6
6
  # you include a dash in the version string.
7
7
 
8
- LOGSTASH_CORE_VERSION = "2.3.0.snapshot3"
8
+ LOGSTASH_CORE_VERSION = "2.3.0.snapshot4"
data/locales/en.yml CHANGED
@@ -73,6 +73,11 @@ en:
73
73
  data loss.
74
74
  forced_sigint: >-
75
75
  SIGINT received. Terminating immediately..
76
+ non_reloadable_config_reload: >-
77
+ Unable to reload configuration because it does not support dynamic reloading
78
+ non_reloadable_config_register: |-
79
+ Logstash was not able to load configuration since it does not support
80
+ dynamic reloading and -r or --auto-reload flag was enabled
76
81
  configtest-flag-information: |-
77
82
  You may be interested in the '--configtest' flag which you can
78
83
  use to validate logstash's configuration before you choose
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.require_paths = ["lib"]
18
18
  gem.version = LOGSTASH_CORE_VERSION
19
19
 
20
- gem.add_runtime_dependency "logstash-core-event-java", "2.3.0.snapshot3"
20
+ gem.add_runtime_dependency "logstash-core-event-java", "2.3.0.snapshot4"
21
21
 
22
22
  gem.add_runtime_dependency "cabin", "~> 0.8.0" #(Apache 2.0 license)
23
23
  gem.add_runtime_dependency "pry", "~> 0.10.1" #(Ruby license)
@@ -25,8 +25,9 @@ describe LogStash::Agent do
25
25
 
26
26
  describe "register_pipeline" do
27
27
  let(:pipeline_id) { "main" }
28
+ let(:config_string) { "input { } filter { } output { }" }
28
29
  let(:settings) { {
29
- :config_string => "input { } filter { } output { }",
30
+ :config_string => config_string,
30
31
  :pipeline_workers => 4
31
32
  } }
32
33
 
@@ -50,14 +51,20 @@ describe LogStash::Agent do
50
51
 
51
52
  context "when auto_reload is false" do
52
53
  let(:agent_args) { [ "--config", config_file] } #reload_interval => 0.01, :config_path => } }
54
+ let(:pipeline_id) { "main" }
55
+ let(:pipeline_settings) { { :config_path => config_file } }
53
56
 
54
- before :each do
55
- allow(subject).to receive(:sleep)
56
- allow(subject).to receive(:clean_state?).and_return(false)
57
- allow(subject).to receive(:running_pipelines?).and_return(true)
57
+ before(:each) do
58
+ subject.register_pipeline(pipeline_id, pipeline_settings)
58
59
  end
59
60
 
60
61
  context "if state is clean" do
62
+ before :each do
63
+ allow(subject).to receive(:running_pipelines?).and_return(true)
64
+ allow(subject).to receive(:sleep)
65
+ allow(subject).to receive(:clean_state?).and_return(false)
66
+ end
67
+
61
68
  it "should not reload_state!" do
62
69
  expect(subject).to_not receive(:reload_state!)
63
70
  t = Thread.new { subject.execute }
@@ -66,10 +73,49 @@ describe LogStash::Agent do
66
73
  t.join
67
74
  end
68
75
  end
76
+
77
+ context "when calling reload_state!" do
78
+ context "with a config that contains reload incompatible plugins" do
79
+ let(:second_pipeline_config) { "input { stdin {} } filter { } output { }" }
80
+
81
+ it "does not reload if new config contains reload incompatible plugins" do
82
+ t = Thread.new { subject.execute }
83
+ sleep 0.01 until subject.running_pipelines? && subject.pipelines.values.first.ready?
84
+ expect(subject).to_not receive(:upgrade_pipeline)
85
+ File.open(config_file, "w") { |f| f.puts second_pipeline_config }
86
+ subject.send(:reload_state!)
87
+ sleep 0.1
88
+ Stud.stop!(t)
89
+ t.join
90
+ end
91
+ end
92
+
93
+ context "with a config that does not contain reload incompatible plugins" do
94
+ let(:second_pipeline_config) { "input { generator { } } filter { } output { }" }
95
+
96
+ it "does not reload if new config contains reload incompatible plugins" do
97
+ t = Thread.new { subject.execute }
98
+ sleep 0.01 until subject.running_pipelines? && subject.pipelines.values.first.ready?
99
+ expect(subject).to receive(:upgrade_pipeline)
100
+ File.open(config_file, "w") { |f| f.puts second_pipeline_config }
101
+ subject.send(:reload_state!)
102
+ sleep 0.1
103
+ Stud.stop!(t)
104
+ t.join
105
+ end
106
+ end
107
+ end
69
108
  end
70
109
 
71
110
  context "when auto_reload is true" do
72
111
  let(:agent_args) { [ "--auto-reload", "--config", config_file] } #reload_interval => 0.01, :config_path => } }
112
+ let(:pipeline_id) { "main" }
113
+ let(:pipeline_settings) { { :config_path => config_file } }
114
+
115
+ before(:each) do
116
+ subject.register_pipeline(pipeline_id, pipeline_settings)
117
+ end
118
+
73
119
  context "if state is clean" do
74
120
  it "should periodically reload_state" do
75
121
  expect(subject).to receive(:reload_state!).at_least(3).times
@@ -81,6 +127,36 @@ describe LogStash::Agent do
81
127
  t.join
82
128
  end
83
129
  end
130
+
131
+ context "when calling reload_state!" do
132
+ context "with a config that contains reload incompatible plugins" do
133
+ let(:second_pipeline_config) { "input { stdin {} } filter { } output { }" }
134
+
135
+ it "does not reload if new config contains reload incompatible plugins" do
136
+ t = Thread.new { subject.execute }
137
+ sleep 0.01 until subject.running_pipelines? && subject.pipelines.values.first.ready?
138
+ expect(subject).to_not receive(:upgrade_pipeline)
139
+ File.open(config_file, "w") { |f| f.puts second_pipeline_config }
140
+ sleep 0.1
141
+ Stud.stop!(t)
142
+ t.join
143
+ end
144
+ end
145
+
146
+ context "with a config that does not contain reload incompatible plugins" do
147
+ let(:second_pipeline_config) { "input { generator { } } filter { } output { }" }
148
+
149
+ it "does not reload if new config contains reload incompatible plugins" do
150
+ t = Thread.new { subject.execute }
151
+ sleep 0.01 until subject.running_pipelines? && subject.pipelines.values.first.ready?
152
+ expect(subject).to receive(:upgrade_pipeline).at_least(2).times
153
+ File.open(config_file, "w") { |f| f.puts second_pipeline_config }
154
+ sleep 0.1
155
+ Stud.stop!(t)
156
+ t.join
157
+ end
158
+ end
159
+ end
84
160
  end
85
161
  end
86
162
 
@@ -27,6 +27,7 @@ describe LogStash::OutputDelegator do
27
27
 
28
28
  context "after having received a batch of events" do
29
29
  before do
30
+ subject.register
30
31
  subject.multi_receive(events)
31
32
  end
32
33
 
@@ -39,23 +40,35 @@ describe LogStash::OutputDelegator do
39
40
  end
40
41
  end
41
42
 
42
- it "should register all workers on register" do
43
- expect(out_inst).to receive(:register)
44
- subject.register
45
- end
46
43
 
47
- it "should close all workers when closing" do
48
- expect(out_inst).to receive(:do_close)
49
- subject.do_close
44
+ describe "closing" do
45
+ before do
46
+ subject.register
47
+ end
48
+
49
+ it "should register all workers on register" do
50
+ expect(out_inst).to have_received(:register)
51
+ end
52
+
53
+ it "should close all workers when closing" do
54
+ expect(out_inst).to receive(:do_close)
55
+ subject.do_close
56
+ end
50
57
  end
51
58
 
52
59
  describe "concurrency and worker support" do
60
+ before do
61
+ allow(out_inst).to receive(:id).and_return("a-simple-plugin")
62
+ allow(out_inst).to receive(:metric=).with(any_args)
63
+ allow(out_klass).to receive(:workers_not_supported?).and_return(false)
64
+ end
65
+
53
66
  describe "non-threadsafe outputs that allow workers" do
54
67
  let(:default_worker_count) { 3 }
55
68
 
56
69
  before do
57
70
  allow(out_klass).to receive(:threadsafe?).and_return(false)
58
- allow(out_klass).to receive(:workers_not_supported?).and_return(false)
71
+ subject.register
59
72
  end
60
73
 
61
74
  it "should instantiate multiple workers" do
@@ -71,7 +84,7 @@ describe LogStash::OutputDelegator do
71
84
  describe "threadsafe outputs" do
72
85
  before do
73
86
  allow(out_klass).to receive(:threadsafe?).and_return(true)
74
- allow(out_klass).to receive(:workers_not_supported?).and_return(false)
87
+ subject.register
75
88
  end
76
89
 
77
90
  it "should return true when threadsafe? is invoked" do
@@ -88,14 +101,18 @@ describe LogStash::OutputDelegator do
88
101
  end
89
102
 
90
103
  it "should not utilize the worker queue" do
91
- expect(subject.send(:worker_queue)).not_to receive(:pop)
92
- subject.multi_receive(events)
104
+ expect(subject.send(:worker_queue)).to be_nil
93
105
  end
94
106
 
95
107
  it "should send received events to the worker" do
96
108
  expect(out_inst).to receive(:multi_receive).with(events)
97
109
  subject.multi_receive(events)
98
110
  end
111
+
112
+ it "should close all workers when closing" do
113
+ expect(out_inst).to receive(:do_close)
114
+ subject.do_close
115
+ end
99
116
  end
100
117
  end
101
118
  end
@@ -115,11 +132,12 @@ describe LogStash::OutputDelegator do
115
132
  let(:default_worker_count) { 2 }
116
133
  let(:out_klass) { LogStash::Outputs::NOOPDelLegacyNoWorkers }
117
134
 
118
- before do
135
+ before(:each) do
119
136
  allow(logger).to receive(:debug).with(any_args)
120
137
  end
121
138
 
122
139
  it "should only setup one worker" do
140
+ subject.register
123
141
  expect(subject.worker_count).to eql(1)
124
142
  end
125
143
  end
metadata CHANGED
@@ -1,21 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0.snapshot3
4
+ version: 2.3.0.snapshot4
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-21 00:00:00.000000000 Z
11
+ date: 2016-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 2.3.0.snapshot3
18
+ version: 2.3.0.snapshot4
19
19
  name: logstash-core-event-java
20
20
  prerelease: false
21
21
  type: :runtime
@@ -23,7 +23,7 @@ dependencies:
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 2.3.0.snapshot3
26
+ version: 2.3.0.snapshot4
27
27
  - !ruby/object:Gem::Dependency
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements: