logstash-input-lumberjack 1.0.3 → 1.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 13d047624d0d97f3184fec85ee0d5a3f9a1fd274
4
- data.tar.gz: 82d47b698574bd27368c49237c61e67c4bfcd5f7
3
+ metadata.gz: 12b4f41cf358aa9dd6e7e398744f74c780371863
4
+ data.tar.gz: 91ad7e8d873cbfd3f98d310ac9169ac963ca19e2
5
5
  SHA512:
6
- metadata.gz: a8109970459a4c12f5ee11feb4b0aa12c668da8f840e9ca371e7f448da447993894964bfb1f2310c8766d7e8dd304bf0b30c088a947ecef21745a51d3caf44f9
7
- data.tar.gz: 731c6a93b576bc7d221a9aaa66ee965ba12e3be7fe4d1182468195aaa9fb93483d071e136fc004326487af2a03141909981ef17ac2341cc459e82a92aa2b8a27
6
+ metadata.gz: bd7ec8da4baf22a8c947c9bffcf44aa94db2bfcb3405f59f4ed685b7e34054f30706033f64335f397c92ed8afa0213e62f4606c4f96fe08409a8fdaf3603be3a
7
+ data.tar.gz: 6b275397ba9b3917f4f12b5f7b4bc6b5b3caea0cc4edd695b443ea00fd8b5a308aab0eb39b5f99ceec46e22a61de841ce8544325927a89f0370333fdf4cc2fe6
@@ -4,8 +4,12 @@ require "cabin"
4
4
  module LogStash
5
5
  # Largely inspired by Martin's fowler circuit breaker
6
6
  class CircuitBreaker
7
+ # Raised when too many errors has occured and we refuse to execute the block
7
8
  class OpenBreaker < StandardError; end
8
9
 
10
+ # Raised when we catch an error that we count
11
+ class HalfOpenBreaker < StandardError; end
12
+
9
13
  # Error threshold before opening the breaker,
10
14
  # if the breaker is open it wont execute the code.
11
15
  DEFAULT_ERROR_THRESHOLD = 5
@@ -48,6 +52,8 @@ module LogStash
48
52
  rescue *@exceptions => e
49
53
  logger.warn("CircuitBreaker::rescuing exceptions", :name => @name, :exception => e.class)
50
54
  increment_errors(e)
55
+
56
+ raise HalfOpenBreaker
51
57
  end
52
58
 
53
59
  def closed?
@@ -31,10 +31,13 @@ class LogStash::Inputs::Lumberjack < LogStash::Inputs::Base
31
31
 
32
32
  # This setting no longer has any effect and will be removed in a future release.
33
33
  config :max_clients, :validate => :number, :deprecated => "This setting no longer has any effect. See https://github.com/logstash-plugins/logstash-input-lumberjack/pull/12 for the history of this change"
34
+
35
+ # The number of seconds before we raise a timeout,
36
+ # this option is useful to control how much time to wait if something is blocking the pipeline.
37
+ config :congestion_threshold, :validate => :number, :default => 5
34
38
 
35
39
  # TODO(sissel): Add CA to authenticate clients with.
36
-
37
- BUFFERED_QUEUE_SIZE = 20
40
+ BUFFERED_QUEUE_SIZE = 1
38
41
  RECONNECT_BACKOFF_SLEEP = 0.5
39
42
 
40
43
  def register
@@ -66,52 +69,52 @@ class LogStash::Inputs::Lumberjack < LogStash::Inputs::Base
66
69
  start_buffer_broker(output_queue)
67
70
 
68
71
  while true do
69
- begin
70
- # Wrapping the accept call into a CircuitBreaker
71
- if @circuit_breaker.closed?
72
- connection = @lumberjack.accept # Blocking call that creates a new connection
72
+ # Wrappingu the accept call into a CircuitBreaker
73
+ if @circuit_breaker.closed?
74
+ connection = @lumberjack.accept # Blocking call that creates a new connection
73
75
 
74
- invoke(connection, codec.clone) do |_codec, line, fields|
75
- _codec.decode(line) do |event|
76
+ invoke(connection, @codec.clone) do |_codec, line, fields|
77
+ _codec.decode(line) do |event|
78
+ begin
76
79
  decorate(event)
