logstash-output-lmlogs 1.2.1 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3236f68981e8e3fb68a9335240874b9f8fb93b59372893425992f0c9c86f2895
4
- data.tar.gz: 850265953883226fd2c82b3ad00acf894667aaca86396af454af6d9d59411acc
3
+ metadata.gz: 46b4784b47b720c638e2f6cb53ace887c3ff3bd821cc27ca675fc3bf6b5b3325
4
+ data.tar.gz: 2dd4c277e4b769d4580ea1474d00f058d2f08f1d718da6e715c51ab16f722679
5
5
  SHA512:
6
- metadata.gz: 86a1e6be32d0c8f976371dd9441aa282c980a7886e4940b5e298ae28406c5f9e1934b751264a40010e7b94a307076248274c350ae87e51ce33d1b5cea1a1b57a
7
- data.tar.gz: 01ca2ae8f258141614eef6312fe18c394b7602bd9e88e86c57d6f810471ee204889da918da4704c999d2942ef368925ba675df9a6bc2fb4169e842beb4fe7455
6
+ metadata.gz: 118161034fbd6b10b946449a75ccabc6fcce733006824711bdbcde2fff864f65ac249bd1de2f78600e975e71f47740881e946c4f2335a82956e6a8b130f44af5
7
+ data.tar.gz: f28a74d295e3f14bca4bfed4389c5dd32cfaaecb8f5b550168f2542494b0876c50b95d42661d101879284f9a7f532a74551b7fa1989abf83289b046f210e33de
data/CHANGELOG.md CHANGED
@@ -1,2 +1,18 @@
1
1
  ## 1.0.0
2
2
  - First version of the plugin
