logstash-output-lmlogs 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a4781f24993d21cefddbbdfdca25641f5382a4db7243a2ed0f06a15e58fdb870
4
+ data.tar.gz: cfaca0ff01103adbb6df7c6cf693c6db7eb06f435adfb0dd62ac7baf57de4d74
5
+ SHA512:
6
+ metadata.gz: b79cb9b9306d41b5d1faf705208a1e3cacfc227bfb1ba1acf7b3580ed1f517e89ff148e05ea6cf892651d8997279a1ffad3c96bac4459a4bdacbcfc3fa1d3476
7
+ data.tar.gz: fff0d6826fa34cf0b6867c6406f5ca99d5c6e1244adfa1293a8d09e2d2393338c4c70d411b0f929365d4eb57eac5113f9537b9bfee815bf34bc68ec216527f20
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ - First version of the plugin
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ logstash_path = ENV["LOGSTASH_PATH"] || "../../logstash"
6
+ use_logstash_source = ENV["LOGSTASH_SOURCE"] && ENV["LOGSTASH_SOURCE"].to_s == "1"
7
+
8
+ if Dir.exist?(logstash_path) && use_logstash_source
9
+ gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
10
+ gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api"
11
+ end
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ [![Build Status](https://travis-ci.org/unomaly/logstash-output-unomaly.svg?branch=master)](https://travis-ci.org/unomaly/logstash-output-unomaly)
2
+
3
+ This plugin sends Logstash events to the [Logicmonitor Logs](https://www.logicmonitor.com)
4
+
5
+ # Getting started
6
+
7
+ ## Installing through rubygems
8
+
9
+ Run the following on your Logstash instance
10
+
11
+ `logstash-plugin install logstash-output-lmlogs`
12
+
13
+ ## Minimal configuration
14
+ ```
15
+ output {
16
+ lmlogs {
17
+ portal_name => "your company name"
18
+ access_id => "your lm access id"
19
+ access_key => "your access key"
20
+ }
21
+ }
22
+ ```
23
+
24
+ ```
25
+
26
+
27
+ # Important options
28
+
29
+ | Option | Description | Default |
30
+ |----------------------------|-------------------------------------------------------------------------------------|-----------------|
31
+ | batch_size | Event batch size to send to LM Logs. | 100 |
32
+ | message_key | Key that will be used by the plugin as the system key | "message" |
33
+ | lm_property | Key that will be used by LM to match resource based on property |"system.hostname"|
34
+ | keep_timestamp | If false, LM Logs will use the ingestion timestamp as the event timestamp | true |
35
+ | timestamp_is_key | If true, LM Logs will use a specified key as the event timestamp | false |
36
+ | timestamp_key | If timestamp_is_key is set, LM Logs will use this key in the event as the timestamp | "logtimestamp" |
37
+
38
+ See the [source code](lib/logstash/outputs/lmlogs.rb) for the full list of options
39
+
40
+ The syntax for `message_key` and `source_key` values are available in the [Logstash Event API Documentation](https://www.elastic.co/guide/en/logstash/current/event-api.html)
41
+
42
+ ## Known issues
43
+ - Installation of the plugin fails on Logstash 6.2.1.
44
+
45
+
46
+ ## Contributing
47
+
48
+ Bug reports and pull requests are welcome. This project is intended to
49
+ be a safe, welcoming space for collaboration.
50
+
51
+ ## Development
52
+
53
+ We use docker to build the plugin. You can build it by running `docker-compose run jruby gem build logstash-output-lmlogs.gemspec `
@@ -0,0 +1,282 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+ require "logstash/json"
5
+ require 'uri'
6
+ require 'json'
7
+ require 'date'
8
+ require 'base64'
9
+ require 'openssl'
10
+ require 'manticore'
11
+
12
+ # An example output that does nothing.
13
+ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
14
+ class InvalidHTTPConfigError < StandardError; end
15
+
16
+ concurrency :shared
17
+ config_name "lmlogs"
18
+
19
+ # Event batch size to send to LM Logs. Increasing the batch size can increase throughput by reducing HTTP overhead
20
+ config :batch_size, :validate => :number, :default => 100
21
+
22
+ # Key that will be used by the plugin as the log message
23
+ config :message_key, :validate => :string, :default => "message"
24
+
25
+ # Key that will be used by the plugin as the system key
26
+ config :property_key, :validate => :string, :default => "host"
27
+
28
+ # Key that will be used by LM to match resource based on property
29
+ config :lm_property, :validate => :string, :default => "system.hostname"
30
+
31
+ # Keep logstash timestamp
32
+ config :keep_timestamp, :validate => :boolean, :default => true
33
+
34
+ # Use a configured message key for timestamp values
35
+ # Valid timestamp formats are ISO8601 strings or epoch in seconds, milliseconds or nanoseconds
36
+ config :timestamp_is_key, :validate => :boolean, :default => false
37
+ config :timestamp_key, :validate => :string, :default => "logtimestamp"
38
+
39
+ # Display debug logs
40
+ config :debug, :validate => :boolean, :default => false
41
+
42
+ # Timeout (in seconds) for the entire request
43
+ config :request_timeout, :validate => :number, :default => 60
44
+
45
+ # Timeout (in seconds) to wait for data on the socket. Default is `10s`
46
+ config :socket_timeout, :validate => :number, :default => 10
47
+
48
+ # Timeout (in seconds) to wait for a connection to be established. Default is `10s`
49
+ config :connect_timeout, :validate => :number, :default => 10
50
+
51
+ # Should redirects be followed? Defaults to `true`
52
+ config :follow_redirects, :validate => :boolean, :default => true
53
+
54
+ # Max number of concurrent connections. Defaults to `50`
55
+ config :pool_max, :validate => :number, :default => 50
56
+
57
+ # Max number of concurrent connections to a single host. Defaults to `25`
58
+ config :pool_max_per_route, :validate => :number, :default => 25
59
+
60
+ # Turn this on to enable HTTP keepalive support. We highly recommend setting `automatic_retries` to at least
61
+ # one with this to fix interactions with broken keepalive implementations.
62
+ config :keepalive, :validate => :boolean, :default => true
63
+
64
+ # How many times should the client retry a failing URL. We highly recommend NOT setting this value
65
+ # to zero if keepalive is enabled. Some servers incorrectly end keepalives early requiring a retry!
66
+ # Note: if `retry_non_idempotent` is set only GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be retried.
67
+ config :automatic_retries, :validate => :number, :default => 5
68
+
69
+ # If `automatic_retries` is enabled this will cause non-idempotent HTTP verbs (such as POST) to be retried.
70
+ config :retry_non_idempotent, :validate => :boolean, :default => true
71
+
72
+ # How long to wait before checking if the connection is stale before executing a request on a connection using keepalive.
73
+ # # You may want to set this lower, possibly to 0 if you get connection errors regularly
74
+ # Quoting the Apache commons docs (this client is based Apache Commmons):
75
+ # 'Defines period of inactivity in milliseconds after which persistent connections must be re-validated prior to being leased to the consumer. Non-positive value passed to this method disables connection validation. This check helps detect connections that have become stale (half-closed) while kept inactive in the pool.'
76
+ # See https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html#setValidateAfterInactivity(int)[these docs for more info]
77
+ config :validate_after_inactivity, :validate => :number, :default => 200
78
+
79
+ # Enable cookie support. With this enabled the client will persist cookies
80
+ # across requests as a normal web browser would. Enabled by default
81
+ config :cookies, :validate => :boolean, :default => true
82
+
83
+ # If you'd like to use an HTTP proxy . This supports multiple configuration syntaxes:
84
+ #
85
+ # 1. Proxy host in form: `http://proxy.org:1234`
86
+ # 2. Proxy host in form: `{host => "proxy.org", port => 80, scheme => 'http', user => 'username@host', password => 'password'}`
87
+ # 3. Proxy host in form: `{url => 'http://proxy.org:1234', user => 'username@host', password => 'password'}`
88
+ config :proxy
89
+
90
+ # LM Portal Name
91
+ config :portal_name, :validate => :string, :required => true
92
+
93
+ # Username to use for HTTP auth.
94
+ config :access_id, :validate => :string, :required => true
95
+
96
+ # Password to use for HTTP auth
97
+ config :access_key, :validate => :password, :required => true
98
+
99
+ @@MAX_PAYLOAD_SIZE = 8*1024*1024
100
+
101
+ public
102
+ def register
103
+ @total = 0
104
+ @total_failed = 0
105
+ logger.info("Initialized LogicMonitor output plugin with configuration",
106
+ :host => @host)
107
+
108
+ end # def register
109
+
110
+ def client_config
111
+ c = {
112
+ connect_timeout: @connect_timeout,
113
+ socket_timeout: @socket_timeout,
114
+ request_timeout: @request_timeout,
115
+ follow_redirects: @follow_redirects,
116
+ automatic_retries: @automatic_retries,
117
+ retry_non_idempotent: @retry_non_idempotent,
118
+ check_connection_timeout: @validate_after_inactivity,
119
+ pool_max: @pool_max,
120
+ pool_max_per_route: @pool_max_per_route,
121
+ cookies: @cookies,
122
+ keepalive: @keepalive
123
+ }
124
+
125
+ if @proxy
126
+ # Symbolize keys if necessary
127
+ c[:proxy] = @proxy.is_a?(Hash) ?
128
+ @proxy.reduce({}) {|memo,(k,v)| memo[k.to_sym] = v; memo} :
129
+ @proxy
130
+ end
131
+
132
+ if @access_id
133
+ if !@access_key || !@access_key.value
134
+ raise ::LogStash::ConfigurationError, "access_id '#{@access_id}' specified without access_key!"
135
+ end
136
+
137
+ # Symbolize keys if necessary
138
+ c[:auth] = {
139
+ :access_id => @access_id,
140
+ :access_key => @access_key.value,
141
+ :eager => true
142
+ }
143
+ end
144
+ end
145
+
146
+ private
147
+ def make_client
148
+ puts client_config
149
+ Manticore::Client.new(client_config)
150
+ end
151
+
152
+ public
153
+ def client
154
+ @client ||= make_client
155
+ end
156
+
157
+ public
158
+ def close
159
+ @client.close
160
+ end
161
+
162
+
163
+ def generate_auth_string(body)
164
+ timestamp = DateTime.now.strftime('%Q')
165
+ hash_this = "POST#{timestamp}#{body}/log/ingest"
166
+ sign_this = OpenSSL::HMAC.hexdigest(
167
+ OpenSSL::Digest.new('sha256'),
168
+ "#{@access_key.value}",
169
+ hash_this
170
+ )
171
+ signature = Base64.strict_encode64(sign_this)
172
+ "LMv1 #{@access_id}:#{signature}:#{timestamp}"
173
+ end
174
+
175
+ def send_batch(events)
176
+ url = "https://" + @portal_name + ".logicmonitor.com/rest/log/ingest"
177
+ body = events.to_json
178
+ auth_string = generate_auth_string(body)
179
+ request = client.post(url, {
180
+ :body => body,
181
+ :headers => {
182
+ "Content-Type" => "application/json",
183
+ "User-Agent" => "LM Logs Logstash Plugin",
184
+ "Authorization" => "#{auth_string}"
185
+ }
186
+ })
187
+
188
+ request.on_success do |response|
189
+ if response.code == 202
190
+ @total += events.length
191
+ @logger.debug("Successfully sent ",
192
+ :response_code => response.code,
193
+ :batch_size => events.length,
194
+ :total_sent => @total,
195
+ :time => Time::now.utc)
196
+ elsif response.code == 207
197
+ log_failure(
198
+ "207 HTTP code - some of the events successfully parsed, some not. ",
199
+ :response_code => response.code,
200
+ :url => url,
201
+ :response_body => response.body,
202
+ :total_failed => @total_failed)
203
+ else
204
+ @total_failed += 1
205
+ log_failure(
206
+ "Encountered non-202/207 HTTP code #{response.code}",
207
+ :response_code => response.code,
208
+ :url => url,
209
+ :response_body => response.body,
210
+ :total_failed => @total_failed)
211
+ end
212
+ end
213
+
214
+ request.on_failure do |exception|
215
+ @total_failed += 1
216
+ log_failure("Could not access URL",
217
+ :url => url,
218
+ :method => @http_method,
219
+ :body => body,
220
+ :message => exception.message,
221
+ :class => exception.class.name,
222
+ :backtrace => exception.backtrace,
223
+ :total_failed => @total_failed
224
+ )
225
+ end
226
+
227
+ @logger.debug("Sending LM Logs",
228
+ :total => @total,
229
+ :time => Time::now.utc)
230
+ request.call
231
+
232
+ rescue Exception => e
233
+ @logger.error("[Exception=] #{e.message} #{e.backtrace}")
234
+ end
235
+
236
+
237
+ public
238
+ def multi_receive(events)
239
+ puts @@MAX_PAYLOAD_SIZE
240
+ if debug
241
+ puts events.to_json
242
+ end
243
+
244
+ events.each_slice(@batch_size) do |chunk|
245
+ documents = []
246
+ chunk.each do |event|
247
+ lmlogs_event = {
248
+ message: event.get(@message_key).to_s
249
+ }
250
+
251
+ lmlogs_event["_lm.resourceId"] = {}
252
+ lmlogs_event["_lm.resourceId"]["#{@lm_property}"] = event.get(@property_key.to_s)
253
+
254
+ if @keep_timestamp
255
+ lmlogs_event["timestamp"] = event.get("@timestamp")
256
+ end
257
+
258
+ if @timestamp_is_key
259
+ lmlogs_event["timestamp"] = event.get(@timestamp_key.to_s)
260
+ end
261
+
262
+ documents = isValidPayloadSize(documents,lmlogs_event,@@MAX_PAYLOAD_SIZE)
263
+
264
+ end
265
+ send_batch(documents)
266
+ end
267
+ end
268
+
269
+ def log_failure(message, opts)
270
+ @logger.error("[HTTP Output Failure] #{message}", opts)
271
+ end
272
+
273
+ def isValidPayloadSize(documents,lmlogs_event,max_payload_size)
274
+ if (documents.to_json.bytesize + lmlogs_event.to_json.bytesize) > max_payload_size
275
+ send_batch(documents)
276
+ documents = []
277
+
278
+ end
279
+ documents.push(lmlogs_event)
280
+ return documents
281
+ end
282
+ end # class LogStash::Outputs::LMLogs
@@ -0,0 +1,28 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-output-lmlogs'
3
+ s.version = '0.1.0'
4
+ s.licenses = ['Apache License (2.0)']
5
+ s.summary = "Logstash output plugin for LM Logs"
6
+ 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"
7
+ s.authors = ["LogicMonitor"]
8
+ s.email = "support@logicmonitor.com"
9
+ s.homepage = "https://www.logicmonitor.com"
10
+ s.require_paths = ["lib"]
11
+
12
+ # Files
13
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','Gemfile']
14
+ # Tests
15
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
16
+
17
+ # Special flag to let us know this is actually a logstash plugin
18
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
19
+
20
+ # Gem dependencies
21
+ #
22
+
23
+ s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
24
+ s.add_runtime_dependency "logstash-codec-plain"
25
+ s.add_runtime_dependency 'manticore', '>= 0.5.2', '< 1.0.0'
26
+
27
+ s.add_development_dependency 'logstash-devutils'
28
+ end
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/outputs/lmlogs"
4
+ require "logstash/event"
5
+
6
+ describe LogStash::Outputs::LMLogs do
7
+ let(:sample_event) { LogStash::Event.new("message" => "hello this is log") }
8
+ let(:client) { @lmlogs.client }
9
+
10
+ before do
11
+ @lmlogs = LogStash::Outputs::LMLogs.new(
12
+ "portal_name" => "localhost",
13
+ "access_id" => "access_id",
14
+ "access_key" => "access_key",
15
+ "batch_size" => 3,
16
+ "lm_property" => "test.property"
17
+ )
18
+ @lmlogs.register
19
+ allow(@lmlogs).to receive(:client).and_return(client)
20
+ allow(client).to receive(:post).and_call_original
21
+ end
22
+
23
+ before do
24
+ allow(@lmlogs).to receive(:client).and_return(client)
25
+ end
26
+
27
+ it "Forwards an event" do
28
+ expect(client).to receive(:post).once.and_call_original
29
+ @lmlogs.multi_receive([sample_event])
30
+ end
31
+
32
+ it "Batches multiple events and extracts metadata" do
33
+ event1 = LogStash::Event.new("message" => "hello this is log 1", "host" => "host1")
34
+ event2 = LogStash::Event.new("message" => "hello this is log 2", "host" => "host2")
35
+ event3 = LogStash::Event.new("message" => "hello this is log 3", "host" => "host3")
36
+ expect(client).to receive(:post).once.with("https://localhost.logicmonitor.com/rest/log/ingest",hash_including(:body => LogStash::Json.dump(
37
+ [{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => event1.timestamp.to_s},
38
+ {"message" => "hello this is log 2", "_lm.resourceId" => {"test.property" => "host2"}, "timestamp" => event2.timestamp.to_s},
39
+ {"message" => "hello this is log 3", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => event3.timestamp.to_s}
40
+ ]
41
+ ))).and_call_original
42
+ @lmlogs.multi_receive([event1, event2, event3])
43
+ end
44
+
45
+ it "Batches data of size batch_size" do
46
+ expect(client).to receive(:post).exactly(2).times.and_call_original
47
+ @lmlogs.multi_receive([sample_event, sample_event, sample_event, sample_event, sample_event])
48
+ end
49
+
50
+ it "max payload exceeded test" do
51
+
52
+ document = [{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => "2021-03-22T04:28:55.907121106Z"},
53
+ {"message" => "hello this is log 2", "_lm.resourceId" => {"test.property" => "host2"}, "timestamp" => "2021-03-22T04:28:55.907321106Z"},
54
+ {"message" => "hello this is log 3", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => "2021-03-22T04:28:55.907421106Z"}
55
+ ]
56
+
57
+ lm_logs_event = {"message" => "hello this is log 4", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => "2021-03-22T04:28:55.909421106Z"}
58
+ document_expected = [{"message" => "hello this is log 4", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => "2021-03-22T04:28:55.909421106Z"}]
59
+ expect(client).to receive(:post).once.with("https://localhost.logicmonitor.com/rest/log/ingest",hash_including(:body => LogStash::Json.dump(
60
+ [{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => "2021-03-22T04:28:55.907121106Z"},
61
+ {"message" => "hello this is log 2", "_lm.resourceId" => {"test.property" => "host2"}, "timestamp" => "2021-03-22T04:28:55.907321106Z"},
62
+ {"message" => "hello this is log 3", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => "2021-03-22T04:28:55.907421106Z"}
63
+ ]
64
+ ))).and_call_original
65
+
66
+ document_result = @lmlogs.isValidPayloadSize(document,lm_logs_event,document.to_json.bytesize)
67
+ expect(document_result).to eq(document_expected)
68
+ end
69
+ it "max payload in limit" do
70
+
71
+ document = [{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => "2021-03-22T04:28:55.907121106Z"},
72
+ {"message" => "hello this is log 2", "_lm.resourceId" => {"test.property" => "host2"}, "timestamp" => "2021-03-22T04:28:55.907321106Z"},
73
+ {"message" => "hello this is log 3", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => "2021-03-22T04:28:55.907421106Z"}
74
+ ]
75
+
76
+ lm_logs_event = {"message" => "hello this is log 4", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => "2021-03-22T04:28:55.909421106Z"}
77
+
78
+ document_expected = [{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => "2021-03-22T04:28:55.907121106Z"},
79
+ {"message" => "hello this is log 2", "_lm.resourceId" => {"test.property" => "host2"}, "timestamp" => "2021-03-22T04:28:55.907321106Z"},
80
+ {"message" => "hello this is log 3", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => "2021-03-22T04:28:55.907421106Z"},
81
+ {"message" => "hello this is log 4", "_lm.resourceId" => {"test.property" => "host3"}, "timestamp" => "2021-03-22T04:28:55.909421106Z"}]
82
+ expect(client).to receive(:post).exactly(0).times.and_call_original
83
+
84
+ document_result = @lmlogs.isValidPayloadSize(document,lm_logs_event,document.to_json.bytesize + lm_logs_event.to_json.bytesize)
85
+ expect(document_result).to eq(document_expected)
86
+ end
87
+
88
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-output-lmlogs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - LogicMonitor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-04-01 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: '1.60'
19
+ - - "<="
20
+ - !ruby/object:Gem::Version
21
+ version: '2.99'
22
+ name: logstash-core-plugin-api
23
+ prerelease: false
24
+ type: :runtime
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.60'
30
+ - - "<="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.99'
33
+ - !ruby/object:Gem::Dependency
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ name: logstash-codec-plain
40
+ prerelease: false
41
+ type: :runtime
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.5.2
53
+ - - "<"
54
+ - !ruby/object:Gem::Version
55
+ version: 1.0.0
56
+ name: manticore
57
+ prerelease: false
58
+ type: :runtime
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.5.2
64
+ - - "<"
65
+ - !ruby/object:Gem::Version
66
+ version: 1.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
+ description: This gem is a Logstash plugin required to be installed on top of the
82
+ Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This
83
+ gem is not a stand-alone program
84
+ email: support@logicmonitor.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - CHANGELOG.md
90
+ - Gemfile
91
+ - README.md
92
+ - lib/logstash/outputs/lmlogs.rb
93
+ - logstash-output-lmlogs.gemspec
94
+ - spec/outputs/lmlogs_spec.rb
95
+ homepage: https://www.logicmonitor.com
96
+ licenses:
97
+ - Apache License (2.0)
98
+ metadata:
99
+ logstash_plugin: 'true'
100
+ logstash_group: output
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.1.6
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Logstash output plugin for LM Logs
120
+ test_files:
121
+ - spec/outputs/lmlogs_spec.rb