logstash-output-newrelic 1.0.8 → 1.1.4

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: 15a58f1472c4f00bc1decbd672cf520a247d192eb6b31b348bc6daa77f2ea27c
4
- data.tar.gz: f71834a29f1507c3948d9044826b7c2cc23e249121b57dacd65103bc8d22f742
3
+ metadata.gz: f099ad9c408ec722141c72268c3bdc038adbe98c0760da028f5149f87077a0eb
4
+ data.tar.gz: 45817bcb9ada5fa8ca81a57f102878fc752111f7a0b7e3d3a7fc9c681a6df480
5
5
  SHA512:
6
- metadata.gz: 9db4eb7268c9c401932ff4bfd2055ca8475c69c962d3a99f41dec89e51833f6b9c527eb887b65d520d20e322401798a231cb5ae53c7d8c78c3bc6581cef77d29
7
- data.tar.gz: b95f9564bd9f6c51d38a3995c86733b78cdaa9cb474ffda178a05006d6f10f47e4fbdb31e1934e0e4e9f31821487dd26be65a49f617c503add87fa394d689982
6
+ metadata.gz: de3784b9f1ca8300c99a7adea011e95b5ac5140ffd01d7a18dfc6cf5c5c5bbd2767cc4ac519e763bea7e0e7d12a509b9dcde98cc890b52d41ae901d750086511
7
+ data.tar.gz: acfc744ccc74de945848c3b76ade20b6e858fce52d1951e1533b302a2c55b4ae2f6156f507a8b0f949967981a5a304f293973f632f8c3863ab04fc1f1463a82b
@@ -14,14 +14,6 @@
14
14
  * Run tests: `jruby -S bundle exec rspec`
15
15
  * Build the gem: `jruby -S gem build logstash-output-newrelic.gemspec`
16
16
 
17
- ## Pushing changes to the public repo
18
- After updating the New Relic repo with changes, changes will need to be pushed to the public GitHub repo at: https://github.com/newrelic/logstash-output-plugin
19
-
20
- * `git remote add public git@github.com:newrelic/logstash-output-plugin.git`
21
- * `git push public master:name-of-branch-to-create`
22
- * Create a PR from that branch in https://github.com/newrelic/logstash-output-plugin
23
- * Get the PR reviewed, merged, and delete the branch!
24
-
25
17
  # Testing it with a local Logstash install
26
18
 
27
19
  Note: you may need to run the following commands outside of your checkout, since these should not
@@ -31,10 +23,4 @@ be run with the JRuby version that you've configured your checkout to use (by us
31
23
  * Add new version: `logstash-plugin install logstash-output-newrelic-<version>.gem`
32
24
  * Restart logstash: For Homebrew: `brew services restart logstash`
33
25
  * Cause a change that you've configured Logstash to pick up (for instance, append to a file you're having it monitor)
