logstash-output-newrelic 1.0.9 → 1.1.1
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 +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
|