77
80
  fields.each { |k,v| event[k] = v; v.force_encoding(Encoding::UTF_8) }
78
-
79
- @circuit_breaker.execute { @buffered_queue << event }
81
+ @circuit_breaker.execute { @buffered_queue.push(event, @congestion_threshold) }
82
+ rescue => e
83
+ raise e
80
84
  end
81
85
  end
82
- else
83
- @logger.warn("Lumberjack input: the pipeline is blocked, temporary refusing new connection.")
84
- sleep(RECONNECT_BACKOFF_SLEEP)
85
86
  end
86
- # When too many errors happen inside the circuit breaker it will throw
87
- # this exception and start refusing connection, we need to catch it but
88
- # it's safe to ignore.
89
- rescue LogStash::CircuitBreaker::OpenBreaker => e
87
+ else
88
+ @logger.warn("Lumberjack input: the pipeline is blocked, temporary refusing new connection.")
89
+ sleep(RECONNECT_BACKOFF_SLEEP)
90
90
  end
91
91
  end
92
92
  rescue LogStash::ShutdownSignal
93
93
  @logger.info("Lumberjack input: received ShutdownSignal")
94
- rescue => e
95
- @logger.error("Lumberjack input: unhandled exception", :exception => e, :backtrace => e.backtrace)
96
94
  ensure
97
95
  shutdown(output_queue)
98
96
  end # def run
99
97
 
100
- private
101
- def accept(&block)
102
- connection = @lumberjack.accept # Blocking call that creates a new connection
103
- block.call(connection, @codec.clone)
104
- end
105
-
106
98
  private
107
99
  def invoke(connection, codec, &block)
108
100
  @threadpool.post do
109
101
  begin
102
+ # If any errors occur in from the events the connection should be closed in the
103
+ # library ensure block and the exception will be handled here
110
104
  connection.run do |fields|
111
105
  block.call(codec, fields.delete("line"), fields)
112
106
  end
113
- rescue => e
114
- @logger.error("Exception in lumberjack input thread", :exception => e)
107
+
108
+ # When too many errors happen inside the circuit breaker it will throw
109
+ # this exception and start refusing connection. The bubbling of theses
110
+ # exceptions make sure that the lumberjack library will close the current
111
+ # connection which will force the client to reconnect and restransmit
112
+ # his payload.
113
+ rescue LogStash::CircuitBreaker::OpenBreaker,
114
+ LogStash::CircuitBreaker::HalfOpenBreaker => e
115
+ logger.warn("Lumberjack input: The circuit breaker has detected a slowdown or stall in the pipeline, the input is closing the current connection and rejecting new connection until the pipeline recover.", :exception => e.class)
116
+ rescue => e # If we have a malformed packet we should handle that so the input doesn't crash completely.
117
+ @logger.error("Lumberjack input: unhandled exception", :exception => e, :backtrace => e.backtrace)
115
118
  end
116
119
  end
117
120
  end
@@ -9,7 +9,7 @@ module LogStash
9
9
  class SizedQueueTimeout
10
10
  class TimeoutError < StandardError; end
11
11
 
12
- DEFAULT_TIMEOUT = 2 # in seconds
12
+ DEFAULT_TIMEOUT = 5 # in seconds
13
13
 
14
14
  def initialize(max_size, options = {})
15
15
  # `concurrent-ruby` are deprecating the `Condition`
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-input-lumberjack'
4
- s.version = '1.0.3'
4
+ s.version = '1.0.4'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Receive events using the lumberjack protocol."
7
7
  s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_runtime_dependency "logstash-core", '>= 1.4.0', '< 2.0.0'
24
24
 
25
25
  s.add_runtime_dependency 'logstash-codec-plain'
26
- s.add_runtime_dependency 'jls-lumberjack', ['>=0.0.23']
26
+ s.add_runtime_dependency 'jls-lumberjack', ['>=0.0.24']
27
27
  s.add_runtime_dependency "concurrent-ruby"
28
28
 
29
29
  s.add_development_dependency 'logstash-devutils'
@@ -7,6 +7,7 @@ require "logstash/codecs/multiline"
7
7
  require "logstash/event"
