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 +4 -4
- data/DEVELOPER.md +13 -2
- data/Gemfile +12 -0
- data/lib/logstash/outputs/newrelic.rb +49 -33
- data/lib/logstash/outputs/newrelic_version/version.rb +1 -1
- data/spec/outputs/input_17997_messages_resulting_in_2680KB_compressed_payload.json +17997 -0
- data/spec/outputs/input_5000_messages_resulting_in_740KB_compressed_payload.json +5000 -0
- data/spec/outputs/newrelic_spec.rb +94 -0
- data/spec/outputs/single_input_message_exceeeding_1MB_once_compressed.json +1 -0
- metadata +7 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e6c4d247631f976e7a7fc6153a02cc764f583491c749654a827c1fd6846c6c2
|
4
|
+
data.tar.gz: 42389a3c04b5f1ef4804f9bf7efa820d7037c25e2df73c127354d180c624ff02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
6
|
-
|
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
|
71
|
-
|
72
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
89
|
+
nr_log_message_hash
|
90
|
+
end
|
87
91
|
end
|
88
92
|
|
89
|
-
def multi_receive(
|
90
|
-
if
|
93
|
+
def multi_receive(logstash_events)
|
94
|
+
if logstash_events.empty?
|
91
95
|
return
|
92
96
|
end
|
93
97
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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 =>
|
113
|
+
:logs => nr_logs
|
108
114
|
}
|
109
|
-
|
115
|
+
|
110
116
|
execute = @executor.java_method :submit, [java.lang.Runnable]
|
111
117
|
execute.call do
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|