logstash-output-newrelic 1.3.0 → 1.4.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: 7f6e7768d78135be1d77a25e79d4db1eacbe23c5d1a31b4c738073672dfb3aa3
4
- data.tar.gz: 8844275d5c3e3d5200d3a3461050e5f46053a7614582377db4480aca600b780c
3
+ metadata.gz: 9e6c4d247631f976e7a7fc6153a02cc764f583491c749654a827c1fd6846c6c2
4
+ data.tar.gz: 42389a3c04b5f1ef4804f9bf7efa820d7037c25e2df73c127354d180c624ff02
5
5
  SHA512:
6
- metadata.gz: b71c733f87e3e1ec200b1ee101a9d293a84e20f744fcd8aa2b572b93e0523bda83af67d216d94b90da9c273152874ec832f1e1c7c02250fabee0cafc9b53a315
7
- data.tar.gz: '0617081a05a7a31f9e5f0469836fd55016f8c7fbe971851ad531c646819898a31dc7303d1aa569be3fbec98f173d39bc60c7d090594c074745f0c72d70a42545'
6
+ metadata.gz: deebd2f6b0c7f5c07ee4fc347f577a9011a481be03f8e170a9e9c368594009cbc33b853e05c025a1938b038febc8cc6d6db8c906aa3eacbeacfabab3483d7755
7
+ data.tar.gz: becf3aef35efc785f84ea956cabf2004d8d1ddbde4dac11f11bec3a25b65ab9a3277a97dcb35add2839581fb0b19ddf59114a83c9e5afd7a54da14ddd9b181d1
data/DEVELOPER.md CHANGED
@@ -2,12 +2,23 @@
2
2
 
3
3
  # Getting started
4
4
 
5
- * Install JRuby: `rbenv install jruby-9.2.5.0`
6
- * Use that JRuby: `rbenv local jruby-9.2.5.0`
5
+ **NOTE for Mac M1 users: ** note that `jruby-9.3.3.0` is the first jruby compatible with Mac M1 processors. In order to
6
+ develop the plugin locally, we recommend using this version. Nevertheless, when building the gem file (in the GH workflows),
7
+ we keep using jruby 9.2.13.0 in order to be backwards-compatible with older Logstash versions.
8
+
9
+ * Install RVM:
10
+ * `command curl -sSL https://rvm.io/pkuczynski.asc | gpg --import -`
11
+ * `\curl -sSL https://get.rvm.io | bash -s stable`
12
+ * Reopen the terminal for `rvm` command to be available
13
+ * Install JRuby: `rvm install jruby-9.2.13.0`.
14
+ * Use that JRuby: `rvm use jruby-9.2.13.0`
15
+ * Ensure your terminal is using Java 11.
7
16
  * Install Bundler gem: `jruby -S gem install bundler`
8
17
 
9
18
  # Developing
10
19
 
20
+ * Ensure you have `logstash` installed locally (required for unit testing): `brew install logstash`
21
+ * Ensure your `logstash` path matches the one in `Gemfile`
11
22
  * Install dependencies: `jruby -S bundle install`
12
23
  * Write tests and production code!
13
24
  * Bump version: edit version file `version.rb`
data/Gemfile CHANGED
@@ -1,3 +1,15 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
+ # The following is required to locally develop this plugin. Note that this Gemfile is NOT used when building the gem
5
+ # file for this plugin (see merge-to-master.yml), only when unit testing. When unit-testing, we need to have logstash-core
6
+ # in our local machine, given that the logstash-core GEM has not been published since 5.6.0.
7
+ # See: https://github.com/elastic/logstash/pull/14229 https://github.com/elastic/logstash/issues/14203
8
+ # And: https://github.com/elastic/logstash/pull/14229
9
+
10
+ logstash_path = ENV['LOGSTASH_PATH'] || '/opt/homebrew/Cellar/logstash/8.9.0/libexec'
11
+
12
+ if Dir.exist?(logstash_path)
13
+ gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
14
+ gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api"
15
+ end
@@ -12,10 +12,11 @@ require_relative './exception/error'
12
12
 
13
13
  class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
14
14
  java_import java.util.concurrent.Executors;
15
- java_import java.util.concurrent.Semaphore;
16
15
 
17
16
  NON_RETRYABLE_CODES = Set[401, 403]
18
17
 
18
+ MAX_PAYLOAD_SIZE_BYTES = 1_000_000
19
+
19
20
  config_name "newrelic"
20
21
 
21
22
  config :api_key, :validate => :password, :required => false
