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

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: