logstash-output-newrelic 1.0.9 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/lib/logstash/outputs/newrelic.rb +15 -33
- data/lib/logstash/outputs/newrelic_version/version.rb +1 -1
- data/spec/outputs/newrelic_spec.rb +44 -65
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45a98fd90dd92f095b34d4593459e6b5587ab779c331597c291ea3b94ad4291e
|
4
|
+
data.tar.gz: f7f612da2d0040da95ca329c25e6dae097762246f5fa5061ad01082d22df0733
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 816c2f5fa309328ffdf78f58894885cf791c3f8fb91867620e8494e1761e2ca4b8d9744b4c6a385c13482a7654ecfc677fb0792dc4174141e0b92beb6bc757ec
|
7
|
+
data.tar.gz: b2b41b31f4af73a28bdad58416c10f0a25e54a56bc295987d96c825268bce4bcfcdc01e80ca0027dfaa71af95edb9c88d8fe254ad5be6aa6b025b692742d50b1
|
data/README.md
CHANGED
@@ -38,11 +38,13 @@ output {
|
|
38
38
|
| Property | Description | Default value |
|
39
39
|
|---|---|---|
|
40
40
|
| concurrent_requests | The number of threads to make requests from | 1 |
|
41
|
-
| retries | The maximum number of times to retry a failed request, exponentially increasing delay between each retry | 5 |
|
42
|
-
| retry_seconds | The inital delay between retries, in seconds | 5 |
|
43
|
-
| max_delay | The maximum delay between retries, in seconds | 30 |
|
44
41
|
| base_uri | New Relic ingestion endpoint | https://log-api.newrelic.com/log/v1 |
|
45
42
|
|
43
|
+
|
44
|
+
### EU plugin configuration
|
45
|
+
|
46
|
+
When using this plugin in the EU override the base_uri with `http://log-api.eu.newrelic.com/log/v1`
|
47
|
+
|
46
48
|
## Testing
|
47
49
|
|
48
50
|
An easy way to test the plugin is to make sure Logstash is getting input from a log file you
|
@@ -13,10 +13,8 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
|
|
13
13
|
|
14
14
|
config_name "newrelic"
|
15
15
|
|
16
|
-
config :api_key, :validate => :password, :required =>
|
17
|
-
config :
|
18
|
-
config :max_delay, :validate => :number, :default => 30
|
19
|
-
config :retries, :validate => :number, :default => 5
|
16
|
+
config :api_key, :validate => :password, :required => false
|
17
|
+
config :license_key, :validate => :password, :required => false
|
20
18
|
config :concurrent_requests, :validate => :number, :default => 1
|
21
19
|
config :base_uri, :validate => :string, :default => "https://log-api.newrelic.com/log/v1"
|
22
20
|
|
@@ -24,11 +22,17 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
|
|
24
22
|
|
25
23
|
def register
|
26
24
|
@end_point = URI.parse(@base_uri)
|
25
|
+
if @api_key.nil? && @license_key.nil?
|
26
|
+
raise LogStash::ConfigurationError, "Must provide a license key or api key", caller
|
27
|
+
end
|
28
|
+
auth = {
|
29
|
+
@api_key.nil? ? 'X-License-Key': 'X-Insert-Key' =>
|
30
|
+
@api_key.nil? ? @license_key.value : @api_key.value
|
31
|
+
}
|
27
32
|
@header = {
|
28
|
-
'X-Insert-Key' => @api_key.value,
|
29
33
|
'X-Event-Source' => 'logs',
|
30
34
|
'Content-Encoding' => 'gzip'
|
31
|
-
}.freeze
|
35
|
+
}.merge(auth).freeze
|
32
36
|
@executor = java.util.concurrent.Executors.newFixedThreadPool(@concurrent_requests)
|
33
37
|
@semaphor = java.util.concurrent.Semaphore.new(@concurrent_requests)
|
34
38
|
end
|
@@ -102,41 +106,19 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
|
|
102
106
|
gzip = Zlib::GzipWriter.new(io)
|
103
107
|
gzip << [payload].to_json
|
104
108
|
gzip.close
|
105
|
-
|
109
|
+
nr_send(io.string)
|
106
110
|
ensure
|
107
111
|
@semaphor.release()
|
108
112
|
end
|
109
113
|
end
|
110
114
|
end
|
111
115
|
|
112
|
-
def
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
def sleep_duration(attempt)
|
117
|
-
if attempt == 0
|
118
|
-
return 0
|
119
|
-
end
|
120
|
-
|
121
|
-
[max_delay, (2 ** (attempt - 1)) * retry_seconds].min
|
122
|
-
end
|
123
|
-
|
124
|
-
def sleep_on_retry(attempt)
|
125
|
-
duration = sleep_duration(attempt)
|
126
|
-
if duration > 0
|
127
|
-
sleep duration
|
116
|
+
def handle_response(response)
|
117
|
+
if !(200 <= response.code.to_i && response.code.to_i < 300)
|
118
|
+
@logger.error("Request returned " + response.code + " " + response.body)
|
128
119
|
end
|
129
120
|
end
|
130
121
|
|
131
|
-
def attempt_send(payload, attempt)
|
132
|
-
sleep_on_retry(attempt)
|
133
|
-
attempt_send(payload, attempt + 1) unless was_successful?(nr_send(payload)) if should_retry?(attempt)
|
134
|
-
end
|
135
|
-
|
136
|
-
def was_successful?(response)
|
137
|
-
200 <= response.code.to_i && response.code.to_i < 300
|
138
|
-
end
|
139
|
-
|
140
122
|
def nr_send(payload)
|
141
123
|
http = Net::HTTP.new(@end_point.host, 443)
|
142
124
|
request = Net::HTTP::Post.new(@end_point.request_uri)
|
@@ -144,6 +126,6 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
|
|
144
126
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
145
127
|
@header.each {|k, v| request[k] = v}
|
146
128
|
request.body = payload
|
147
|
-
http.request(request)
|
129
|
+
handle_response(http.request(request))
|
148
130
|
end
|
149
131
|
end # class LogStash::Outputs::NewRelic
|
@@ -7,6 +7,48 @@ require "logstash/event"
|
|
7
7
|
require "webmock/rspec"
|
8
8
|
require "zlib"
|
9
9
|
|
10
|
+
describe LogStash::Outputs::NewRelic do
|
11
|
+
let (:base_uri) { "https://testing-example-collector.com" }
|
12
|
+
let (:retry_seconds) { 0 }
|
13
|
+
# Don't sleep in tests, to keep tests fast. We have a test for the method that produces the sleep duration between retries.
|
14
|
+
let (:max_delay) { 0 }
|
15
|
+
let (:retries) { 3 }
|
16
|
+
let (:license_key) { 'cool-guy' }
|
17
|
+
let (:simple_config) {
|
18
|
+
{
|
19
|
+
"base_uri" => base_uri,
|
20
|
+
"license_key" => license_key
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
before(:each) do
|
26
|
+
@newrelic_output = LogStash::Plugin.lookup("output", "newrelic").new(simple_config)
|
27
|
+
@newrelic_output.register
|
28
|
+
end
|
29
|
+
|
30
|
+
after(:each) do
|
31
|
+
if @newrelic_output
|
32
|
+
@newrelic_output.shutdown
|
33
|
+
end
|
34
|
+
end
|
35
|
+
context "license key tests" do
|
36
|
+
it "sets license key when given in the header" do
|
37
|
+
stub_request(:any, base_uri).to_return(status: 200)
|
38
|
+
|
39
|
+
event = LogStash::Event.new({:message => "Test message" })
|
40
|
+
@newrelic_output.multi_receive([event])
|
41
|
+
|
42
|
+
wait_for(a_request(:post, base_uri)
|
43
|
+
.with(headers: {
|
44
|
+
"X-License-Key" => license_key,
|
45
|
+
"X-Event-Source" => "logs",
|
46
|
+
"Content-Encoding" => "gzip",
|
47
|
+
})).to have_been_made
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
10
52
|
describe LogStash::Outputs::NewRelic do
|
11
53
|
let (:api_key) { "someAccountKey" }
|
12
54
|
let (:base_uri) { "https://testing-example-collector.com" }
|
@@ -18,9 +60,6 @@ describe LogStash::Outputs::NewRelic do
|
|
18
60
|
{
|
19
61
|
"api_key" => api_key,
|
20
62
|
"base_uri" => base_uri,
|
21
|
-
"retries" => retries,
|
22
|
-
"retry_seconds" => retry_seconds,
|
23
|
-
"max_delay" => max_delay,
|
24
63
|
}
|
25
64
|
}
|
26
65
|
|
@@ -71,8 +110,8 @@ describe LogStash::Outputs::NewRelic do
|
|
71
110
|
it "requires api_key" do
|
72
111
|
no_api_key_config = {
|
73
112
|
}
|
74
|
-
|
75
|
-
expect {
|
113
|
+
output = LogStash::Plugin.lookup("output", "newrelic").new(no_api_key_config)
|
114
|
+
expect { output.register }.to raise_error LogStash::ConfigurationError
|
76
115
|
end
|
77
116
|
end
|
78
117
|
|
@@ -225,66 +264,6 @@ describe LogStash::Outputs::NewRelic do
|
|
225
264
|
end
|
226
265
|
end
|
227
266
|
|
228
|
-
context "retry" do
|
229
|
-
it "sleep periods double each time up to max time" do
|
230
|
-
specific_config = simple_config.clone
|
231
|
-
# Use non-trivial times -- they can be big, since this test doesn't do any sleeping, just
|
232
|
-
# tests the sleep duration
|
233
|
-
specific_config["max_delay"] = 60
|
234
|
-
specific_config["retry_seconds"] = 5
|
235
|
-
|
236
|
-
# Create a new plugin with this specific config that has longer retry sleep
|
237
|
-
# configuration than we normally want
|
238
|
-
@newrelic_output.shutdown
|
239
|
-
@newrelic_output = LogStash::Plugin.lookup("output", "newrelic").new(specific_config)
|
240
|
-
@newrelic_output.register
|
241
|
-
|
242
|
-
expect(@newrelic_output.sleep_duration(0)).to equal(0)
|
243
|
-
expect(@newrelic_output.sleep_duration(1)).to equal(5)
|
244
|
-
expect(@newrelic_output.sleep_duration(2)).to equal(10)
|
245
|
-
expect(@newrelic_output.sleep_duration(3)).to equal(20)
|
246
|
-
expect(@newrelic_output.sleep_duration(4)).to equal(40)
|
247
|
-
expect(@newrelic_output.sleep_duration(5)).to equal(60)
|
248
|
-
expect(@newrelic_output.sleep_duration(6)).to equal(60) # Never gets bigger than this
|
249
|
-
end
|
250
|
-
|
251
|
-
it "first call fails, should retry" do
|
252
|
-
stub_request(:any, base_uri)
|
253
|
-
.to_return(status: 500)
|
254
|
-
.to_return(status: 200)
|
255
|
-
|
256
|
-
event = LogStash::Event.new({ "message" => "Test message" })
|
257
|
-
@newrelic_output.multi_receive([event])
|
258
|
-
|
259
|
-
wait_for(a_request(:post, base_uri)).to have_been_made.times(2)
|
260
|
-
end
|
261
|
-
|
262
|
-
it "first two calls fail, should retry" do
|
263
|
-
stub_request(:any, base_uri)
|
264
|
-
.to_return(status: 500)
|
265
|
-
.to_return(status: 500)
|
266
|
-
.to_return(status: 200)
|
267
|
-
|
268
|
-
event = LogStash::Event.new({ "message" => "Test message" })
|
269
|
-
@newrelic_output.multi_receive([event])
|
270
|
-
|
271
|
-
wait_for(a_request(:post, base_uri)).to have_been_made.times(3)
|
272
|
-
end
|
273
|
-
|
274
|
-
it "all calls fails, should stop retrying at some point" do
|
275
|
-
stub_request(:any, base_uri)
|
276
|
-
.to_return(status: 500)
|
277
|
-
|
278
|
-
event = LogStash::Event.new({ "message" => "Test message" })
|
279
|
-
@newrelic_output.multi_receive([event])
|
280
|
-
|
281
|
-
# This may not fail if the wait_for is called exactly when there have been 'retries' calls.
|
282
|
-
# However, with zero sleep time (max_delay=0), on a laptop the POST was done 2000+ times by the
|
283
|
-
# time this was executed
|
284
|
-
wait_for(a_request(:post, base_uri)).to have_been_made.times(retries)
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
267
|
context "error handling" do
|
289
268
|
it "continues through errors, future calls should still succeed" do
|
290
269
|
stub_request(:any, base_uri)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-newrelic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- New Relic Logging Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|