@@ -43,7 +44,6 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
43
44
  'Content-Type' => 'application/json'
44
45
  }.merge(auth).freeze
45
46
  @executor = java.util.concurrent.Executors.newFixedThreadPool(@concurrent_requests)
46
- @semaphor = java.util.concurrent.Semaphore.new(@concurrent_requests)
47
47
  end
48
48
 
49
49
  # Used by tests so that the test run can complete (background threads prevent JVM exit)
@@ -67,34 +67,40 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
67
67
  end
68
68
  end
69
69
 
70
- def encode(event_hash)
71
- log_message_hash = {
72
- # non-intrinsic attributes get put into 'attributes'
73
- :attributes => event_hash
74
- }
70
+ def to_nr_logs(logstash_events)
71
+ logstash_events.map do |logstash_event|
72
+ event_hash = logstash_event.to_hash
75
73
 
76
- # intrinsic attributes go at the top level
77
- if event_hash['message']
78
- log_message_hash['message'] = event_hash['message']
79
- log_message_hash[:attributes].delete('message')
80
- end
81
- if event_hash['timestamp']
82
- log_message_hash['timestamp'] = event_hash['timestamp']
83
- log_message_hash[:attributes].delete('timestamp')
84
- end
74
+ nr_log_message_hash = {
75
+ # non-intrinsic attributes get put into 'attributes'
76
+ :attributes => event_hash
77
+ }
78
+
79
+ # intrinsic attributes go at the top level
80
+ if event_hash['message']
81
+ nr_log_message_hash['message'] = event_hash['message']
82
+ nr_log_message_hash[:attributes].delete('message')
83
+ end
84
+ if event_hash['timestamp']
85
+ nr_log_message_hash['timestamp'] = event_hash['timestamp']
86
+ nr_log_message_hash[:attributes].delete('timestamp')
87
+ end
85
88
 
86
- log_message_hash
89
+ nr_log_message_hash
90
+ end
87
91
  end
88
92
 
89
- def multi_receive(events)
90
- if events.size == 0
93
+ def multi_receive(logstash_events)
94
+ if logstash_events.empty?
91
95
  return
92
96
  end
93
97
 
94
- payload = []
95
- events.each do |event|
96
- payload.push(encode(event.to_hash))
97
- end
98
+ nr_logs = to_nr_logs(logstash_events)
99
+
100
+ package_and_send_recursively(nr_logs)
101
+ end
102
+
103
+ def package_and_send_recursively(nr_logs)
98
104
  payload = {
99
105
  :common => {
100
106
  :attributes => {
@@ -104,19 +110,29 @@ class LogStash::Outputs::NewRelic < LogStash::Outputs::Base
104
110
  }
105
111
  }
106
112
  },
107
- :logs => payload
113
+ :logs => nr_logs
108
114
  }
109
- @semaphor.acquire()
115
+
110
116
  execute = @executor.java_method :submit, [java.lang.Runnable]
111
117
  execute.call do
112
- begin
113
- io = StringIO.new
114
- gzip = Zlib::GzipWriter.new(io)
115
- gzip << [payload].to_json
116
- gzip.close
117
- nr_send(io.string)
118
- ensure
119
- @semaphor.release()
118
+ compressed_payload = StringIO.new
119
+ gzip = Zlib::GzipWriter.new(compressed_payload)
120
+ gzip << [payload].to_json
121
+ gzip.close
122
+
123
+ compressed_size = compressed_payload.string.bytesize
124
+ log_record_count = nr_logs.length
125
+
126
+ if compressed_size >= MAX_PAYLOAD_SIZE_BYTES && log_record_count == 1
127
+ @logger.error("Can't compress record below required maximum packet size and it will be discarded.")
128
+ elsif compressed_size >= MAX_PAYLOAD_SIZE_BYTES && log_record_count > 1
129
+ @logger.debug("Compressed payload size (#{compressed_size}) exceededs maximum packet size (1MB) and will be split in two.")
130
+ split_index = log_record_count / 2
131
+ package_and_send_recursively(nr_logs[0...split_index])
132
+ package_and_send_recursively(nr_logs[split_index..-1])
133
+ else
134
+ @logger.debug("Payload compressed size: #{compressed_size}")
135
+ nr_send(compressed_payload.string)
120
136
  end
121
137
  end
122
138
  end
@@ -1,7 +1,7 @@
1
1
  module LogStash
2
2
  module Outputs
3
3
  module NewRelicVersion
4
- VERSION = "1.3.0"
4
+ VERSION = "1.4.0"
5
5
  end
6
6
  end
7
7
  end