logstash-output-edge_http 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a076945788c4f08facd2cb2e61717e26e77431552c7ac846ce4bf8401fb156d4
4
+ data.tar.gz: 0cb3ebf49320c940bfb4ad29f65af21c59c12227b97de1f06391c4b3e2eddea8
5
+ SHA512:
6
+ metadata.gz: 22d7e935ba950ae5a401524867efefa8f58803f99151af98ae82e439eefc1e45c901bfe0c1245a25a5c90932f16673fd1fb82a92e50f70e1b085614f951fe3d3
7
+ data.tar.gz: ac400ffed57010d459a6adcdde926a1ae379296c94c03cd77f0148fd0baa9b7f6783983451af7ab54517aab5cd6ba1467384de3f029c0a65f34e9ad2e9a32ed8
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ logstash_path = ENV["LOGSTASH_PATH"] || "./logstash"
6
+
7
+ if Dir.exist?(logstash_path)
8
+ gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
9
+ gem 'logstash-mixin-http_client', :path => "#{logstash_path}/vendor/bundle/jruby/2.6.0/gems/logstash-mixin-http_client"
10
+ else
11
+ raise 'missing logstash vendoring'
12
+ end
13
+
14
+ gem "oauth2", "~> 2.0.9"
15
+ gem "webmock", "~> 3.8"
16
+ gem 'logstash-devutils', "~> 2"
17
+ gem 'sinatra'
18
+ gem 'webrick'
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # Contributing to Loki Logstash Output Plugin
2
+
3
+ For information about how to use this plugin see this [documentation](../../docs/sources/clients/logstash/_index.md).
4
+
5
+ ## Install dependencies
6
+
7
+ First, make sure you have JDK version `8` or `11` installed and you have set the `JAVA_HOME` environment variable.
8
+
9
+ You need to setup JRuby environment to build this plugin. Refer https://github.com/rbenv/rbenv for setting up your rbenv environment.
10
+
11
+ After setting up `rbenv`. Install JRuby
12
+
13
+ ```bash
14
+ rbenv install jruby-9.2.10.0
15
+ rbenv local jruby-9.2.10.0
16
+ ```
17
+
18
+ Check that the environment is configured
19
+
20
+ ```bash
21
+ ruby --version
22
+ jruby 9.2.10
23
+ ```
24
+
25
+ You should make sure you are running `jruby` and not `ruby`. If the command `ruby --version` still shows `ruby` and not `jruby`, check that PATH contains `$HOME/.rbenv/shims` and `$HOME/.rbenv/bin`. Also verify that you have this in your bash profile:
26
+
27
+ ```bash
28
+ export PATH="$HOME/.rbenv/bin:$PATH"
29
+ eval "$(rbenv init -)"
30
+ ```
31
+
32
+ Then install bundler:
33
+
34
+ ```bash
35
+ gem install bundler:2.1.4
36
+ ```
37
+
38
+ Follow those instructions to [install logstash](https://www.elastic.co/guide/en/logstash/current/installing-logstash.html) before moving to the next section.
39
+
40
+ ## Build and test the plugin
41
+
42
+ ### Install required packages
43
+
44
+ ```bash
45
+ git clone git@github.com:elastic/logstash.git
46
+ cd logstash
47
+ git checkout tags/v7.16.1
48
+ export LOGSTASH_PATH="$(pwd)"
49
+ export GEM_PATH="$LOGSTASH_PATH/vendor/bundle/jruby/2.5.0"
50
+ export GEM_HOME="$LOGSTASH_PATH/vendor/bundle/jruby/2.5.0"
51
+ ./gradlew assemble
52
+ cd ..
53
+ ruby -S bundle /config set --local path "$LOGSTASH_PATH/vendor/bundle"
54
+ ruby -S bundle install
55
+ ruby -S bundle exec rake vendor
56
+ ```
57
+
58
+ ### Build the plugin
59
+
60
+ ```bash
61
+ gem build logstash-output-loki.gemspec
62
+ ```
63
+
64
+ ### Test
65
+
66
+ ```bash
67
+ ruby -S bundle exec rspec
68
+ ```
69
+
70
+ Alternatively if you don't want to install JRuby. Enter inside logstash-loki container.
71
+
72
+ ```bash
73
+ docker build -t logstash-loki ./
74
+ docker run -v $(pwd)/spec:/home/logstash/spec -it --rm --entrypoint /bin/sh logstash-loki
75
+ bundle exec rspec
76
+ ```
77
+
78
+ ## Install plugin to local logstash
79
+
80
+ ```bash
81
+ bin/logstash-plugin install --no-verify --local logstash-output-loki-1.0.0.gem
82
+ ```
83
+
84
+ ## Send sample event and check plugin is working
85
+
86
+ ```bash
87
+ bin/logstash -f loki.conf
88
+ ```
@@ -0,0 +1,414 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+ require "logstash/json"
5
+ require "uri"
6
+ require "logstash/plugin_mixins/http_client"
7
+ require "zlib"
8
+ require 'oauth2'
9
+
10
+ class LogStash::Outputs::Http < LogStash::Outputs::Base
11
+ include LogStash::PluginMixins::HttpClient
12
+
13
+ concurrency :shared
14
+
15
+ attr_accessor :is_batch
16
+
17
+ VALID_METHODS = ["put", "post", "patch", "delete", "get", "head"]
18
+
19
+ RETRYABLE_MANTICORE_EXCEPTIONS = [
20
+ ::Manticore::Timeout,
21
+ ::Manticore::SocketException,
22
+ ::Manticore::ClientProtocolException,
23
+ ::Manticore::ResolutionFailure,
24
+ ::Manticore::SocketTimeout
25
+ ]
26
+
27
+ RETRYABLE_UNKNOWN_EXCEPTION_STRINGS = [
28
+ /Connection reset by peer/i,
29
+ /Read Timed out/i
30
+ ]
31
+
32
+ class PluginInternalQueueLeftoverError < StandardError; end
33
+
34
+ # This output lets you send events to a
35
+ # generic HTTP(S) endpoint
36
+ #
37
+ # This output will execute up to 'pool_max' requests in parallel for performance.
38
+ # Consider this when tuning this plugin for performance.
39
+ #
40
+ # Additionally, note that when parallel execution is used strict ordering of events is not
41
+ # guaranteed!
42
+ #
43
+ # Beware, this gem does not yet support codecs. Please use the 'format' option for now.
44
+
45
+ config_name "http"
46
+
47
+ # URL to use
48
+ config :url, :validate => :string, :required => :true
49
+
50
+ # The HTTP Verb. One of "put", "post", "patch", "delete", "get", "head"
51
+ config :http_method, :validate => VALID_METHODS, :required => :true
52
+
53
+ # Custom headers to use
54
+ # format is `headers => ["X-My-Header", "%{host}"]`
55
+ config :headers, :validate => :hash, :default => {}
56
+
57
+ # Content type
58
+ #
59
+ # If not specified, this defaults to the following:
60
+ #
61
+ # * if format is "json", "application/json"
62
+ # * if format is "form", "application/x-www-form-urlencoded"
63
+ config :content_type, :validate => :string
64
+
65
+ # Set this to false if you don't want this output to retry failed requests
66
+ config :retry_failed, :validate => :boolean, :default => true
67
+
68
+ # If encountered as response codes this plugin will retry these requests
69
+ config :retryable_codes, :validate => :number, :list => true, :default => [429, 500, 502, 503, 504]
70
+
71
+ # If you would like to consider some non-2xx codes to be successes
72
+ # enumerate them here. Responses returning these codes will be considered successes
73
+ config :ignorable_codes, :validate => :number, :list => true
74
+
75
+ # This lets you choose the structure and parts of the event that are sent.
76
+ #
77
+ #
78
+ # For example:
79
+ # [source,ruby]
80
+ # mapping => {"foo" => "%{host}"
81
+ # "bar" => "%{type}"}
82
+ config :mapping, :validate => :hash
83
+
84
+ # Set the format of the http body.
85
+ #
86
+ # If form, then the body will be the mapping (or whole event) converted
87
+ # into a query parameter string, e.g. `foo=bar&baz=fizz...`
88
+ #
89
+ # If message, then the body will be the result of formatting the event according to message
90
+ #
91
+ # Otherwise, the event is sent as json.
92
+ config :format, :validate => ["json", "json_batch", "form", "message"], :default => "json"
93
+
94
+ # Set this to true if you want to enable gzip compression for your http requests
95
+ config :http_compression, :validate => :boolean, :default => false
96
+
97
+ config :message, :validate => :string
98
+
99
+ def register
100
+ @http_method = @http_method.to_sym
101
+
102
+ # We count outstanding requests with this queue
103
+ # This queue tracks the requests to create backpressure
104
+ # When this queue is empty no new requests may be sent,
105
+ # tokens must be added back by the client on success
106
+ @request_tokens = SizedQueue.new(@pool_max)
107
+ @pool_max.times {|t| @request_tokens << true }
108
+
109
+ @requests = Array.new
110
+
111
+ if @content_type.nil?
112
+ case @format
113
+ when "form" ; @content_type = "application/x-www-form-urlencoded"
114
+ when "json" ; @content_type = "application/json"
115
+ when "json_batch" ; @content_type = "application/json"
116
+ when "message" ; @content_type = "text/plain"
117
+ end
118
+ end
119
+
120
+ @is_batch = @format == "json_batch"
121
+
122
+ @headers["Content-Type"] = @content_type
123
+
124
+ validate_format!
125
+
126
+ # Run named Timer as daemon thread
127
+ @timer = java.util.Timer.new("HTTP Output #{self.params['id']}", true)
128
+ end # def register
129
+
130
+ def multi_receive(events)
131
+ return if events.empty?
132
+ send_events(events)
133
+ end
134
+
135
+ class RetryTimerTask < java.util.TimerTask
136
+ def initialize(pending, event, attempt)
137
+ @pending = pending
138
+ @event = event
139
+ @attempt = attempt
140
+ super()
141
+ end
142
+
143
+ def run
144
+ @pending << [@event, @attempt]
145
+ end
146
+ end
147
+
148
+ def log_retryable_response(response)
149
+ retry_msg = @retry_failed ? 'will retry' : "won't retry"
150
+ if (response.code == 429)
151
+ @logger.debug? && @logger.debug("Encountered a 429 response, #{retry_msg}. This is not serious, just flow control via HTTP")
152
+ else
153
+ @logger.warn("Encountered a retryable HTTP request in HTTP output, #{retry_msg}", :code => response.code, :body => response.body)
154
+ end
155
+ end
156
+
157
+ def log_error_response(response, url, event)
158
+ log_failure(
159
+ "Encountered non-2xx HTTP code #{response.code}",
160
+ :response_code => response.code,
161
+ :url => url,
162
+ :event => event
163
+ )
164
+ end
165
+
166
+ def send_events(events)
167
+ successes = java.util.concurrent.atomic.AtomicInteger.new(0)
168
+ failures = java.util.concurrent.atomic.AtomicInteger.new(0)
169
+ retries = java.util.concurrent.atomic.AtomicInteger.new(0)
170
+ event_count = @is_batch ? 1 : events.size
171
+
172
+ pending = Queue.new
173
+ if @is_batch
174
+ pending << [events, 0]
175
+ else
176
+ events.each {|e| pending << [e, 0]}
177
+ end
178
+
179
+ while popped = pending.pop
180
+ break if popped == :done
181
+
182
+ event, attempt = popped
183
+
184
+ raise PluginInternalQueueLeftoverError.new("Received pipeline shutdown request but http output has unfinished events. " \
185
+ "If persistent queue is enabled, events will be retried.") if attempt > 2 && pipeline_shutdown_requested?
186
+
187
+ action, event, attempt = send_event(event, attempt)
188
+ begin
189
+ action = :failure if action == :retry && !@retry_failed
190
+
191
+ case action
192
+ when :success
193
+ successes.incrementAndGet
194
+ when :retry
195
+ retries.incrementAndGet
196
+
197
+ next_attempt = attempt+1
198
+ sleep_for = sleep_for_attempt(next_attempt)
199
+ @logger.info("Retrying http request, will sleep for #{sleep_for} seconds")
200
+ timer_task = RetryTimerTask.new(pending, event, next_attempt)
201
+ @timer.schedule(timer_task, sleep_for*1000)
202
+ when :failure
203
+ failures.incrementAndGet
204
+ else
205
+ raise "Unknown action #{action}"
206
+ end
207
+
208
+ if action == :success || action == :failure
209
+ if successes.get+failures.get == event_count
210
+ pending << :done
211
+ end
212
+ end
213
+ rescue => e
214
+ # This should never happen unless there's a flat out bug in the code
215
+ @logger.error("Error sending HTTP Request",
216
+ :class => e.class.name,
217
+ :message => e.message,
218
+ :backtrace => e.backtrace)
219
+ failures.incrementAndGet
220
+ raise e
221
+ end
222
+ end
223
+ rescue => e
224
+ @logger.error("Error in http output loop",
225
+ :class => e.class.name,
226
+ :message => e.message,
227
+ :backtrace => e.backtrace)
228
+ raise e
229
+ end
230
+
231
+ def pipeline_shutdown_requested?
232
+ return super if defined?(super) # since LS 8.1.0
233
+ nil
234
+ end
235
+
236
+ def sleep_for_attempt(attempt)
237
+ sleep_for = attempt**2
238
+ sleep_for = sleep_for <= 60 ? sleep_for : 60
239
+ (sleep_for/2) + (rand(0..sleep_for)/2)
240
+ end
241
+
242
+ def send_event(event, attempt)
243
+ body = event_body(event)
244
+
245
+ # Send the request
246
+ url = @is_batch ? @url : event.sprintf(@url)
247
+ headers = @is_batch ? @headers : event_headers(event)
248
+
249
+ # Compress the body and add appropriate header
250
+ if @http_compression == true
251
+ headers["Content-Encoding"] = "gzip"
252
+ body = gzip(body)
253
+ end
254
+
255
+ # Create an async request
256
+ response = client.send(@http_method, url, :body => body, :headers => headers).call
257
+
258
+ if !response_success?(response)
259
+ if retryable_response?(response)
260
+ log_retryable_response(response)
261
+ return :retry, event, attempt
262
+ else
263
+ log_error_response(response, url, event)
264
+ return :failure, event, attempt
265
+ end
266
+ else
267
+ return :success, event, attempt
268
+ end
269
+
270
+ rescue => exception
271
+ will_retry = retryable_exception?(exception)
272
+ log_params = {
273
+ :url => url,
274
+ :method => @http_method,
275
+ :message => exception.message,
276
+ :class => exception.class,
277
+ :will_retry => will_retry
278
+ }
279
+ if @logger.debug?
280
+ # backtraces are big
281
+ log_params[:backtrace] = exception.backtrace
282
+ # headers can have sensitive data
283
+ log_params[:headers] = headers
284
+ # body can be big and may have sensitive data
285
+ log_params[:body] = body
286
+ end
287
+ log_failure("Could not fetch URL", log_params)
288
+
289
+ if will_retry
290
+ return :retry, event, attempt
291
+ else
292
+ return :failure, event, attempt
293
+ end
294
+ end
295
+
296
+ def close
297
+ @timer.cancel
298
+ client.close
299
+ end
300
+
301
+ private
302
+
303
+ def response_success?(response)
304
+ code = response.code
305
+ return true if @ignorable_codes && @ignorable_codes.include?(code)
306
+ return code >= 200 && code <= 299
307
+ end
308
+
309
+ def retryable_response?(response)
310
+ @retryable_codes && @retryable_codes.include?(response.code)
311
+ end
312
+
313
+ def retryable_exception?(exception)
314
+ retryable_manticore_exception?(exception) || retryable_unknown_exception?(exception)
315
+ end
316
+
317
+ def retryable_manticore_exception?(exception)
318
+ RETRYABLE_MANTICORE_EXCEPTIONS.any? {|me| exception.is_a?(me)}
319
+ end
320
+
321
+ def retryable_unknown_exception?(exception)
322
+ exception.is_a?(::Manticore::UnknownException) &&
323
+ RETRYABLE_UNKNOWN_EXCEPTION_STRINGS.any? { |snippet| exception.message =~ snippet }
324
+ end
325
+
326
+ # This is split into a separate method mostly to help testing
327
+ def log_failure(message, opts)
328
+ @logger.error(message, opts)
329
+ end
330
+
331
+ # Format the HTTP body
332
+ def event_body(event)
333
+ # TODO: Create an HTTP post data codec, use that here
334
+ if @format == "json"
335
+ LogStash::Json.dump(map_event(event))
336
+ elsif @format == "message"
337
+ event.sprintf(@message)
338
+ elsif @format == "json_batch"
339
+ LogStash::Json.dump(event.map {|e| map_event(e) })
340
+ else
341
+ encode(map_event(event))
342
+ end
343
+ end
344
+
345
+ # gzip data
346
+ def gzip(data)
347
+ gz = StringIO.new
348
+ gz.set_encoding("BINARY")
349
+ z = Zlib::GzipWriter.new(gz)
350
+ z.write(data)
351
+ z.close
352
+ gz.string
353
+ end
354
+
355
+ def convert_mapping(mapping, event)
356
+ if mapping.is_a?(Hash)
357
+ mapping.reduce({}) do |acc, kv|
358
+ k, v = kv
359
+ acc[k] = convert_mapping(v, event)
360
+ acc
361
+ end
362
+ elsif mapping.is_a?(Array)
363
+ mapping.map { |elem| convert_mapping(elem, event) }
364
+ else
365
+ event.sprintf(mapping)
366
+ end
367
+ end
368
+
369
+ def map_event(event)
370
+ if @mapping
371
+ convert_mapping(@mapping, event)
372
+ else
373
+ event.to_hash
374
+ end
375
+ end
376
+
377
+ def event_headers(event)
378
+ custom_headers(event) || {}
379
+ end
380
+
381
+ def custom_headers(event)
382
+ return nil unless @headers
383
+
384
+ @headers.reduce({}) do |acc,kv|
385
+ k,v = kv
386
+ acc[k] = event.sprintf(v)
387
+ acc
388
+ end
389
+ end
390
+
391
+ #TODO Extract this to a codec
392
+ def encode(hash)
393
+ return hash.collect do |key, value|
394
+ CGI.escape(key) + "=" + CGI.escape(value.to_s)
395
+ end.join("&")
396
+ end
397
+
398
+
399
+ def validate_format!
400
+ if @format == "message"
401
+ if @message.nil?
402
+ raise "message must be set if message format is used"
403
+ end
404
+
405
+ if @content_type.nil?
406
+ raise "content_type must be set if message format is used"
407
+ end
408
+
409
+ unless @mapping.nil?
410
+ @logger.warn "mapping is not supported and will be ignored if message format is used"
411
+ end
412
+ end
413
+ end
414
+ end
@@ -0,0 +1,32 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-output-edge_http'
3
+ s.version = '1.0.0'
4
+ s.authors = ['Britto Prabhu']
5
+ s.email = ['britto.prabhu@apmterminals.com']
6
+
7
+ s.summary = 'Output plugin to ship logs to Loki server with oauth2 token'
8
+ s.description = 'This Output plugin to ship logs to Loki server with oauth2 token and proxy support'
9
+ s.summary = "Sends events to a generic HTTP or HTTPS endpoint with additional oauth2 token support"
10
+ s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program. This plugin supports oauth2 token."
11
+ s.homepage = 'https://github.com/Maersk-Global/apmt-observability-deployment'
12
+ s.license = 'Apache-2.0'
13
+ s.require_paths = ["lib"]
14
+
15
+ # Files
16
+ s.files = Dir["lib/**/*","spec/**/*","*.gemspec","*.md","CONTRIBUTORS","Gemfile","LICENSE","NOTICE.TXT", "vendor/jar-dependencies/**/*.jar", "vendor/jar-dependencies/**/*.rb", "VERSION", "docs/**/*"]
17
+
18
+ # Tests
19
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
20
+
21
+ # Special flag to let us know this is actually a logstash plugin
22
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
23
+
24
+ # Gem dependencies
25
+ s.add_runtime_dependency "oauth2", "~> 2.0.9"
26
+ s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
27
+ s.add_runtime_dependency "logstash-mixin-http_client", ">= 7.2.0", "< 8.0.0"
28
+
29
+ s.add_development_dependency 'logstash-devutils'
30
+ s.add_development_dependency 'sinatra'
31
+ s.add_development_dependency 'webrick'
32
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-output-edge_http
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Britto Prabhu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-09-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 2.0.9
19
+ name: oauth2
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.9
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.60'
33
+ - - "<="
34
+ - !ruby/object:Gem::Version
35
+ version: '2.99'
36
+ name: logstash-core-plugin-api
37
+ prerelease: false
38
+ type: :runtime
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '1.60'
44
+ - - "<="
45
+ - !ruby/object:Gem::Version
46
+ version: '2.99'
47
+ - !ruby/object:Gem::Dependency
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 7.2.0
53
+ - - "<"
54
+ - !ruby/object:Gem::Version
55
+ version: 8.0.0
56
+ name: logstash-mixin-http_client
57
+ prerelease: false
58
+ type: :runtime
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 7.2.0
64
+ - - "<"
65
+ - !ruby/object:Gem::Version
66
+ version: 8.0.0
67
+ - !ruby/object:Gem::Dependency
68
+ requirement: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ name: logstash-devutils
74
+ prerelease: false
75
+ type: :development
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ - !ruby/object:Gem::Dependency
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ name: sinatra
88
+ prerelease: false
89
+ type: :development
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ requirement: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ name: webrick
102
+ prerelease: false
103
+ type: :development
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ description: This gem is a Logstash plugin required to be installed on top of the
110
+ Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This
111
+ gem is not a stand-alone program. This plugin supports oauth2 token.
112
+ email:
113
+ - britto.prabhu@apmterminals.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - Gemfile
119
+ - README.md
120
+ - lib/logstash/outputs/edge_http.rb
121
+ - logstash-output-edge_http.gemspec
122
+ homepage: https://github.com/Maersk-Global/apmt-observability-deployment
123
+ licenses:
124
+ - Apache-2.0
125
+ metadata:
126
+ logstash_plugin: 'true'
127
+ logstash_group: output
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.2.33
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Sends events to a generic HTTP or HTTPS endpoint with additional oauth2 token
147
+ support
148
+ test_files: []