logstash-output-newrelic 1.0.8 → 1.1.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
  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