logstash-input-jms 3.1.2-java → 3.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9523dfd590735b242d04d1e13c9b024367cf864e0e34fdedcd23dfabacead46
4
- data.tar.gz: afdfffb20005867db82bba2ff40557b3752dcbac1cbcd57fdfcab057b95813d2
3
+ metadata.gz: 2a40f29ee0db67e912d547f5fa74a74bcd08466c3f2594dd9edd5f82669ea494
4
+ data.tar.gz: c8fa0a986cea0a588b8b68fbd8618f24122ee42abb21ad3cf7f5e7cbb0f3484c
5
5
  SHA512:
6
- metadata.gz: 78f2d4db68c4dbf16910aa6813e5d622743e2c7c8cc1cd8c91e2a54cdb31698350df79f6d6bea910ca611c863dcb0d4ff3c1bdee42c9948c00f88c05dfab426b
7
- data.tar.gz: 2371457a596688f1960f8921508252d3bd78ea072b3283fa6492964a81e07cd288893b4c2379973872f9df202a492e4ad01a0d57115d2397df4a9254e8283e4c
6
+ metadata.gz: a121b9359ff97942888218bb1f2553f469940574e7f8421f7e910980bf37b973fd73cb2e0739a7525c0b71c5e8b4891765f70e505a798d1d9263f0bedbb13eee
7
+ data.tar.gz: d10f028310928b17f41f48cc50e8393022171d2c2fa4d25502f428f3d2bfbfc6172eee75d527d0ebb9b66f5a3790b6fe9c50fc3de5355dd71a907be33d5f9c5c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 3.2.0
2
+ - Feat: event_factory support + targets to aid ECS [#49](https://github.com/logstash-plugins/logstash-input-jms/pull/49)
3
+ - Fix: when configured to add JMS headers to the event, headers whose value is not set no longer result in nil entries on the event
4
+ - Fix: when adding the `jms_reply_to` header to an event, a string representation is set instead of an opaque object.
5
+
1
6
  ## 3.1.2
2
7
  - Docs: Added additional troubleshooting information [#38](https://github.com/logstash-plugins/logstash-input-jms/pull/38)
3
8
 
@@ -45,7 +50,7 @@
45
50
  - New dependency requirements for logstash-core for the 5.0 release
46
51
 
47
52
  ## 2.0.0
48
- - Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
53
+ - Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
49
54
  instead of using Thread.raise on the plugins' threads. Ref: https://github.com/elastic/logstash/pull/3895
50
55
  - Dependency on logstash-core update to 2.0
51
56
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Logstash Plugin
2
2
 
3
- [![Travis Build Status](https://travis-ci.org/logstash-plugins/logstash-input-jms.svg)](https://travis-ci.org/logstash-plugins/logstash-input-jms)
3
+ [![Travis Build Status](https://travis-ci.com/logstash-plugins/logstash-input-jms.svg)](https://travis-ci.com/logstash-plugins/logstash-input-jms)
4
4
 
5
5
  This is a plugin for [Logstash](https://github.com/elastic/logstash).
6
6
 
data/docs/index.asciidoc CHANGED
@@ -33,6 +33,14 @@ JMS configurations can be done either entirely in the Logstash configuration fil
33
33
  configurations, should also use the combination of yaml file and Logstash configuration.
34
34
 
35
35
 
36
+ [id="plugins-{type}s-{plugin}-ecs"]
37
+ ==== Compatibility with the Elastic Common Schema (ECS)
38
+
39
+ JMS data is application specific. ECS compliance for fields depends on the use case.
40
+ The plugin includes sensible defaults that change based on <<plugins-{type}s-{plugin}-ecs_compatibility,ECS compatibility mode>>.
41
+ When ECS compatibility is disabled, headers, properties, and payload are targeted at the root level of the event to maintain compatibility with legacy usage of this plugin.
42
+ When targeting an ECS version, headers and properties target `@metadata` sub-fields unless configured otherwise in order to avoid conflict with ECS fields.
43
+ See <<plugins-{type}s-{plugin}-headers_target>>, <<plugins-{type}s-{plugin}-properties_target>> and <<plugins-{type}s-{plugin}-target>>.
36
44
 
37
45
  ==== Sample Configuration using Logstash Configuration Only
38
46
 
@@ -60,7 +68,7 @@ The JMS plugin can also be configured using JNDI if desired.
60
68
  truststore => '/Users/logstash-user/security/truststore.jks'
61
69
  truststore_password => 'yet_another_secret'
62
70
  # Parts of the JMS message to be included <8>
63
- include_header => false
71
+ include_headers => false
64
72
  include_properties => false
65
73
  include_body => true
66
74
  # Message selector
@@ -98,7 +106,7 @@ The JMS plugin can also be configured using JNDI if desired.
98
106
  input {
99
107
  jms {
100
108
  # Logstash Configuration Settings. <1>
101
- include_header => false
109
+ include_headers => false
102
110
  include_properties => false
103
111
  include_body => true
104
112
  use_jms_timestamp => false
@@ -144,7 +152,7 @@ This section contains sample configurations for connecting to a JMS provider tha
144
152
  input {
145
153
  jms {
146
154
  # Logstash Configuration File Settings <1>
147
- include_header => false
155
+ include_headers => false
148
156
  include_properties => false
149
157
  include_body => true
150
158
  use_jms_timestamp => false
@@ -205,7 +213,7 @@ This section contains sample configurations for connecting to a JMS provider tha
205
213
  input {
206
214
  jms {
207
215
  # Logstash specific configuration settings <1>
208
- include_header => false
216
+ include_headers => false
209
217
  include_properties => false
210
218
  include_body => true
211
219
  use_jms_timestamp => false
@@ -379,10 +387,13 @@ This plugin supports the following configuration options plus the <<plugins-{typ
379
387
  | <<plugins-{type}s-{plugin}-durable_subscriber>> |<<boolean,boolean>>|No
380
388
  | <<plugins-{type}s-{plugin}-durable_subscriber_client_id>> |<<string,string>>|No
381
389
  | <<plugins-{type}s-{plugin}-durable_subscriber_name>> |<<string,string>>|No
390
+ | <<plugins-{type}s-{plugin}-ecs_compatibility>> |<<string,string>>|No
382
391
  | <<plugins-{type}s-{plugin}-factory>> |<<string,string>>|No
383
392
  | <<plugins-{type}s-{plugin}-factory_settings>> |<<hash,hash>>|No
393
+ | <<plugins-{type}s-{plugin}-headers_target>> |<<string,string>>|No
384
394
  | <<plugins-{type}s-{plugin}-include_body>> |<<boolean,boolean>>|No
385
395
  | <<plugins-{type}s-{plugin}-include_header>> |<<boolean,boolean>>|No
396
+ | <<plugins-{type}s-{plugin}-include_headers>> |<<boolean,boolean>>|No
386
397
  | <<plugins-{type}s-{plugin}-include_properties>> |<<boolean,boolean>>|No
387
398
  | <<plugins-{type}s-{plugin}-interval>> |<<number,number>>|No
388
399
  | <<plugins-{type}s-{plugin}-jndi_context>> |<<hash,hash>>|No
@@ -391,6 +402,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
391
402
  | <<plugins-{type}s-{plugin}-keystore_password>> |<<password,password>>|No
392
403
  | <<plugins-{type}s-{plugin}-oracle_aq_buffered_messages>> |<<boolean,boolean>>|No
393
404
  | <<plugins-{type}s-{plugin}-password>> |<<string,string>>|No
405
+ | <<plugins-{type}s-{plugin}-properties_target>> |<<string,string>>|No
394
406
  | <<plugins-{type}s-{plugin}-pub_sub>> |<<boolean,boolean>>|No
395
407
  | <<plugins-{type}s-{plugin}-require_jars>> |<<array,array>>|No
396
408
  | <<plugins-{type}s-{plugin}-runner>> |<<string,string>>|__Deprecated__
@@ -398,6 +410,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
398
410
  | <<plugins-{type}s-{plugin}-skip_headers>> |<<array,array>>|No
399
411
  | <<plugins-{type}s-{plugin}-skip_properties>> |<<array,array>>|No
400
412
  | <<plugins-{type}s-{plugin}-system_properties>> |<<hash,hash>>|No
413
+ | <<plugins-{type}s-{plugin}-target>> |<<string,string>>|No
401
414
  | <<plugins-{type}s-{plugin}-threads>> |<<number,number>>|No
402
415
  | <<plugins-{type}s-{plugin}-timeout>> |<<number,number>>|No
403
416
  | <<plugins-{type}s-{plugin}-truststore>> |a valid filesystem path|No
@@ -430,6 +443,8 @@ Url to use when connecting to the JMS provider. This is only relevant for non-JN
430
443
 
431
444
  Name of the destination queue or topic to use.
432
445
 
446
+ TIP: If the destination setting doesn't appear to be working properly, try this format: `<JMS module name>!<JMS queue name>`.
447
+
433
448
  [id="plugins-{type}s-{plugin}-durable_subscriber"]
434
449
  ===== `durable_subscriber`
435
450
 
@@ -466,6 +481,21 @@ This represents the value of the client ID for a durable subscribtion, and is on
466
481
  This represents the value of the subscriber name for a durable subscribtion, and is only used if `durable_subscriber`
467
482
  is set to `true`. Please consult your JMS Provider documentation for constraints and requirements for this setting.
468
483
 
484
+ [id="plugins-{type}s-{plugin}-ecs_compatibility"]
485
+ ===== `ecs_compatibility`
486
+
487
+ * Value type is <<string,string>>
488
+ * Supported values are:
489
+ ** `disabled`: does not use ECS-compatible field names (fields might be set at the root of the event)
490
+ ** `v1`, `v8`: avoids field names that might conflict with Elastic Common Schema (for example, JMS specific properties)
491
+ * Default value depends on which version of Logstash is running:
492
+ ** When Logstash provides a `pipeline.ecs_compatibility` setting, its value is used as the default
493
+ ** Otherwise, the default value is `disabled`.
494
+
495
+ Controls this plugin's compatibility with the {ecs-ref}[Elastic Common Schema (ECS)].
496
+ The value of this setting affects the _default_ value of <<plugins-{type}s-{plugin}-headers_target>> and
497
+ <<plugins-{type}s-{plugin}-properties_target>>.
498
+
469
499
  [id="plugins-{type}s-{plugin}-factory"]
470
500
  ===== `factory`
471
501
 
@@ -486,6 +516,16 @@ Hash of implementation specific configuration values to set on the connection fa
486
516
  `exclusive_consumer => true` would call `setExclusiveConsumer(true)` on the supplied connection factory.
487
517
  See your JMS provider documentation for implementation specific details.
488
518
 
519
+ [id="plugins-{type}s-{plugin}-headers_target"]
520
+ ===== `headers_target`
521
+
522
+ * Value type is <<string,string>>
523
+ * Default value depends on whether <<plugins-{type}s-{plugin}-ecs_compatibility>> is enabled:
524
+ ** ECS Compatibility disabled: no default value for this setting
525
+ ** ECS Compatibility enabled: `"[@metadata][input][jms][headers]"
526
+
527
+ The name of the field under which JMS headers will be added, if <<plugins-{type}s-{plugin}-include_headers>> is set.
528
+
489
529
  [id="plugins-{type}s-{plugin}-include_body"]
490
530
  ===== `include_body`
491
531
 
@@ -493,29 +533,54 @@ Hash of implementation specific configuration values to set on the connection fa
493
533
  * Default value is `true`
494
534
 
495
535
  Include JMS Message Body in the event.
496
- Supports TextMessage, MapMessage and ByteMessage.
536
+ Supports TextMessage, MapMessage and BytesMessage.
497
537
 
498
- If the JMS Message is a TextMessage or ByteMessage, then the value will be in
538
+ If the JMS Message is a TextMessage or BytesMessage, then the value will be in
499
539
  the "message" field of the event. If the JMS Message is a MapMessage, then all
500
- the key/value pairs will be added in the Hashmap of the event.
540
+ the key/value pairs will be added at the top-level of the event by default.
541
+ To avoid pollution of the top-level namespace, when receiving a MapMessage, use the <<plugins-{type}s-{plugin}-target>>.
501
542
 
502
543
  StreamMessage and ObjectMessage are not supported.
503
544
 
504
545
  [id="plugins-{type}s-{plugin}-include_header"]
505
546
  ===== `include_header`
506
547
 
548
+ * Value type is <<boolean,boolean>>
549
+ * This option is deprecated
550
+
551
+ Note: This option is deprecated and it will be removed in the next major version of Logstash.
552
+ Use `include_headers` instead.
553
+
554
+ [id="plugins-{type}s-{plugin}-include_headers"]
555
+ ===== `include_headers`
556
+
507
557
  * Value type is <<boolean,boolean>>
508
558
  * Default value is `true`
509
559
 
510
560
  A JMS message has three parts:
511
561
 
512
- * Message Headers (required)
513
- * Message Properties (optional)
514
- * Message Bodies (optional)
562
+ * Message Headers (required)
563
+ * Message Properties (optional)
564
+ * Message Body (optional)
515
565
 
516
566
  You can tell the input plugin which parts should be included in the event produced by Logstash.
517
567
 
518
- Include JMS Message Header Field values in the event.
568
+ Include standard JMS message header field values in the event.
569
+ Example headers:
570
+ [source,ruby]
571
+ -----
572
+ {
573
+ "jms_message_id" => "ID:amqhost-39547-1636977297920-71:1:1:1:1",
574
+ "jms_timestamp" => 1636977329102,
575
+ "jms_expiration" => 0,
576
+ "jms_delivery_mode" => "persistent",
577
+ "jms_redelivered" => false,
578
+ "jms_destination" => "topic://41ad5342149901ad",
579
+ "jms_priority" => 4,
580
+ "jms_type" => "sample",
581
+ "jms_correlation_id" => "28d975cb-14ff-4285-841e-05ef1e0a7ab2"
582
+ }
583
+ -----
519
584
 
520
585
  [id="plugins-{type}s-{plugin}-include_properties"]
521
586
  ===== `include_properties`
@@ -588,6 +653,16 @@ Only for use with Oracle AQ
588
653
 
589
654
  Password to use when connecting to the JMS provider.
590
655
 
656
+ [id="plugins-{type}s-{plugin}-properties_target"]
657
+ ===== `properties_target`
658
+
659
+ * Value type is <<string,string>>
660
+ * Default value depends on whether <<plugins-{type}s-{plugin}-ecs_compatibility>> is enabled:
661
+ ** ECS Compatibility disabled: no default value for this setting
662
+ ** ECS Compatibility enabled: `"[@metadata][input][jms][properties]"
663
+
664
+ The name of the field under which JMS properties will be added, if <<plugins-{type}s-{plugin}-include_properties>> is set.
665
+
591
666
  [id="plugins-{type}s-{plugin}-pub_sub"]
592
667
  ===== `pub_sub`
593
668
 
@@ -648,6 +723,17 @@ If `include_properties` is set, a list of properties to skip processing on can b
648
723
 
649
724
  Any System properties that the JMS provider requires can be set either in a Hash here, or in `jvm.options`
650
725
 
726
+ [id="plugins-{type}s-{plugin}-target"]
727
+ ===== `target`
728
+
729
+ * Value type is <<string,string>>
730
+ * There is no default value for this setting.
731
+
732
+ The name of the field to assign MapMessage data into.
733
+ If not specified data will be stored in the root of the event.
734
+
735
+ NOTE: For TextMessage and BytesMessage the `target` has no effect. Use the codec setting instead
736
+ e.g. `codec => json { target => "[jms]" }`.
651
737
 
652
738
  [id="plugins-{type}s-{plugin}-threads"]
653
739
  ===== `threads`
@@ -655,7 +741,7 @@ Any System properties that the JMS provider requires can be set either in a Hash
655
741
  * Value type is <<number,number>>
656
742
  * Default value is `1`
657
743
 
658
- * Note that if pub_sub is set to true, this value *must* be 1. A configuration error will be thrown otherwise
744
+ NOTE: If pub_sub is set to `true`, this value *must* be `1`. A configuration error will be thrown otherwise!
659
745
 
660
746
  [id="plugins-{type}s-{plugin}-timeout"]
661
747
  ===== `timeout`
@@ -722,4 +808,4 @@ For some known examples, see https://github.com/reidmorrison/jruby-jms/blob/mast
722
808
  [id="plugins-{type}s-{plugin}-common-options"]
723
809
  include::{include_path}/{type}.asciidoc[]
724
810
 
725
- :default_codec!:
811
+ :default_codec!:
@@ -4,13 +4,18 @@ require "logstash/inputs/threadable"
4
4
  require 'java'
5
5
  require "logstash/namespace"
6
6
 
7
+ require 'logstash/plugin_mixins/ecs_compatibility_support'
8
+ require 'logstash/plugin_mixins/ecs_compatibility_support/target_check'
9
+ require 'logstash/plugin_mixins/event_support/event_factory_adapter'
10
+ require 'logstash/plugin_mixins/validator_support/field_reference_validation_adapter'
11
+
7
12
  # Read events from a Jms Broker. Supports both Jms Queues and Topics.
8
13
  #
9
14
  # For more information about Jms, see <http://docs.oracle.com/javaee/6/tutorial/doc/bncdq.html>
10
15
  # For more information about the Ruby Gem used, see <http://github.com/reidmorrison/jruby-jms>
11
16
  # Here is a config example to pull from a queue:
12
17
  # jms {
13
- # include_header => false
18
+ # include_headers => false
14
19
  # include_properties => false
15
20
  # include_body => true
16
21
  # use_jms_timestamp => false
@@ -23,6 +28,12 @@ require "logstash/namespace"
23
28
  #
24
29
  #
25
30
  class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
31
+
32
+ include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1, :v8 => :v1)
33
+ include LogStash::PluginMixins::EventSupport::EventFactoryAdapter
34
+
35
+ extend LogStash::PluginMixins::ValidatorSupport::FieldReferenceValidationAdapter
36
+
26
37
  config_name "jms"
27
38
 
28
39
  # A JMS message has three parts :
@@ -32,7 +43,8 @@ class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
32
43
  # You can tell the input plugin which parts should be included in the event produced by Logstash
33
44
  #
34
45
  # Include JMS Message Header Field values in the event
35
- config :include_header, :validate => :boolean, :default => true
46
+ config :include_header, :validate => :boolean, :deprecated => "Set 'include_headers => ...' instead"
47
+ config :include_headers, :validate => :boolean, :default => true
36
48
  # Include JMS Message Properties Field values in the event
37
49
  config :include_properties, :validate => :boolean, :default => true
38
50
 
@@ -48,12 +60,12 @@ class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
48
60
  # If the JMS Message is a MapMessage, then all the key/value pairs will be added in the Hashmap of the event
49
61
  # StreamMessage and ObjectMessage are not supported
50
62
 
51
- # Receive Oracle AQ buffered messages.
63
+ # Receive Oracle AQ buffered messages.
52
64
  # In this mode persistent Oracle AQ JMS messages will not be received.
53
65
  config :oracle_aq_buffered_messages, :validate => :boolean, :default => false
54
66
 
55
67
  config :include_body, :validate => :boolean, :default => true
56
-
68
+
57
69
  # Convert the JMSTimestamp header field to the @timestamp value of the event
58
70
  config :use_jms_timestamp, :validate => :boolean, :default => false
59
71
 
@@ -122,6 +134,15 @@ class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
122
134
  config :truststore, :validate => :path
123
135
  config :truststore_password, :validate => :password
124
136
 
137
+ # Defines a target field for placing fields.
138
+ # If this setting is omitted, data gets stored at the root (top level) of the event.
139
+ # The target is only relevant while decoding data into a new event.
140
+ #
141
+ # NOTE: this is only relevant for map messages; byte[] and string use the codec!
142
+ config :target, :validate => :field_reference
143
+
144
+ config :headers_target, :validate => :field_reference # ECS default: [@metadata][input][jms][headers]
145
+ config :properties_target, :validate => :field_reference # ECS default: [@metadata][input][jms][properties]
125
146
 
126
147
  # :yaml_file, :factory and :jndi_name are mutually exclusive, both cannot be supplied at the
127
148
  # same time. The priority order is :yaml_file, then :jndi_name, then :factory
@@ -132,10 +153,25 @@ class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
132
153
  # For some known examples, see: [Example jms.yml](https://github.com/reidmorrison/jruby-jms/blob/master/examples/jms.yml)
133
154
 
134
155
  public
156
+
157
+ def initialize(*params)
158
+ super
159
+
160
+ if ecs_compatibility != :disabled # set ECS target defaults
161
+ @headers_target = '[@metadata][input][jms][headers]' unless original_params.include?('headers_target')
162
+ @properties_target = '[@metadata][input][jms][properties]' unless original_params.include?('properties_target')
163
+ end
164
+
165
+ @headers_setter = event_setter_for(@headers_target)
166
+ @properties_setter = event_setter_for(@properties_target)
167
+
168
+ @headers_mapper = ecs_compatibility == :disabled ? LegacyHeadersMapper::INSTANCE : HeadersMapper::INSTANCE
169
+ end
170
+
135
171
  def register
136
172
  require "jms"
137
173
 
138
- check_config
174
+ check_config!
139
175
  load_ssl_properties
140
176
  load_system_properties if @system_properties
141
177
  @jms_config = jms_config
@@ -208,7 +244,15 @@ class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
208
244
  @system_properties.each { |k,v| java.lang.System.set_property(k,v.to_s) }
209
245
  end
210
246
 
211
- def check_config
247
+ def check_config!
248
+ if original_params.include?('include_header')
249
+ if original_params.include?('include_headers')
250
+ raise(LogStash::ConfigurationError, "Both `include_headers => #{include_headers}` and `include_header => #{include_header}`" +
251
+ " options are specified, please only set one")
252
+ end
253
+ @include_headers = include_header # only `include_header => ...` was set
254
+ end
255
+
212
256
  check_durable_subscription_config
213
257
  raise(LogStash::ConfigurationError, "Threads cannot be > 1 if pub_sub is set") if @threads > 1 && @pub_sub
214
258
  end
@@ -252,43 +296,35 @@ class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
252
296
  end
253
297
  end # def run_consumer
254
298
 
255
-
256
299
  def queue_event(msg, output_queue)
257
300
  begin
258
301
  if @include_body
259
302
  if msg.java_kind_of?(JMS::MapMessage)
260
- event = LogStash::Event.new
261
- msg.data.each do |field, value|
262
- event.set(field.to_s, value) # TODO(claveau): needs codec.decode or converter.convert ?
263
- end
303
+ event = process_map_message(msg)
264
304
  elsif msg.java_kind_of?(JMS::TextMessage) || msg.java_kind_of?(JMS::BytesMessage)
265
- unless msg.to_s.nil?
266
- @codec.decode(msg.to_s) do |event_message|
267
- event = event_message
268
- end
269
- end
305
+ event = decode_message(msg)
270
306
  else
271
307
  @logger.error( "Unsupported message type #{msg.data.class.to_s}" )
272
308
  end
273
309
  end
274
310
 
275
- event ||= LogStash::Event.new
311
+ event ||= event_factory.new_event
276
312
 
277
313
  # Here, we can use the JMS Enqueue timestamp as the @timestamp
278
314
  if @use_jms_timestamp && msg.jms_timestamp
279
315
  event.set("@timestamp", LogStash::Timestamp.at(msg.jms_timestamp / 1000, (msg.jms_timestamp % 1000) * 1000))
280
316
  end
281
317
 
282
- if @include_header
283
- msg.attributes && msg.attributes.each do |field, value|
284
- event.set(field.to_s, value) unless @skip_headers.include?(field.to_s)
285
- end
318
+ if @include_headers
319
+ headers = map_headers(msg)
320
+ @skip_headers.each { |key| headers.delete(key) }
321
+ @headers_setter.call(event, headers)
286
322
  end
287
323
 
288
324
  if @include_properties
289
- msg.properties && msg.properties.each do |field, value|
290
- event.set(field.to_s, value) unless @skip_properties.include?(field.to_s)
291
- end
325
+ properties = to_string_keyed_hash(msg.properties)
326
+ @skip_properties.each { |key| properties.delete(key) }
327
+ @properties_setter.call(event, properties)
292
328
  end
293
329
 
294
330
  decorate(event)
@@ -300,6 +336,41 @@ class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
300
336
  end
301
337
  end
302
338
 
339
+ def to_string_keyed_hash(hash)
340
+ hash.inject({}) { |h, (key, val)| h[key.to_s] = val; h }
341
+ end
342
+ private :to_string_keyed_hash
343
+
344
+ # @param msg [JMS::MapMessage]
345
+ # @return [LogStash::Event]
346
+ def process_map_message(msg)
347
+ data = to_string_keyed_hash(msg.data)
348
+ do_target_check_once_and_get_event_factory.new_event(data)
349
+ end
350
+
351
+ def do_target_check_once_and_get_event_factory
352
+ @target_checked ||= begin
353
+ do_target_check
354
+ targeted_event_factory
355
+ end
356
+ end
357
+
358
+ TARGET_NOT_SET_MESSAGE = LogStash::PluginMixins::ECSCompatibilitySupport::TargetCheck::TARGET_NOT_SET_MESSAGE
359
+
360
+ def do_target_check
361
+ return true unless target.nil?
362
+ return nil if ecs_compatibility == :disabled
363
+ logger.info(TARGET_NOT_SET_MESSAGE) # target isn't set in ECS mode
364
+ end
365
+
366
+ # @param msg [JMS::TextMessage, JMS::BytesMessage]
367
+ # @return [LogStash::Event, nil]
368
+ def decode_message(msg)
369
+ text = msg.to_s # javax.jms.TextMessage#getText (e.g. JSON payload)
370
+ event = nil
371
+ @codec.decode(text) { |e| event = e } unless text.nil?
372
+ event
373
+ end
303
374
 
304
375
  def subscriber(session, params)
305
376
  destination_key = @pub_sub ? :topic_name : :queue_name
@@ -347,4 +418,102 @@ class LogStash::Inputs::Jms < LogStash::Inputs::Threadable
347
418
  end
348
419
  {:exception => cause.class.name, :exception_message => cause.message }
349
420
  end
421
+
422
+ private
423
+
424
+ def normalize_field_ref(target)
425
+ # so we can later event.set("#{target}[#{name}]", ...)
426
+ target.match?(/\A[^\[\]]+\z/) ? "[#{target}]" : target
427
+ end
428
+
429
+ def event_setter_for(target)
430
+ if target.nil? || target.empty?
431
+ TOP_LEVEL_EVENT_SETTER
432
+ else
433
+ TargetEventSetter.new normalize_field_ref(target)
434
+ end
435
+ end
436
+
437
+ TOP_LEVEL_EVENT_SETTER = lambda { |event, data| data.each { |key, val| event.set(key, val) } }
438
+ private_constant :TOP_LEVEL_EVENT_SETTER
439
+
440
+ class TargetEventSetter
441
+
442
+ def initialize(target)
443
+ @target = target
444
+ end
445
+
446
+ def call(event, data)
447
+ data.each { |key, val| event.set("#{@target}[#{key}]", val) }
448
+ end
449
+
450
+ end
451
+ private_constant :TargetEventSetter
452
+
453
+ def map_headers(msg)
454
+ @headers_mapper.call(msg)
455
+ end
456
+
457
+ # Maps JMS headers names
458
+ # (similar to JMS gem's Message#attributes extension)
459
+ class HeadersMapper
460
+
461
+ # @param msg [javax.jms.Message]
462
+ # @return [Hash]
463
+ def call(msg)
464
+ map = {
465
+ 'jms_message_id' => msg.getJMSMessageID, # String
466
+ 'jms_timestamp' => msg.getJMSTimestamp, # long
467
+ 'jms_expiration' => msg.getJMSExpiration, # long
468
+ 'jms_priority' => msg.getJMSPriority, # int (0-9)
469
+ 'jms_type' => msg.getJMSType, # String
470
+ 'jms_redelivered' => msg.getJMSRedelivered, # boolean
471
+ }
472
+
473
+ correlation_id = msg.getJMSCorrelationID # String
474
+ map['jms_correlation_id'] = correlation_id unless correlation_id.nil?
475
+
476
+ delivery_mode = jms_delivery_mode(msg)
477
+ map['jms_delivery_mode'] = delivery_mode unless delivery_mode.nil?
478
+
479
+ destination = msg.getJMSDestination # javax.jms.Destination
480
+ map['jms_destination'] = destination.to_string unless destination.nil?
481
+
482
+ reply_to = msg.getJMSReplyTo # javax.jms.Destination
483
+ map['jms_reply_to'] = reply_to.to_string unless reply_to.nil?
484
+
485
+ map
486
+ end
487
+
488
+ private
489
+
490
+ def jms_delivery_mode(msg)
491
+ case msg.getJMSDeliveryMode
492
+ when javax.jms.DeliveryMode::PERSISTENT
493
+ 'persistent'
494
+ when javax.jms.DeliveryMode::NON_PERSISTENT
495
+ 'non_persistent'
496
+ else
497
+ nil
498
+ end
499
+ end
500
+
501
+ INSTANCE = self.new
502
+
503
+ end
504
+
505
+ # For plugin compatibility due the use of JMS gem's Message#attributes.
506
+ class LegacyHeadersMapper < HeadersMapper
507
+
508
+ def call(msg)
509
+ map = super(msg)
510
+ delivery_mode = jms_delivery_mode(msg)
511
+ map['jms_delivery_mode_sym'] = delivery_mode ? delivery_mode.to_sym : nil
512
+ map
513
+ end
514
+
515
+ INSTANCE = self.new
516
+
517
+ end
518
+
350
519
  end # class LogStash::Inputs::Jms
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-input-jms'
4
- s.version = '3.1.2'
4
+ s.version = '3.2.0'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Reads events from a Jms Broker"
7
7
  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"
@@ -19,15 +19,18 @@ Gem::Specification.new do |s|
19
19
  # Special flag to let us know this is actually a logstash plugin
20
20
  s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
21
21
 
22
+ s.platform = RUBY_PLATFORM
23
+
22
24
  # Gem dependencies
23
25
  s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
24
26
  s.add_runtime_dependency 'logstash-codec-json', '~> 3.0'
25
27
  s.add_runtime_dependency 'logstash-codec-plain', '~> 3.0'
28
+ s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~> 1.3'
29
+ s.add_runtime_dependency "logstash-mixin-event_support", '~> 1.0'
30
+ s.add_runtime_dependency 'logstash-mixin-validator_support', '~> 1.0'
31
+
32
+ s.add_runtime_dependency "jruby-jms", ">= 1.2.0" #(Apache 2.0 license)
26
33
  s.add_runtime_dependency 'semantic_logger', '< 4.0.0'
27
34
 
28
- if RUBY_PLATFORM == 'java'
29
- s.platform = RUBY_PLATFORM
30
- s.add_runtime_dependency "jruby-jms", ">= 1.2.0" #(Apache 2.0 license)
31
- end
32
35
  s.add_development_dependency 'logstash-devutils'
33
36
  end
@@ -1,11 +1,8 @@
1
1
  require_relative '../spec_helper'
2
2
  require 'logstash/inputs/jms'
3
- require 'jms'
4
- require 'json'
3
+ require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
5
4
  require 'securerandom'
6
5
 
7
-
8
-
9
6
  shared_examples_for "a JMS input" do
10
7
  context 'when inputting messages' do
11
8
  let (:destination) { "#{pub_sub ? 'topic' : 'queue'}://#{queue_name}"}
@@ -15,7 +12,7 @@ shared_examples_for "a JMS input" do
15
12
  let(:message) { "Hello There" }
16
13
 
17
14
  context 'when properties are skipped' do
18
- let (:jms_config) { super.merge({'skip_properties' => ['this', 'that']})}
15
+ let (:config) { super().merge({'skip_properties' => ['this', 'that']})}
19
16
 
20
17
  it 'should skip the specified property and process other properties, headers and the message' do
21
18
  send_message do |session|
@@ -25,7 +22,7 @@ shared_examples_for "a JMS input" do
25
22
  msg.set_string_property('the_other', 'the_other_prop')
26
23
  msg
27
24
  end
28
- expect(queue.first.get('message')).to eql (message)
25
+ expect(queue.first.get('message')).to eql(message)
29
26
  expect(queue.first.get('jms_destination')).to_not be_nil
30
27
  expect(queue.first.get('jms_timestamp')).to_not be_nil
31
28
  expect(queue.first.get('this')).to be_nil
@@ -35,7 +32,7 @@ shared_examples_for "a JMS input" do
35
32
  end
36
33
 
37
34
  context 'when using message selectors' do
38
- let (:jms_config) { super.merge({'selector' => selector }) }
35
+ let (:config) { super().merge({'selector' => selector }) }
39
36
 
40
37
  context 'with multiple selector query parameter' do
41
38
  let (:selector) { "this = 3 OR this = 4" }
@@ -47,7 +44,7 @@ shared_examples_for "a JMS input" do
47
44
  msg.set_int_property('this', 4)
48
45
  msg
49
46
  end
50
- expect(queue.first.get('message')).to eql (message)
47
+ expect(queue.first.get('message')).to eql(message)
51
48
  expect(queue.first.get('this')).to eql(4)
52
49
  expect(queue.first.get('that')).to eql('that_prop')
53
50
  end
@@ -73,7 +70,7 @@ shared_examples_for "a JMS input" do
73
70
  msg.set_int_property('this', 3)
74
71
  msg
75
72
  end
76
- expect(queue.first.get('message')).to eql (message)
73
+ expect(queue.first.get('message')).to eql(message)
77
74
  expect(queue.first.get('this')).to eql(3)
78
75
  expect(queue.first.get('that')).to eql('that_prop')
79
76
  end
@@ -126,7 +123,7 @@ shared_examples_for "a JMS input" do
126
123
  msg.set_string_property('that', 'that_prop')
127
124
  msg
128
125
  end
129
- expect(queue.first.get('message')).to eql (message)
126
+ expect(queue.first.get('message')).to eql(message)
130
127
  expect(queue.first.get('this')).to eql('this_prop')
131
128
  expect(queue.first.get('that')).to eql('that_prop')
132
129
  end
@@ -145,7 +142,8 @@ shared_examples_for "a JMS input" do
145
142
  end
146
143
 
147
144
  context 'when headers are skipped' do
148
- let (:jms_config) { super.merge({'skip_headers' => ['jms_destination', 'jms_reply_to']})}
145
+ let (:config) { super().merge('skip_headers' => ['jms_destination', 'jms_reply_to']) }
146
+
149
147
  it 'should skip the specified header and process other headers, properties and the message' do
150
148
  send_message do |session|
151
149
  msg = session.message(message)
@@ -155,7 +153,7 @@ shared_examples_for "a JMS input" do
155
153
  msg.set_string_property('the_other', 'the_other_prop')
156
154
  msg
157
155
  end
158
- expect(queue.first.get('message')).to eql (message)
156
+ expect(queue.first.get('message')).to eql(message)
159
157
  expect(queue.first.get('jms_destination')).to be_nil
160
158
  expect(queue.first.get('jms_timestamp')).to_not be_nil
161
159
  expect(queue.first.get('this')).to eq('this_prop')
@@ -164,33 +162,124 @@ shared_examples_for "a JMS input" do
164
162
  end
165
163
  end
166
164
 
167
- context 'when neither header nor property is skipped ' do
168
- it 'should process properties, headers and the message' do
165
+ context 'when include_headers => false' do
166
+ let (:config) { super().merge('include_headers' => 'false') }
167
+
168
+ it 'should skip all headers' do
169
169
  send_message do |session|
170
170
  msg = session.message(message)
171
- msg.set_string_property('this', 'this_prop')
172
- msg.set_string_property('that', 'that_prop')
173
- msg.set_string_property('the_other', 'the_other_prop')
171
+ msg.reply_to = session.create_destination(:topic_name => SecureRandom.hex(8))
172
+ msg.set_string_property('some', 'property')
174
173
  msg
175
174
  end
176
- expect(queue.first.get('message')).to eql (message)
177
- expect(queue.first.get('jms_timestamp')).to_not be_nil
178
- expect(queue.first.get('jms_destination')).to_not be_nil
179
- expect(queue.first.get('this')).to eq('this_prop')
180
- expect(queue.first.get('that')).to eq('that_prop')
181
- expect(queue.first.get('the_other')).to eq('the_other_prop')
175
+ event = queue.first.to_hash_with_metadata
176
+ expect( event.keys.find { |name| name.start_with?('jms_') } ).to be nil
177
+ end
178
+ end
179
+
180
+ context 'when include_header => false (deprecated)' do
181
+ let (:config) { super().merge('include_header' => 'false') }
182
+
183
+ it 'should skip all headers' do
184
+ send_message do |session|
185
+ msg = session.message(message)
186
+ msg.reply_to = session.create_destination(:topic_name => SecureRandom.hex(8))
187
+ msg.set_string_property('some', 'property')
188
+ msg
189
+ end
190
+ event = queue.first.to_hash_with_metadata
191
+ expect( event.keys.find { |name| name.start_with?('jms_') } ).to be nil
192
+ end
193
+ end
194
+
195
+ context 'when neither header nor property is skipped', :ecs_compatibility_support do
196
+ ecs_compatibility_matrix(:disabled, :v1, :v8) do |ecs_select|
197
+
198
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
199
+
200
+ let (:config) { super().merge('ecs_compatibility' => ecs_select.active_mode) }
201
+
202
+ it 'should process properties, headers and the message' do
203
+ send_message do |session|
204
+ msg = session.message(message)
205
+ msg.set_string_property('this', 'this_prop')
206
+ msg.set_int_property('camelCase', 42)
207
+ msg.set_boolean_property('JMSFlag', true)
208
+ msg
209
+ end
210
+
211
+ event = queue.first
212
+
213
+ expect(event.get('message')).to eql(message)
214
+
215
+ # headers
216
+ if ecs_compatibility?
217
+ expect(event.include?('jms_timestamp')).to be false
218
+ expect(event.include?('jms_destination')).to be false
219
+ expect(event.get('[@metadata][input][jms][headers][jms_timestamp]')).to be_a Integer
220
+ expect(event.get('[@metadata][input][jms][headers][jms_destination]')).to_not be nil
221
+ expect(event.include?("[@metadata][input][jms][headers][jms_delivery_mode_sym]")).to be false
222
+ expect(event.include?("[@metadata][input][jms][headers][jms_delivery_mode]")).to be true
223
+ else
224
+ expect(event.get('jms_timestamp')).to be_a Integer
225
+ expect(event.get('jms_destination')).to_not be nil
226
+ expect(event.include?("jms_delivery_mode_sym")).to be true
227
+ end
228
+
229
+ # properties
230
+ if ecs_compatibility?
231
+ expect(event.include?('this')).to be false
232
+ expect(event.get('[@metadata][input][jms][properties][this]')).to eq 'this_prop'
233
+ expect(event.get('[@metadata][input][jms][properties][camelCase]')).to eq 42
234
+ expect(event.get('[@metadata][input][jms][properties][JMSFlag]')).to be true
235
+ else
236
+ expect(event.get('this')).to eq 'this_prop'
237
+ expect(event.get('camelCase')).to eq 42
238
+ expect(event.get('JMSFlag')).to be true
239
+ end
240
+ end
241
+
182
242
  end
183
243
  end
184
244
  end
185
245
 
186
- context 'when the message is map message' do
187
- let(:message) { {:one => 1} }
188
- it 'should read the message' do
189
- send_message
190
- expect(queue.size).to eql 1
191
- expect(queue.first.get('one')).to eql (1)
192
- expect(queue.first.get("jms_destination")).to eql(destination)
246
+ context 'when the message is map message', :ecs_compatibility_support do
247
+
248
+ ecs_compatibility_matrix(:disabled, :v1, :v8) do |ecs_select|
249
+
250
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
251
+
252
+ let (:config) { super().merge('ecs_compatibility' => ecs_select.active_mode) }
253
+
254
+ let(:message) { {:one => 1} }
255
+
256
+ before do
257
+ if ecs_compatibility?
258
+ expect(subject.logger).to receive(:info).once.with /ECS compatibility is enabled but `target` option was not specified/i
259
+ end
260
+ end
261
+
262
+ it 'should read the message' do
263
+ send_message
264
+
265
+ expect(queue.size).to eql 1
266
+ event = queue.first
267
+ expect(event.get('one')).to eql 1
268
+
269
+ if ecs_compatibility?
270
+ expect(event.get('[@metadata][input][jms][headers][jms_destination]')).to eql(destination)
271
+ expect(event.get('[@metadata][input][jms][headers][jms_delivery_mode]')).to eql 'persistent'
272
+ expect(event.include?('[@metadata][input][jms][headers][jms_delivery_mode_sym]')).to be false
273
+ else
274
+ expect(event.get("jms_destination")).to eql(destination)
275
+ expect(event.get("jms_delivery_mode_sym")).to eql :persistent
276
+ end
277
+
278
+ send_message # should not log the ECS warning again
279
+ end
280
+
193
281
  end
282
+
194
283
  end
195
284
 
196
285
  context 'when the message is a bytes message' do
@@ -203,17 +292,26 @@ shared_examples_for "a JMS input" do
203
292
  jms_message
204
293
  end
205
294
  expect(queue.size).to eql 1
206
- expect(queue.first.get('message')).to eql ('hello world')
295
+ expect(queue.first.get('message')).to eql 'hello world'
207
296
  expect(queue.first.get("jms_destination")).to eql(destination)
208
297
  end
209
298
  end
210
299
  end
211
300
  end
212
301
 
213
- describe "input/jms", :integration => true do
302
+ describe LogStash::Inputs::Jms, :integration => true do
214
303
  let (:message) { "hello World" }
215
304
  let (:queue_name) { SecureRandom.hex(8)}
216
305
 
306
+ let (:yaml_section) { 'activemq' }
307
+ let (:config) {{'yaml_file' => fixture_path("jms.yml"),
308
+ 'yaml_section' => yaml_section,
309
+ 'destination' => queue_name,
310
+ 'pub_sub' => pub_sub,
311
+ 'interval' => 2}}
312
+
313
+ subject(:input) { described_class.new(config) }
314
+
217
315
  before :each do
218
316
  allow(input).to receive(:jms_config_from_yaml) do |yaml_file, section|
219
317
  settings = YAML.load_file(yaml_file)[section]
@@ -222,14 +320,6 @@ describe "input/jms", :integration => true do
222
320
  end
223
321
  end
224
322
 
225
- let (:yaml_section) { 'activemq' }
226
- let (:jms_config) {{'yaml_file' => fixture_path("jms.yml"),
227
- 'yaml_section' => yaml_section,
228
- 'destination' => queue_name,
229
- 'pub_sub' => pub_sub,
230
- 'interval' => 2}}
231
- let(:input) { LogStash::Plugin.lookup("input", "jms").new(jms_config) }
232
-
233
323
  after :each do
234
324
  input.close unless input.nil?
235
325
  end
@@ -241,7 +331,7 @@ describe "input/jms", :integration => true do
241
331
  end
242
332
 
243
333
  context 'with pub_sub true and durable subscriber' do
244
- let (:jms_config) { super.merge({'durable_subscriber' => true,
334
+ let (:config) { super().merge({'durable_subscriber' => true,
245
335
  'durable_subscriber_client_id' => SecureRandom.hex(8),
246
336
  'durable_subscriber_name' => SecureRandom.hex(8) } ) }
247
337
 
@@ -258,8 +348,8 @@ describe "input/jms", :integration => true do
258
348
 
259
349
  context 'with tls', :tls => true do
260
350
  let (:yaml_section) { 'activemq_tls' }
261
- let (:jms_config) { super.merge({"keystore" => fixture_path("keystore.jks"), "keystore_password" => "changeit",
262
- "truststore" => fixture_path("keystore.jks"), "truststore_password" => "changeit"})}
351
+ let (:config) { super().merge({"keystore" => fixture_path("keystore.jks"), "keystore_password" => "changeit",
352
+ "truststore" => fixture_path("keystore.jks"), "truststore_password" => "changeit"})}
263
353
 
264
354
  context 'with pub_sub true' do
265
355
  let (:pub_sub) { true }
@@ -267,7 +357,7 @@ describe "input/jms", :integration => true do
267
357
  end
268
358
 
269
359
  context 'with pub_sub true and durable subscriber' do
270
- let (:jms_config) { super.merge({'durable_subscriber' => true,
360
+ let (:config) { super().merge({'durable_subscriber' => true,
271
361
  'durable_subscriber_client_id' => SecureRandom.hex(8),
272
362
  'durable_subscriber_name' => SecureRandom.hex(8) } ) }
273
363
 
@@ -1,9 +1,9 @@
1
1
  require_relative '../spec_helper'
2
2
  require 'logstash/inputs/jms'
3
- require 'jms'
4
- require 'json'
3
+ require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
4
+ require 'securerandom'
5
5
 
6
- describe "inputs/jms" do
6
+ describe LogStash::Inputs::Jms do
7
7
  let (:queue_name) {SecureRandom.hex(8)}
8
8
  let (:jms_config) {{'destination' => queue_name}}
9
9
 
@@ -37,10 +37,10 @@ describe "inputs/jms" do
37
37
  context 'configuration check' do
38
38
  context 'if threads is > 1' do
39
39
  let(:thread_count) { 2 }
40
- let(:jms_config) { super.merge({'threads' => thread_count})}
40
+ let(:jms_config) { super().merge({'threads' => thread_count})}
41
41
 
42
42
  context 'with pub_sub set to true' do
43
- let(:jms_config) { super.merge({'pub_sub' => true})}
43
+ let(:jms_config) { super().merge({'pub_sub' => true})}
44
44
 
45
45
  it 'should raise a configuration error' do
46
46
  expect { plugin.register }.to raise_error(LogStash::ConfigurationError)
@@ -48,7 +48,7 @@ describe "inputs/jms" do
48
48
  end
49
49
 
50
50
  context 'with pub_sub set to false' do
51
- let(:jms_config) { super.merge({'pub_sub' => false})}
51
+ let(:jms_config) { super().merge({'pub_sub' => false})}
52
52
 
53
53
  it 'should not raise a configuration error' do
54
54
  plugin.register
@@ -58,13 +58,13 @@ describe "inputs/jms" do
58
58
  end
59
59
 
60
60
  context 'with durable_subscriber set' do
61
- let(:jms_config) { super.merge({ 'pub_sub' => true,
61
+ let(:jms_config) { super().merge({ 'pub_sub' => true,
62
62
  'durable_subscriber' => true,
63
63
  'durable_subscriber_name' => SecureRandom.hex(8),
64
64
  'durable_subscriber_client_id' => SecureRandom.hex(8)})}
65
65
 
66
66
  context 'if durable_subscriber_client_id is not set' do
67
- let(:jms_config) { super.tap { |h| h.delete('durable_subscriber_client_id') } }
67
+ let(:jms_config) { super().tap { |h| h.delete('durable_subscriber_client_id') } }
68
68
 
69
69
  it 'should set client_id to Logstash' do
70
70
  plugin.register
@@ -73,7 +73,7 @@ describe "inputs/jms" do
73
73
  end
74
74
 
75
75
  context 'if durable_subscriber_name is not set' do
76
- let(:jms_config) { super.tap { |h| h.delete('durable_subscriber_name') } }
76
+ let(:jms_config) { super().tap { |h| h.delete('durable_subscriber_name') } }
77
77
 
78
78
  it 'should set name to the topic name' do
79
79
  plugin.register
@@ -83,7 +83,7 @@ describe "inputs/jms" do
83
83
 
84
84
 
85
85
  context 'if pub_sub is set to false' do
86
- let(:jms_config) { super.merge({'pub_sub' => false})}
86
+ let(:jms_config) { super().merge({'pub_sub' => false})}
87
87
  it 'should raise a configuration error' do
88
88
  expect { plugin.register }.to raise_error(LogStash::ConfigurationError)
89
89
  end
@@ -253,4 +253,60 @@ describe "inputs/jms" do
253
253
  end
254
254
  end
255
255
  end
256
+
257
+ context 'invalid configuration' do
258
+ let (:jms_config) { super().merge('include_headers' => true, 'include_header' => false) }
259
+
260
+ it 'should raise a configuration error' do
261
+ expect { subject.register }.to raise_error LogStash::ConfigurationError,
262
+ /Both `include_headers => true` and `include_header => false` options are specified/i
263
+ end
264
+ end
265
+
266
+ context 'targets', :ecs_compatibility_support do
267
+
268
+ ecs_compatibility_matrix(:disabled, :v1, :v8) do |ecs_select|
269
+
270
+ let (:jms_config) do
271
+ super().merge(
272
+ 'include_body' => false,
273
+ 'include_headers' => true, 'headers_target' => '@metadata',
274
+ 'include_properties' => true, 'properties_target' => '[@metadata]'
275
+ )
276
+ end
277
+
278
+ let(:jms_timestamp) { 1 }
279
+
280
+ let(:jms_message_double) do
281
+ message = double('jms-message-stub')
282
+ allow(message).to receive(:jms_timestamp).and_return(jms_timestamp)
283
+ allow_any_instance_of(described_class).to receive(:map_headers).and_return(
284
+ 'jms_message_id' => 'id1', 'jms_timestamp' => jms_timestamp, 'jms_expiration' => nil
285
+ )
286
+ allow(message).to receive(:properties).and_return(:foo => 'bar', 'the-baz' => 42)
287
+ message
288
+ end
289
+
290
+ before(:each) do
291
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
292
+
293
+ plugin.register
294
+ plugin.queue_event(jms_message_double, queue = [])
295
+ expect(queue.size).to eql 1
296
+ @event = queue.first
297
+ end
298
+
299
+ it 'sets headers into meta-data' do
300
+ expect( @event.get('[@metadata][jms_timestamp]') ).to eql jms_timestamp
301
+ expect( @event.get('[@metadata][jms_message_id]') ).to_not be nil
302
+ end
303
+
304
+ it 'sets properties as meta-data' do
305
+ expect( @event.get('[@metadata][foo]') ).to eql 'bar'
306
+ expect( @event.get('[@metadata][the-baz]') ).to eql 42
307
+ end
308
+
309
+ end
310
+
311
+ end
256
312
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-jms
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.2
4
+ version: 3.2.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elasticsearch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-05 00:00:00.000000000 Z
11
+ date: 2021-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -61,17 +61,45 @@ dependencies:
61
61
  - !ruby/object:Gem::Dependency
62
62
  requirement: !ruby/object:Gem::Requirement
63
63
  requirements:
64
- - - "<"
64
+ - - "~>"
65
65
  - !ruby/object:Gem::Version
66
- version: 4.0.0
67
- name: semantic_logger
66
+ version: '1.3'
67
+ name: logstash-mixin-ecs_compatibility_support
68
68
  prerelease: false
69
69
  type: :runtime
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - "<"
72
+ - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 4.0.0
74
+ version: '1.3'
75
+ - !ruby/object:Gem::Dependency
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '1.0'
81
+ name: logstash-mixin-event_support
82
+ prerelease: false
83
+ type: :runtime
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.0'
89
+ - !ruby/object:Gem::Dependency
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '1.0'
95
+ name: logstash-mixin-validator_support
96
+ prerelease: false
97
+ type: :runtime
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.0'
75
103
  - !ruby/object:Gem::Dependency
76
104
  requirement: !ruby/object:Gem::Requirement
77
105
  requirements:
@@ -86,6 +114,20 @@ dependencies:
86
114
  - - ">="
87
115
  - !ruby/object:Gem::Version
88
116
  version: 1.2.0
117
+ - !ruby/object:Gem::Dependency
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "<"
121
+ - !ruby/object:Gem::Version
122
+ version: 4.0.0
123
+ name: semantic_logger
124
+ prerelease: false
125
+ type: :runtime
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "<"
129
+ - !ruby/object:Gem::Version
130
+ version: 4.0.0
89
131
  - !ruby/object:Gem::Dependency
90
132
  requirement: !ruby/object:Gem::Requirement
91
133
  requirements:
@@ -144,8 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
186
  - !ruby/object:Gem::Version
145
187
  version: '0'
146
188
  requirements: []
147
- rubyforge_project:
148
- rubygems_version: 2.6.13
189
+ rubygems_version: 3.1.6
149
190
  signing_key:
150
191
  specification_version: 4
151
192
  summary: Reads events from a Jms Broker