8
8
  require "lumberjack/client"
9
9
 
10
+ Thread.abort_on_exception = true
10
11
  describe LogStash::Inputs::Lumberjack do
11
12
  let(:connection) { double("connection") }
12
13
  let(:certificate) { LogStashTest.certificate }
@@ -41,7 +42,7 @@ describe LogStash::Inputs::Lumberjack do
41
42
  let(:codec) { LogStash::Codecs::Multiline.new("pattern" => '\n', "what" => "previous") }
42
43
  it "clone the codec per connection" do
43
44
  expect(lumberjack.codec).to receive(:clone).once
44
- expect(lumberjack).to receive(:invoke).and_throw(:msg)
45
+ expect(lumberjack).to receive(:invoke) { break }
45
46
  lumberjack.run(queue)
46
47
  end
47
48
  end
@@ -14,33 +14,55 @@ describe LogStash::CircuitBreaker do
14
14
 
15
15
  subject { LogStash::CircuitBreaker.new("testing", options) }
16
16
 
17
+ context "when the breaker is closed" do
18
+ it "closed by default" do
19
+ expect(subject.closed?).to eq(true)
20
+ end
17
21
 
18
- it "closed by default" do
19
- expect(subject.closed?).to eq(true)
20
- end
21
-
22
- context "when having too many errors" do
23
- let(:future_time) { Time.now + 3600 }
24
- before do
25
- subject.execute do
26
- raise DummyErrorTest
27
- end
22
+ it "always raise an exception if an errors occur" do
23
+ expect {
24
+ subject.execute do
25
+ raise DummyErrorTest
26
+ end
27
+ }.to raise_error(LogStash::CircuitBreaker::HalfOpenBreaker)
28
28
  end
29
29
 
30
- it "raised an exception if we have too many errors" do
30
+ it "open if we pass the errors threadshold" do
31
+ expect {
32
+ subject.execute do
33
+ raise DummyErrorTest
34
+ end
35
+ }.to raise_error(LogStash::CircuitBreaker::HalfOpenBreaker)
36
+
31
37
  expect {
32
38
  subject.execute do
33
39
  raise DummyErrorTest
34
40
  end
35
41
  }.to raise_error(LogStash::CircuitBreaker::OpenBreaker)
36
42
  end
43
+ end
44
+
45
+ context "When the breaker is open" do
46
+ let(:future_time) { Time.now + 3600 }
47
+
48
+ before do
49
+ # trip the breaker
50
+ (error_threshold + 1).times do
51
+ begin
52
+ subject.execute do
53
+ raise DummyErrorTest
54
+ end
55
+ rescue
56
+ end
57
+ end
58
+ end
37
59
 
38
- it "sets the breaker to open" do
60
+ it "#closed? should return false" do
39
61
  expect(subject.closed?).to eq(false)
40
62
  end
41
63
 
42
64
  it "resets the breaker after the time before retry" do
43
- expect(Time).to receive(:now).at_least(1).and_return(future_time)
65
+ expect(Time).to receive(:now).at_least(2).and_return(future_time)
44
66
  expect(subject.closed?).to eq(true)
45
67
  end
46
68
 
@@ -51,7 +73,7 @@ describe LogStash::CircuitBreaker do
51
73
  subject.execute do
52
74
  runned = true
53
75
  end
54
- rescue LogStash::CircuitBreaker::OpenBreaker
76
+ rescue LogStash::CircuitBreaker::OpenBreaker
55
77
  end
56
78
 
57
79
  expect(runned).to eq(false)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-lumberjack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-31 00:00:00.000000000 Z
11
+ date: 2015-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logstash-core
@@ -50,12 +50,12 @@ dependencies:
50
50
  requirements:
51
51
  - - '>='
52
52
  - !ruby/object:Gem::Version
53
- version: 0.0.23
53
+ version: 0.0.24
54
54
  requirement: !ruby/object:Gem::Requirement
55
55
  requirements:
56
56
  - - '>='
57
57
  - !ruby/object:Gem::Version
58
- version: 0.0.23
58
+ version: 0.0.24
59
59
  prerelease: false
60
60
  type: :runtime
61
61
  - !ruby/object:Gem::Dependency