34
- * Look in `https://staging-one.newrelic.com/launcher/logger.log-launcher` for your log message
35
-
36
- # Push changes to RubyGems
37
- After updating the source code and gem version in `version.rb`, push the changes to RubyGems. There is an older version of the gem that we do not want to overwrite — `version 0.9.1`. Please be sure you are publishing changes to the correct gem i.e. `version 1.0.0` or higher. Note, you must be a gem owner to publish changes on [RubyGems.org](https://rubygems.org/profiles/NR-LOGGING). Once you've created the account, you will need to run `gem signin` to login to RubyGems via the command line.
38
-
39
- * Build the gem: `gem build logstash-output-newrelic.gemspec`
40
- * Publish the gem: `gem push logstash-output-newrelic-<VERSION>.gem` with the updated version (ex: `gem push logstash-output-newrelic-1.0.0.gem`)
26
+ * Look in `https://one.newrelic.com/launcher/logger.log-launcher` for your log message
data/README.md CHANGED
@@ -11,9 +11,11 @@ Versions of this plugin less than 1.0.0 are unsupported.
11
11
 
12
12
  ## Configuration
13
13
 
14
- Add the following block to your logstash.conf (with your specific API Insert key), then restart Logstash.
14
+ Add one of the following blocks to your logstash.conf (with your specific key), then restart Logstash.
15
15
  There are other optional configuration properties, see below.
16
16
 
17
+ ### Using API Insert Key
18
+
17
19
  Get your API Insert Key:
18
20
  `https://insights.newrelic.com/accounts/<ACCOUNT_ID>/manage/api_keys`
19
21
 
@@ -26,23 +28,41 @@ output {
26
28
  }
27
29
  ```
28
30
 
31
+ ### Using License Key
32
+
33
+ Get your License Key:
34
+ `https://rpm.newrelic.com/accounts/<ACCOUNT_ID>`
35
+
36
+ Example:
37
+ ```rb
38
+ output {
39
+ newrelic {
40
+ license_key => "<LICENSE_KEY>"
41
+ }
42
+ }
43
+ ```
29
44
 
30
45
  ### Required plugin configuration
31
46
 
47
+ Exactly one of the following:
48
+
32
49
  | Property | Description |
33
50
  |---|---|
34
51
  | api_key | your New Relic API Insert key |
52
+ | license_key | your New Relic License key |
35
53
 
36
54
  ### Optional plugin configuration
37
55
 
38
56
  | Property | Description | Default value |
39
57
  |---|---|---|
40
58
  | 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
59
  | base_uri | New Relic ingestion endpoint | https://log-api.newrelic.com/log/v1 |
45
60
 
61
+
62
+ ### EU plugin configuration
63
+
64
+ When using this plugin in the EU override the base_uri with `https://log-api.eu.newrelic.com/log/v1`
65
+
46
66
  ## Testing
47
67
 
48
68
  An easy way to test the plugin is to make sure Logstash is getting input from a log file you
@@ -57,30 +77,3 @@ input {
57
77
  * Restart Logstash
58
78
  * Append a test log message to your log file: `echo "test message" >> /path/to/your/log/file`
59
79
  * Search New Relic Logs for `"test message"`
60
-
61
- ## JSON message parsing
62
-
63
- This plugin will attempt to parse any 'message' attribute as JSON -- if it is JSON, it will be parsed and
64
- the JSON attributes will be added to the event.
65
-
66
- For example, the event:
67
- ```
68
- {
69
- "timestamp": 1562767499238,
70
- "message": "{\"service-name\": \"login-service\", \"user\": {\"id\": 123, \"name\": \"alice\"}}"
71
- }
72
-
73
- ```
74
-
75
- Will be treated as:
76
- ```
77
- {
78
- "timestamp": 1562767499238,
79
- "message": "{\"service-name\": \"my-service\", \"user\": {\"id\": 123, \"name\": \"alice\"}}",
80
- "service-name": "login-service",
81
- "user": {
82
- "id": 123,
83
- "name": "alice"
84
- }
85
- }
86
- ```
@@ -0,0 +1,24 @@
1
+ require 'bigdecimal'
2
+
3
+ class BigDecimal
4
+ # Floating-point numbers that go through the 'json' Logstash filter get automatically converted into BigDecimals.
5
+ # Example of such a filter:
6
+ #
7
+ # filter {
8
+ # json {
9
+ # source => "message"
10
+ # }
11
+ # }
12
+ #
13
+ # The problem is that { "value" => BigDecimal('0.12345') } gets serialized into { "value": "0.12345e0"}. We do
14
+ # want to keep floating point numbers serialized as floating point numbers, even at the expense of loosing a little
15
+ # bit of precision during the conversion. So, in the above example, the correct serialization would be:
16
+ # { "value": 0.12345}
17
+ def to_json(options = nil) #:nodoc:
18
+ if finite?
19
+ self.to_f.to_s
20
+ else
21
+ 'null'
22
+ end
23
+ end
24
+ end
@@ -6,6 +6,7 @@ require 'uri'
6
6
  require 'zlib'
7
7
  require 'json'
8
8
  require 'java'
9
+ require_relative './config/bigdecimal_patch'
9
10
 
10
11
  class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
11
12
  java_import java.util.concurrent.Executors;
@@ -13,10 +14,8 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
13
14
 
14
15
  config_name "newrelic"
15
16
 
16
- config :api_key, :validate => :password, :required => true
17
- config :retry_seconds, :validate => :number, :default => 5
18
- config :max_delay, :validate => :number, :default => 30
19
- config :retries, :validate => :number, :default => 5
17
+ config :api_key, :validate => :password, :required => false
18
+ config :license_key, :validate => :password, :required => false
20
19
  config :concurrent_requests, :validate => :number, :default => 1
21
20
  config :base_uri, :validate => :string, :default => "https://log-api.newrelic.com/log/v1"
22
21
 
@@ -24,23 +23,31 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
24
23
 
25
24
  def register
26
25
  @end_point = URI.parse(@base_uri)
26
+ if @api_key.nil? && @license_key.nil?
27
+ raise LogStash::ConfigurationError, "Must provide a license key or api key", caller
28
+ end
29
+ auth = {
30
+ @api_key.nil? ? 'X-License-Key': 'X-Insert-Key' =>
31
+ @api_key.nil? ? @license_key.value : @api_key.value
32
+ }
27
33
  @header = {
28
- 'X-Insert-Key' => @api_key.value,
29
34
  'X-Event-Source' => 'logs',
30
35
  'Content-Encoding' => 'gzip'
31
- }.freeze
36
+ }.merge(auth).freeze
32
37
  @executor = java.util.concurrent.Executors.newFixedThreadPool(@concurrent_requests)
33
38
  @semaphor = java.util.concurrent.Semaphore.new(@concurrent_requests)
34
39
  end
35
40
 
36
41
  # Used by tests so that the test run can complete (background threads prevent JVM exit)
37
42
  def shutdown
38
- @executor&.shutdown
39
- # We want this long enough to not have threading issues
40
- terminationWaitInSeconds = 10
41
- terminatedInTime = @executor&.awaitTermination(terminationWaitInSeconds, java.util.concurrent.TimeUnit::SECONDS)
42
- if !terminatedInTime
43
- raise "Did not shut down within #{terminationWaitInSeconds} seconds"
43
+ if @executor
44
+ @executor.shutdown
45
+ # We want this long enough to not have threading issues
46
+ terminationWaitInSeconds = 10
47
+ terminatedInTime = @executor.awaitTermination(terminationWaitInSeconds, java.util.concurrent.TimeUnit::SECONDS)
48
+ if !terminatedInTime
49
+ raise "Did not shut down within #{terminationWaitInSeconds} seconds"
50
+ end
44
51
  end
45
52
  end
46
53
 
@@ -100,39 +107,17 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
100
107
  gzip = Zlib::GzipWriter.new(io)
101
108
  gzip << [payload].to_json
102
109
  gzip.close
103
- attempt_send(io.string, 0)
110
+ nr_send(io.string)
104
111
  ensure
105
112
  @semaphor.release()
106
113
  end
107
114
  end
108
115
  end
109
116
 
110
- def should_retry?(attempt)
111
- attempt < retries
112
- end
113
-
114
- def sleep_duration(attempt)
115
- if attempt == 0
116
- return 0
117
+ def handle_response(response)
118
+ if !(200 <= response.code.to_i && response.code.to_i < 300)
119
+ @logger.error("Request returned " + response.code + " " + response.body)
117
120
  end
118
-
119
- [max_delay, (2 ** (attempt - 1)) * retry_seconds].min
120
- end
121
-
122
- def sleep_on_retry(attempt)
123
- duration = sleep_duration(attempt)
124
- if duration > 0
125
- sleep duration
126
- end
127
- end
128
-
129
- def attempt_send(payload, attempt)
130
- sleep_on_retry(attempt)
131
- attempt_send(payload, attempt + 1) unless was_successful?(nr_send(payload)) if should_retry?(attempt)
132
- end
133
-
134
- def was_successful?(response)
135
- 200 <= response.code.to_i && response.code.to_i < 300
136
121
  end
137
122
 
138
123
  def nr_send(payload)
@@ -142,6 +127,6 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
142
127
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
143
128
  @header.each {|k, v| request[k] = v}
144
129
  request.body = payload
145
- http.request(request)
130
+ handle_response(http.request(request))
146
131
  end
147
132
  end # class LogStash::Outputs::NewRelic
@@ -1,7 +1,7 @@
1
1
  module LogStash
2
2
  module Outputs
3
3
  module NewRelicVersion
4
- VERSION = "1.0.8"
4
+ VERSION = "1.1.4"
5
5
  end
6
6
  end
7
7
  end
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_runtime_dependency "logstash-codec-plain"
27
27
  s.add_development_dependency "logstash-devutils"
28
28
  s.add_development_dependency "webmock"
29
+ s.add_development_dependency "rspec"
29
30
  s.add_development_dependency "rspec-wait"
30
-
31
+ s.add_development_dependency "rspec_junit_formatter"
31
32
  end
@@ -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
+ before(:each) do
25
+ @newrelic_output = LogStash::Plugin.lookup("output", "newrelic").new(simple_config)
26
+ @newrelic_output.register
27
+ end
28
+
29
+ after(:each) do
30
+ if @newrelic_output
31
+ @newrelic_output.shutdown
32
+ end
33
+ end
34
+
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
 
@@ -62,15 +101,17 @@ describe LogStash::Outputs::NewRelic do
62
101
  end
63
102
 
64
103
  after(:each) do
65
- @newrelic_output&.shutdown
104
+ if @newrelic_output
105
+ @newrelic_output.shutdown
106
+ end
66
107
  end
67
108
 
68
109
  context "validation of config" do
69
110
  it "requires api_key" do
70
111
  no_api_key_config = {
71
112
  }
72
-
73
- expect { LogStash::Plugin.lookup("output", "newrelic").new(no_api_key_config) }.to raise_error LogStash::ConfigurationError
113
+ output = LogStash::Plugin.lookup("output", "newrelic").new(no_api_key_config)
114
+ expect { output.register }.to raise_error LogStash::ConfigurationError
74
115
  end
75
116
  end
76
117
 
@@ -200,7 +241,7 @@ describe LogStash::Outputs::NewRelic do
200
241
 
201
242
  # Shut down the plugin so that it has the chance to send a request
202
243
  # (since we're verifying that nothing is sent)
203
- @newrelic_output&.shutdown
244
+ @newrelic_output.shutdown
204
245
 
205
246
  expect(a_request(:post, base_uri))
206
247
  .not_to have_been_made
@@ -223,80 +264,64 @@ describe LogStash::Outputs::NewRelic do
223
264
  end
224
265
  end
225
266
 
226
- context "retry" do
227
- it "sleep periods double each time up to max time" do
228
- specific_config = simple_config.clone
229
- # Use non-trivial times -- they can be big, since this test doesn't do any sleeping, just
230
- # tests the sleep duration
231
- specific_config["max_delay"] = 60
232
- specific_config["retry_seconds"] = 5
233
-
234
- # Create a new plugin with this specific config that has longer retry sleep
235
- # configuration than we normally want
236
- @newrelic_output&.shutdown
237
- @newrelic_output = LogStash::Plugin.lookup("output", "newrelic").new(specific_config)
238
- @newrelic_output.register
239
-
240
- expect(@newrelic_output.sleep_duration(0)).to equal(0)
241
- expect(@newrelic_output.sleep_duration(1)).to equal(5)
242
- expect(@newrelic_output.sleep_duration(2)).to equal(10)
243
- expect(@newrelic_output.sleep_duration(3)).to equal(20)
244
- expect(@newrelic_output.sleep_duration(4)).to equal(40)
245
- expect(@newrelic_output.sleep_duration(5)).to equal(60)
246
- expect(@newrelic_output.sleep_duration(6)).to equal(60) # Never gets bigger than this
247
- end
248
-
249
- it "first call fails, should retry" do
267
+ context "error handling" do
268
+ it "continues through errors, future calls should still succeed" do
250
269
  stub_request(:any, base_uri)
251
- .to_return(status: 500)
270
+ .to_raise(StandardError.new("from test"))
252
271
  .to_return(status: 200)
253
272
 
254
- event = LogStash::Event.new({ "message" => "Test message" })
255
- @newrelic_output.multi_receive([event])
273
+ event1 = LogStash::Event.new({ "message" => "Test message 1" })
274
+ event2 = LogStash::Event.new({ "message" => "Test message 2" })
275
+ @newrelic_output.multi_receive([event1])
276
+ @newrelic_output.multi_receive([event2])
256
277
 
257
- wait_for(a_request(:post, base_uri)).to have_been_made.times(2)
278
+ wait_for(a_request(:post, base_uri)
279
+ .with { |request| single_gzipped_message(request.body)['message'] == 'Test message 2' })
280
+ .to have_been_made
258
281
  end
282
+ end
259
283
 
260
- it "first two calls fail, should retry" do
261
- stub_request(:any, base_uri)
262
- .to_return(status: 500)
263
- .to_return(status: 500)
264
- .to_return(status: 200)
284
+ context "JSON serialization" do
285
+ it "serializes floating point numbers as floating point numbers" do
286
+ stub_request(:any, base_uri).to_return(status: 200)
265
287
 
266
- event = LogStash::Event.new({ "message" => "Test message" })
288
+ event = LogStash::Event.new({ "floatingpoint" => 0.12345 })
267
289
  @newrelic_output.multi_receive([event])
268
290
 
269
- wait_for(a_request(:post, base_uri)).to have_been_made.times(3)
291
+ wait_for(a_request(:post, base_uri)
292
+ .with { |request|
293
+ message = single_gzipped_message(request.body)
294
+ message['attributes']['floatingpoint'] == 0.12345
295
+ }
296
+ ).to have_been_made
270
297
  end
271
298
 
272
- it "all calls fails, should stop retrying at some point" do
273
- stub_request(:any, base_uri)
274
- .to_return(status: 500)
299
+ it "serializes BigDecimals as floating point numbers" do
300
+ stub_request(:any, base_uri).to_return(status: 200)
275
301
 
276
- event = LogStash::Event.new({ "message" => "Test message" })
302
+ event = LogStash::Event.new({ "bigdecimal" => BigDecimal('0.12345') })
277
303
  @newrelic_output.multi_receive([event])
278
304
 
279
- # This may not fail if the wait_for is called exactly when there have been 'retries' calls.
280
- # However, with zero sleep time (max_delay=0), on a laptop the POST was done 2000+ times by the
281
- # time this was executed
282
- wait_for(a_request(:post, base_uri)).to have_been_made.times(retries)
305
+ wait_for(a_request(:post, base_uri)
306
+ .with { |request|
307
+ message = single_gzipped_message(request.body)
308
+ message['attributes']['bigdecimal'] == 0.12345
309
+ }
310
+ ).to have_been_made
283
311
  end
284
- end
285
312
 
286
- context "error handling" do
287
- it "continues through errors, future calls should still succeed" do
288
- stub_request(:any, base_uri)
289
- .to_raise(StandardError.new("from test"))
290
- .to_return(status: 200)
313
+ it "serializes NaN as null" do
314
+ stub_request(:any, base_uri).to_return(status: 200)
291
315
 
292
- event1 = LogStash::Event.new({ "message" => "Test message 1" })
293
- event2 = LogStash::Event.new({ "message" => "Test message 2" })
294
- @newrelic_output.multi_receive([event1])
295
- @newrelic_output.multi_receive([event2])
316
+ event = LogStash::Event.new({ "nan" => BigDecimal('NaN') })
317
+ @newrelic_output.multi_receive([event])
296
318
 
297
319
  wait_for(a_request(:post, base_uri)
298
- .with { |request| single_gzipped_message(request.body)['message'] == 'Test message 2' })
299
- .to have_been_made
320
+ .with { |request|
321
+ message = single_gzipped_message(request.body)
322
+ message['attributes']['nan'] == nil
323
+ }
324
+ ).to have_been_made
300
325
  end
301
326
  end
302
327
  end
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.0.8
4
+ version: 1.1.4
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-08-20 00:00:00.000000000 Z
11
+ date: 2020-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ name: rspec
76
+ prerelease: false
77
+ type: :development
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  requirement: !ruby/object:Gem::Requirement
71
85
  requirements:
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - ">="
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ name: rspec_junit_formatter
104
+ prerelease: false
105
+ type: :development
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  description:
84
112
  email: logging-team@newrelic.com
85
113
  executables: []
@@ -92,6 +120,7 @@ files:
92
120
  - Gemfile
93
121
  - LICENSE
94
122
  - README.md
123
+ - lib/logstash/outputs/config/bigdecimal_patch.rb
95
124
  - lib/logstash/outputs/newrelic.rb
96
125
  - lib/logstash/outputs/newrelic_version/version.rb
97
126
  - logstash-output-newrelic.gemspec