logstash-output-udp 3.0.6 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03da8b46cdf2746435b5822fce43ac3310c990748e316c53e2d0068cf29a682c
4
- data.tar.gz: a50dae007a3c6db9c856acd7dd058b73765c21b04180a5ff6bc834000830f6a3
3
+ metadata.gz: f6d89de043149e0924a181b904dfd2d56766fd52c77ffb7ad623c27c3ee18df4
4
+ data.tar.gz: 94ad42d0d5b5d9c2bda8714318b3ca79899b8889e1db69e1e2a4c71358059f2d
5
5
  SHA512:
6
- metadata.gz: 7543ed4c366a4f9dde7916c560de384fb4991f337d4fc534c55690b242df85d10c8b559a7612924dcad746c4d2d770115b2a0b8d45bd10c7c4614e6bc9c23c0c
7
- data.tar.gz: 840f950c945e73a96de90afa3fd25f3b8e2b2df3ac204b576bbb1b2ab7458e2ddd264b3b815b968ff1724ec170461763d58362c3f86766984553a3b59dacb792
6
+ metadata.gz: ead3de8b14b596c8cac1330ca63737232fb8d8ce5e2564f5aed6cedb54e811662dae7ba2a2a36680ba6aba9d11aa1ce6f14e1e35888076d01907de6976fb5e2d
7
+ data.tar.gz: 71d2903845ceed02477768fe9eea5ca8c27a0875ba064b96a2d396331c726d1bbaa0aca88d64ed9df77b70a7ab30b0523ceaf67a648436f87449a33ba4b9cf26
@@ -1,3 +1,7 @@
1
+ ## 3.1.0
2
+ - Fixed plugin crash upon socket write exception [#10](https://github.com/logstash-plugins/logstash-output-udp/pull/10)
3
+ - Added support for the 'retry_count' and 'retry_backoff_ms' options [#12](https://github.com/logstash-plugins/logstash-output-udp/pull/12)
4
+
1
5
  ## 3.0.6
2
6
  - Docs: Set the default_codec doc attribute.
3
7
 
@@ -23,7 +23,14 @@ include::{include_path}/plugin_header.asciidoc[]
23
23
 
24
24
  Send events over UDP
25
25
 
26
- Keep in mind that UDP will lose messages.
26
+ Keep in mind that UDP does not provide delivery or duplicate protection guarantees.
27
+ Even when this plugin succeeds at writing to the UDP socket, there is no guarantee that
28
+ the recipient will receive exactly one copy of the event.
29
+
30
+ When this plugin fails to write to the UDP socket, by default the event will be dropped
31
+ and the error message will be logged. The <<plugins-{type}s-{plugin}-retry_count>> option
32
+ in conjunction with the <<plugins-{type}s-{plugin}-retry_backoff_ms>> option can be used
33
+ to retry a failed write for a number of times before dropping the event.
27
34
 
28
35
  [id="plugins-{type}s-{plugin}-options"]
29
36
  ==== Udp Output Configuration Options
@@ -35,6 +42,8 @@ This plugin supports the following configuration options plus the <<plugins-{typ
35
42
  |Setting |Input type|Required
36
43
  | <<plugins-{type}s-{plugin}-host>> |<<string,string>>|Yes
37
44
  | <<plugins-{type}s-{plugin}-port>> |<<number,number>>|Yes
45
+ | <<plugins-{type}s-{plugin}-retry_count>> |<<number,number>>|No
46
+ | <<plugins-{type}s-{plugin}-retry_backoff_ms>> |<<number,number>>|No
38
47
  |=======================================================================
39
48
 
40
49
  Also see <<plugins-{type}s-{plugin}-common-options>> for a list of options supported by all
@@ -60,7 +69,21 @@ The address to send messages to
60
69
 
61
70
  The port to send messages on
62
71
 
72
+ [id="plugins-{type}s-{plugin}-retry_count"]
73
+ ===== `retry_count`
74
+
75
+ * Value type is <<number,number>>
76
+ * Default value is `0`
77
+
78
+ The number of times to retry a failed UPD socket write
79
+
80
+ [id="plugins-{type}s-{plugin}-retry_backoff_ms"]
81
+ ===== `retry_backoff_ms`
82
+
83
+ * Value type is <<number,number>>
84
+ * Default value is `10`
63
85
 
86
+ The amount of time to wait in milliseconds before attempting to retry a failed UPD socket write
64
87
 
65
88
  [id="plugins-{type}s-{plugin}-common-options"]
66
89
  include::{include_path}/{type}.asciidoc[]
@@ -5,7 +5,7 @@ require "socket"
5
5
 
6
6
  # Send events over UDP
7
7
  #
8
- # Keep in mind that UDP will lose messages.
8
+ # Keep in mind that UDP is a lossy protocol
9
9
  class LogStash::Outputs::UDP < LogStash::Outputs::Base
10
10
  config_name "udp"
11
11
 
@@ -17,18 +17,58 @@ class LogStash::Outputs::UDP < LogStash::Outputs::Base
17
17
  # The port to send messages on
18
18
  config :port, :validate => :number, :required => true
19
19
 
20
- public
20
+ # The number of times to retry a failed UPD socket write
21
+ config :retry_count, :validate => :number, :default => 0
22
+
23
+ # The amount of time to wait in milliseconds before attempting to retry a failed UPD socket write
24
+ config :retry_backoff_ms, :validate => :number, :default => 100
25
+
21
26
  def register
22
27
  @socket = UDPSocket.new
28
+
23
29
  @codec.on_event do |event, payload|
24
- @socket.send(payload, 0, @host, @port)
30
+ socket_send(payload)
25
31
  end
26
32
  end
27
33
 
28
34
  def receive(event)
29
-
30
- return if event == LogStash::SHUTDOWN
31
35
  @codec.encode(event)
32
36
  end
33
37
 
34
- end # class LogStash::Outputs::Stdout
38
+ private
39
+
40
+ def socket_send(payload)
41
+ send_count = 0
42
+ begin
43
+ send_count += 1
44
+ @socket.send(payload, 0, @host, @port)
45
+ rescue Errno::EMSGSIZE => e
46
+ logger.error("Failed to send event, message size of #{payload.size} too long", error_hash(e, payload))
47
+ rescue => e
48
+ if @retry_count > 0 && send_count <= @retry_count
49
+ logger.warn("Failed to send event, retrying:", error_hash(e, payload))
50
+ sleep(@retry_backoff_ms / 1000.0)
51
+ retry
52
+ else
53
+ logger.error("Failed to send event:", error_hash(e, payload))
54
+ end
55
+ end
56
+ end
57
+
58
+ MAX_DEBUG_PAYLOAD = 1000
59
+
60
+ def error_hash(error, payload)
61
+ error_hash = {
62
+ :error => error.inspect,
63
+ :backtrace => error.backtrace.first(10)
64
+ }
65
+ if logger.debug?
66
+ error_hash.merge(
67
+ :event_payload =>
68
+ payload.length > MAX_DEBUG_PAYLOAD ? "#{payload[0...MAX_DEBUG_PAYLOAD]}...<TRUNCATED>" : payload
69
+ )
70
+ else
71
+ error_hash
72
+ end
73
+ end
74
+ end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-output-udp'
4
- s.version = '3.0.6'
4
+ s.version = '3.1.0'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Sends events over UDP"
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/logstash-plugin install gemname. This gem is not a stand-alone program"
@@ -3,18 +3,17 @@ require_relative "../spec_helper"
3
3
 
4
4
  describe LogStash::Outputs::UDP do
5
5
 
6
+ subject { described_class.new(config) }
6
7
  let(:host) { "localhost" }
7
8
  let(:port) { rand(1024..65535) }
9
+ let(:config) {{ "host" => host, "port" => port}}
8
10
 
9
11
  it "should register without errors" do
10
- plugin = LogStash::Plugin.lookup("output", "udp").new({ "host" => host, "port" => port})
12
+ plugin = LogStash::Plugin.lookup("output", "udp").new(config)
11
13
  expect { plugin.register }.to_not raise_error
12
14
  end
13
15
 
14
16
  describe "#send" do
15
-
16
- subject { LogStash::Outputs::UDP.new({"host" => host, "port" => port}) }
17
-
18
17
  let(:properties) { { "message" => "This is a message!"} }
19
18
  let(:event) { LogStash::Event.new(properties) }
20
19
 
@@ -24,7 +23,71 @@ describe LogStash::Outputs::UDP do
24
23
 
25
24
  it "should receive the generated event" do
26
25
  expect(subject.instance_variable_get("@socket")).to receive(:send).with(kind_of(String), 0, host, port)
26
+ expect(subject.instance_variable_get("@logger")).not_to receive(:error)
27
+ subject.receive(event)
28
+ end
29
+ end
30
+
31
+ describe "retries" do
32
+ let(:event) { LogStash::Event.new("message" => "test") }
33
+ let(:config) {{ "host" => host, "port" => port}}
34
+
35
+ before(:each) do
36
+ subject.register
37
+ end
38
+
39
+ context "not using :retry_count" do
40
+ it "should not retry upon send exception by default" do
41
+ allow(subject.instance_variable_get("@socket")).to receive(:send).once.and_raise(IOError)
42
+ expect(subject.instance_variable_get("@logger")).to receive(:error).once
43
+ subject.receive(event)
44
+ end
45
+ end
46
+
47
+ context "using :retry_count" do
48
+ let(:backoff) { 10 }
49
+ let(:retry_count) { 5 }
50
+ let(:config) {{ "host" => host, "port" => port, "retry_count" => retry_count, "retry_backoff_ms" => backoff}}
51
+
52
+ it "should retry upon send exception" do
53
+ allow(subject.instance_variable_get("@socket")).to receive(:send).exactly(retry_count + 1).times.and_raise(IOError)
54
+ expect(subject.instance_variable_get("@logger")).to receive(:warn).exactly(retry_count).times
55
+ expect(subject.instance_variable_get("@logger")).to receive(:error).once
56
+ expect(subject).to receive(:sleep).with(backoff / 1000.0).exactly(retry_count).times
57
+ subject.receive(event)
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "large message" do
63
+ let(:properties) { { "message" => "0" * 65_536 } }
64
+ let(:event) { LogStash::Event.new(properties) }
65
+
66
+ before(:each) do
67
+ subject.register
68
+ end
69
+
70
+ it "should handle the error and log when an error is received" do
71
+ expect(subject.instance_variable_get("@logger")).to receive(:error)
27
72
  subject.receive(event)
28
73
  end
74
+
75
+ it "should log a truncated payload with debug logging when an error is received and the message is too long" do
76
+ expect(subject.instance_variable_get("@logger")).to receive(:debug?).and_return(true)
77
+ expect(subject.instance_variable_get("@logger")).to receive(:error) do |_, hash|
78
+ expect(hash).to include(:event_payload)
79
+ expect(hash[:event_payload]).to include("TRUNCATED")
80
+ end
81
+ subject.receive(event)
82
+ end
83
+
84
+ it "should not log a payload with debug logging when an error is received" do
85
+ expect(subject.instance_variable_get("@logger")).to receive(:debug?).and_return(false)
86
+ expect(subject.instance_variable_get("@logger")).to receive(:error) do |_, hash|
87
+ expect(hash).not_to include(:event_payload)
88
+ end
89
+ subject.receive(event)
90
+ end
91
+
29
92
  end
30
93
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-udp
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.6
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-06 00:00:00.000000000 Z
11
+ date: 2019-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -99,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
99
  version: '0'
100
100
  requirements: []
101
101
  rubyforge_project:
102
- rubygems_version: 2.6.11
102
+ rubygems_version: 2.6.13
103
103
  signing_key:
104
104
  specification_version: 4
105
105
  summary: Sends events over UDP