3
+ ## 1.0.1
4
+ - Proxy support
5
+ ## 1.0.2
6
+ - Update debug logs
7
+ ## 1.1.0
8
+ - Disable mfa for gem push
9
+ ## 1.2.0
10
+ - Add metadata by default to every log
11
+ ## 1.2.1
12
+ - Fix ensuring metadata exists before deleting the original while forwarding to lm-logs
13
+ ## 1.3.0
14
+ - Add bearer token support for authentication with Logicmonitor
15
+ ## 1.3.1
16
+ - Fix user agent populated in headers
17
+ ## 2.0.0
18
+ - Dont send event metadata by default. Add config include_metadata_keys for including custom metadata
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/logstash-output-lmlogs.svg)](https://badge.fury.io/rb/logstash-output-lmlogs)
2
2
 
3
- This plugin sends Logstash events to the [Logicmonitor Logs](https://www.logicmonitor.com)
3
+ This plugin sends Logstash events to the [Logicmonitor Logs](https://www.logicmonitor.com)
4
4
 
5
5
  # Getting started
6
6
 
@@ -20,6 +20,7 @@ output {
20
20
  }
21
21
  }
22
22
  ```
23
+ You would need either `access_id` and `access_id` both or `bearer_token` for authentication with Logicmonitor.
23
24
 
24
25
 
25
26
 
@@ -27,27 +28,28 @@ output {
27
28
 
28
29
  | Option | Description| Default |
29
30
  | --- | --- | --- |
30
- | batch_size | Event batch size to send to LM Logs.| 100 |
31
+ | batch_size | Event batch size to send to LM Logs.| 100 |
31
32
  | message_key | Key that will be used by the plugin as the system key | "message" |
32
33
  | lm_property | Key that will be used by LM to match resource based on property | "system.hostname" |
33
34
  | keep_timestamp | If false, LM Logs will use the ingestion timestamp as the event timestamp | true |
34
35
  | timestamp_is_key | If true, LM Logs will use a specified key as the event timestamp | false |
35
36
  | timestamp_key | If timestamp_is_key is set, LM Logs will use this key in the event as the timestamp | "logtimestamp" |
36
- | include_metadata | If false, the metadata fields will not be sent to LM Logs | true |
37
+ | include_metadata | If true, all metadata fields will be sent to LM Logs | false |
38
+ | include_metadata_keys | Array of json keys for which plugin looks for these keys and adds as event meatadata. A dot "." can be used to add nested subjson. If config `include_metadata` is set to true, all metadata will be sent regardless of this config. | [] |
37
39
 
38
40
  See the [source code](lib/logstash/outputs/lmlogs.rb) for the full list of options
39
41
 
40
42
  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
43
 
42
- ## Known issues
44
+ ## Known issues
43
45
  - Installation of the plugin fails on Logstash 6.2.1.
44
-
45
-
46
+
47
+
46
48
  ## Contributing
47
-
49
+
48
50
  Bug reports and pull requests are welcome. This project is intended to
49
51
  be a safe, welcoming space for collaboration.
50
-
52
+
51
53
  ## Development
52
-
54
+
53
55
  We use docker to build the plugin. You can build it by running `docker-compose run jruby gem build logstash-output-lmlogs.gemspec `
@@ -8,6 +8,7 @@ require 'date'
8
8
  require 'base64'
9
9
  require 'openssl'
10
10
  require 'manticore'
11
+ require_relative "version"
11
12
 
12
13
  # An example output that does nothing.
13
14
  class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
@@ -30,7 +31,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
30
31
 
31
32
  # Keep logstash timestamp
32
33
  config :keep_timestamp, :validate => :boolean, :default => true
33
-
34
+
34
35
  # Use a configured message key for timestamp values
35
36
  # Valid timestamp formats are ISO8601 strings or epoch in seconds, milliseconds or nanoseconds
36
37
  config :timestamp_is_key, :validate => :boolean, :default => false
@@ -91,13 +92,19 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
91
92
  config :portal_name, :validate => :string, :required => true
92
93
 
93
94
  # Username to use for HTTP auth.
94
- config :access_id, :validate => :string, :required => true
95
+ config :access_id, :validate => :string, :required => false, :default => nil
95
96
 
96
97
  # Include/Exclude metadata from sending to LM Logs
97
- config :include_metadata, :validate => :boolean, :default => true
98
+ config :include_metadata, :validate => :boolean, :default => false
98
99
 
99
100
  # Password to use for HTTP auth
100
- config :access_key, :validate => :password, :required => true
101
+ config :access_key, :validate => :password, :required => false, :default => nil
102
+
103
+ # Use bearer token instead of access key/id for authentication.
104
+ config :bearer_token, :validate => :password, :required => false, :default => nil
105
+
106
+ # json keys for which plugin looks for these keys and adds as event meatadata. A dot "." can be used to add nested subjson.
107
+ config :include_metadata_keys, :validate => :array, :required => false, :default => []
101
108
 
102
109
  @@MAX_PAYLOAD_SIZE = 8*1024*1024
103
110
 
@@ -110,8 +117,16 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
110
117
  @total_failed = 0
111
118
  logger.info("Initialized LogicMonitor output plugin with configuration",
112
119
  :host => @host)
113
- logger.info("Max Payload Size: ",
120
+ logger.info("Max Payload Size: ",
114
121
  :size => @@MAX_PAYLOAD_SIZE)
122
+ configure_auth
123
+
124
+ @final_metadata_keys = Hash.new
125
+ if @include_metadata_keys.any?
126
+ include_metadata_keys.each do | nested_key |
127
+ @final_metadata_keys[nested_key] = nested_key.to_s.split('.')
128
+ end
129
+ end
115
130
 
116
131
  end # def register
117
132
 
@@ -137,19 +152,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
137
152
  @proxy
138
153
  end
139
154
 
140
- if @access_id
141
- if !@access_key || !@access_key.value
142
- raise ::LogStash::ConfigurationError, "access_id '#{@access_id}' specified without access_key!"
143
- end
144
-
145
- # Symbolize keys if necessary
146
- # c[:auth] = {
147
- # :user => @access_id,
148
- # :password => @access_key.value,
149
- # :eager => true
150
- # }
151
- end
152
- log_debug("manticore client config: ", :client => c)
155
+ log_debug("manticore client config: ", :client => c)
153
156
  return c
154
157
  end
155
158
 
@@ -168,21 +171,35 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
168
171
  @client.close
169
172
  end
170
173
 
171
-
174
+ def configure_auth
175
+ @use_bearer_instead_of_lmv1 = false
176
+ if @access_id == nil || @access_key.value == nil
177
+ @logger.info "Access Id or access key null. Using bearer token for authentication."
178
+ @use_bearer_instead_of_lmv1 = true
179
+ end
180
+ if @use_bearer_instead_of_lmv1 && @bearer_token.value == nil
181
+ @logger.error "Bearer token not specified. Either access_id and access_key both or bearer_token must be specified for authentication with Logicmonitor."
182
+ raise LogStash::ConfigurationError, 'No valid authentication specified. Either access_id and access_key both or bearer_token must be specified for authentication with Logicmonitor.'
183
+ end
184
+ end
172
185
  def generate_auth_string(body)
173
- timestamp = DateTime.now.strftime('%Q')
174
- hash_this = "POST#{timestamp}#{body}/log/ingest"
175
- sign_this = OpenSSL::HMAC.hexdigest(
176
- OpenSSL::Digest.new('sha256'),
177
- "#{@access_key.value}",
178
- hash_this
179
- )
180
- signature = Base64.strict_encode64(sign_this)
181
- "LMv1 #{@access_id}:#{signature}:#{timestamp}"
186
+ if @use_bearer_instead_of_lmv1
187
+ return "Bearer #{@bearer_token.value}"
188
+ else
189
+ timestamp = DateTime.now.strftime('%Q')
190
+ hash_this = "POST#{timestamp}#{body}/log/ingest"
191
+ sign_this = OpenSSL::HMAC.hexdigest(
192
+ OpenSSL::Digest.new('sha256'),
193
+ "#{@access_key.value}",
194
+ hash_this
195
+ )
196
+ signature = Base64.strict_encode64(sign_this)
197
+ return "LMv1 #{@access_id}:#{signature}:#{timestamp}"
198
+ end
182
199
  end
183
200
 
184
201
  def send_batch(events)
185
- log_debug("Started sending logs to LM: ",
202
+ log_debug("Started sending logs to LM: ",
186
203
  :time => Time::now.utc)
187
204
  url = "https://" + @portal_name + ".logicmonitor.com/rest/log/ingest"
188
205
  body = events.to_json
@@ -191,7 +208,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
191
208
  :body => body,
192
209
  :headers => {
193
210
  "Content-Type" => "application/json",
194
- "User-Agent" => "LM Logs Logstash Plugin",
211
+ "User-Agent" => "lm-logs-logstash/" + LmLogsLogstashPlugin::VERSION,
195
212
  "Authorization" => "#{auth_string}"
196
213
  }
197
214
  })
@@ -249,7 +266,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
249
266
  elsif debug
250
267
  @logger.debug(message, *opts)
251
268
  end
252
- end
269
+ end
253
270
 
254
271
  public
255
272
  def multi_receive(events)
@@ -260,34 +277,48 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
260
277
  events.each_slice(@batch_size) do |chunk|
261
278
  documents = []
262
279
  chunk.each do |event|
263
- event_json = JSON.parse(event.to_json)
264
- lmlogs_event = {}
265
-
266
- if @include_metadata
267
- lmlogs_event = event_json
268
- lmlogs_event.delete("@timestamp") # remove redundant timestamp field
269
- if lmlogs_event.dig("event", "original") != nil
270
- lmlogs_event["event"].delete("original") # remove redundant log field
271
- end
272
- end
273
280
 
274
- lmlogs_event["message"] = event.get(@message_key).to_s
275
- lmlogs_event["_lm.resourceId"] = {}
276
- lmlogs_event["_lm.resourceId"]["#{@lm_property}"] = event.get(@property_key.to_s)
281
+ documents = isValidPayloadSize(documents, processEvent(event), @@MAX_PAYLOAD_SIZE)
282
+ end
283
+ send_batch(documents)
284
+ end
285
+ end
277
286
 
278
- if @keep_timestamp
279
- lmlogs_event["timestamp"] = event.get("@timestamp")
280
- end
281
-
282
- if @timestamp_is_key
283
- lmlogs_event["timestamp"] = event.get(@timestamp_key.to_s)
284
- end
285
287
 
286
- documents = isValidPayloadSize(documents,lmlogs_event,@@MAX_PAYLOAD_SIZE)
288
+ def processEvent(event)
289
+ event_json = JSON.parse(event.to_json)
290
+ lmlogs_event = {}
287
291
 
292
+ if @include_metadata
293
+ lmlogs_event = event_json
294
+ lmlogs_event.delete("@timestamp") # remove redundant timestamp field
295
+ if lmlogs_event.dig("event", "original") != nil
296
+ lmlogs_event["event"].delete("original") # remove redundant log field
297
+ end
298
+ elsif @final_metadata_keys
299
+ @final_metadata_keys.each do | key, value |
300
+ nestedVal = event_json
301
+ value.each { |x| nestedVal = nestedVal[x] }
302
+ if nestedVal != nil
303
+ lmlogs_event[key] = nestedVal
304
+ end
288
305
  end
289
- send_batch(documents)
290
306
  end
307
+
308
+ lmlogs_event["message"] = event.get(@message_key).to_s
309
+ lmlogs_event["_lm.resourceId"] = {}
310
+ lmlogs_event["_lm.resourceId"]["#{@lm_property}"] = event.get(@property_key.to_s)
311
+
312
+ if @keep_timestamp
313
+ lmlogs_event["timestamp"] = event.get("@timestamp")
314
+ end
315
+
316
+ if @timestamp_is_key
317
+ lmlogs_event["timestamp"] = event.get(@timestamp_key.to_s)
318
+ end
319
+
320
+ return lmlogs_event
321
+
291
322
  end
292
323
 
293
324
  def log_failure(message, opts)
@@ -295,10 +326,10 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
295
326
  end
296
327
 
297
328
  def isValidPayloadSize(documents,lmlogs_event,max_payload_size)
298
- if (documents.to_json.bytesize + lmlogs_event.to_json.bytesize) > max_payload_size
329
+ if (documents.to_json.bytesize + lmlogs_event.to_json.bytesize) > max_payload_size
299
330
  send_batch(documents)
300
331
  documents = []
301
-
332
+
302
333
  end
303
334
  documents.push(lmlogs_event)
304
335
  return documents
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LmLogsLogstashPlugin
4
+ VERSION = '2.0.0'
5
+ end
@@ -1,6 +1,14 @@
1
+
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require "logstash/outputs/version.rb"
6
+
7
+
8
+
1
9
  Gem::Specification.new do |s|
2
10
  s.name = 'logstash-output-lmlogs'
3
- s.version = '1.2.1'
11
+ s.version = LmLogsLogstashPlugin::VERSION
4
12
  s.licenses = ['Apache-2.0']
5
13
  s.summary = "Logstash output plugin for LM Logs"
6
14
  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"
@@ -25,4 +33,5 @@ Gem::Specification.new do |s|
25
33
  s.add_runtime_dependency 'manticore', '>= 0.5.2', '< 1.0.0'
26
34
 
27
35
  s.add_development_dependency 'logstash-devutils'
36
+ s.add_development_dependency 'hashdiff', '>= 1.0.0'
28
37
  end
@@ -0,0 +1,60 @@
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
+
8
+ let(:sample_lm_logs_event){{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => "2021-03-22T04:28:55.907121106Z"}}
9
+
10
+ def create_output_plugin_with_conf(conf)
11
+ return LogStash::Outputs::LMLogs.new(conf)
12
+ end
13
+
14
+ it "with no auth specified" do
15
+ puts "auth test"
16
+ plugin = create_output_plugin_with_conf({
17
+ "portal_name" => "localhost"
18
+ })
19
+ expect { plugin.configure_auth() }.to raise_error(LogStash::ConfigurationError)
20
+ end
21
+
22
+ it "access_key id is specified with no bearer" do
23
+ puts "auth test"
24
+ plugin = create_output_plugin_with_conf({
25
+ "portal_name" => "localhost",
26
+ "access_id" => "abcd",
27
+ "access_key" => "abcd"
28
+ })
29
+ plugin.configure_auth()
30
+ auth_string = plugin.generate_auth_string([sample_lm_logs_event])
31
+
32
+ expect(auth_string).to start_with("LMv1 abcd:")
33
+ end
34
+
35
+ it "when access id /key not specified but bearer specified" do
36
+ plugin = create_output_plugin_with_conf({
37
+ "portal_name" => "localhost",
38
+ "access_id" => "abcd",
39
+ "bearer_token" => "abcd"
40
+ })
41
+ plugin.configure_auth()
42
+ auth_string = plugin.generate_auth_string([sample_lm_logs_event])
43
+
44
+ expect(auth_string).to eq("Bearer abcd")
45
+ end
46
+
47
+ it "when access id /key bearer all specified, use lmv1" do
48
+ puts "auth test"
49
+ plugin = create_output_plugin_with_conf({
50
+ "portal_name" => "localhost",
51
+ "access_id" => "abcd",
52
+ "access_key" => "abcd",
53
+ "bearer_token" => "abcd"
54
+ })
55
+ plugin.configure_auth()
56
+ auth_string = plugin.generate_auth_string([sample_lm_logs_event])
57
+
58
+ expect(auth_string).to start_with("LMv1 abcd:")
59
+ end
60
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/outputs/lmlogs"
4
+ require "logstash/event"
5
+ require "hashdiff"
6
+
7
+
8
+ describe LogStash::Outputs::LMLogs do
9
+
10
+
11
+ let(:logstash_event) {LogStash::Event.new("message" => "hello this is log 1",
12
+ "host" => "host1",
13
+ "nested1" => {"nested2" => {"nested3" => "value"},
14
+ "nested2a" => {"nested3a" => {"nested4" => "valueA"}},
15
+ "nested2b" => {"nested3b" => "value"}
16
+ },
17
+ "nested1_" => "value",
18
+ "nested" => {"nested2" => {"nested3" => "value",
19
+ "nested3b" => "value"},
20
+ "nested_ignored" => "somevalue"
21
+ }
22
+ )}
23
+ let(:sample_lm_logs_event){{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => "2021-03-22T04:28:55.907121106Z"}}
24
+ let(:include_metadata_keys) {["host", "nested1.nested2.nested3", "nested1.nested2a", "nested.nested2" ]}
25
+
26
+ def create_output_plugin_with_conf(conf)
27
+ return LogStash::Outputs::LMLogs.new(conf)
28
+ end
29
+
30
+ def check_same_hash(h1,h2)
31
+
32
+ end
33
+
34
+ it "default behaviour" do
35
+ puts "default behaviour"
36
+ plugin = create_output_plugin_with_conf({
37
+ "portal_name" => "localhost",
38
+ "access_id" => "abcd",
39
+ "access_key" => "abcd",
40
+ "lm_property" => "system.hostname",
41
+ "property_key" => "host"
42
+ })
43
+ constructed_event = plugin.processEvent(logstash_event)
44
+ expected_event = {
45
+ "message" => "hello this is log 1",
46
+ "timestamp" => logstash_event.timestamp,
47
+ "_lm.resourceId" => {"system.hostname" => "host1"},
48
+
49
+ }
50
+ puts " actual : #{constructed_event} \n expected : #{expected_event}"
51
+
52
+ expect(Hashdiff.diff(constructed_event,expected_event)).to eq([])
53
+ end
54
+
55
+ it "with include_metadata set to true" do
56
+ puts "with include_metadata set to true"
57
+ plugin = create_output_plugin_with_conf({
58
+ "portal_name" => "localhost",
59
+ "access_id" => "abcd",
60
+ "access_key" => "abcd",
61
+ "lm_property" => "system.hostname",
62
+ "property_key" => "host",
63
+ "include_metadata" => true
64
+ })
65
+ constructed_event = plugin.processEvent(logstash_event)
66
+ expected_event = {
67
+ "message" => "hello this is log 1",
68
+ "timestamp" => logstash_event.timestamp,
69
+ "@version" => "1",
70
+ "_lm.resourceId" => {"system.hostname" => "host1"},
71
+ "host" => "host1",
72
+ "nested1" => {"nested2" => {"nested3" => "value"},
73
+ "nested2a" => {"nested3a" => {"nested4" => "valueA"}},
74
+ "nested2b" => {"nested3b" => "value"}
75
+ },
76
+ "nested1_" => "value",
77
+ "nested" => {"nested2" => {"nested3" => "value",
78
+ "nested3b" => "value"},
79
+ "nested_ignored" => "somevalue"
80
+ }
81
+ }
82
+ puts " actual : #{constructed_event} \n expected : #{expected_event}"
83
+ puts " hash diff : #{Hashdiff.diff(constructed_event,expected_event)}"
84
+ expect(Hashdiff.diff(constructed_event,expected_event)).to eq([])
85
+ end
86
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-lmlogs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LogicMonitor
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-23 00:00:00.000000000 Z
11
+ date: 2023-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -78,6 +78,20 @@ dependencies:
78
78
  - - ">="
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0'
81
+ - !ruby/object:Gem::Dependency
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 1.0.0
87
+ name: hashdiff
88
+ prerelease: false
89
+ type: :development
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 1.0.0
81
95
  description: This gem is a Logstash plugin required to be installed on top of the
82
96
  Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This
83
97
  gem is not a stand-alone program
@@ -90,8 +104,11 @@ files:
90
104
  - Gemfile
91
105
  - README.md
92
106
  - lib/logstash/outputs/lmlogs.rb
107
+ - lib/logstash/outputs/version.rb
93
108
  - logstash-output-lmlogs.gemspec
109
+ - spec/outputs/auth_spec.rb
94
110
  - spec/outputs/lmlogs_spec.rb
111
+ - spec/outputs/metadata_spec.rb
95
112
  homepage: https://www.logicmonitor.com
96
113
  licenses:
97
114
  - Apache-2.0
@@ -119,4 +136,6 @@ signing_key:
119
136
  specification_version: 4
120
137
  summary: Logstash output plugin for LM Logs
121
138
  test_files:
139
+ - spec/outputs/auth_spec.rb
122
140
  - spec/outputs/lmlogs_spec.rb
141
+ - spec/outputs/metadata_spec.rb