logstash-output-lmlogs 1.2.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +11 -9
- data/lib/logstash/outputs/lmlogs.rb +86 -55
- data/lib/logstash/outputs/version.rb +5 -0
- data/logstash-output-lmlogs.gemspec +10 -1
- data/spec/outputs/auth_spec.rb +60 -0
- data/spec/outputs/metadata_spec.rb +86 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46b4784b47b720c638e2f6cb53ace887c3ff3bd821cc27ca675fc3bf6b5b3325
|
4
|
+
data.tar.gz: 2dd4c277e4b769d4580ea1474d00f058d2f08f1d718da6e715c51ab16f722679
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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 =>
|
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 =>
|
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 =>
|
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
|
-
|
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
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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" => "
|
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
|
-
|
275
|
-
|
276
|
-
|
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
|
-
|
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
|
@@ -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 =
|
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:
|
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:
|
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
|