logstash-filter-kv 4.3.3 → 4.4.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: 224cad4699c558b68869188886233c5f9932777769e3b2231f96276369982ee5
4
- data.tar.gz: d9933e603f3ab6a774ebada27d42bb2d62f829344598871b6d4834b98553e785
3
+ metadata.gz: 1652dfe568f80f6a0edf650e3cf380e04c85c0e140db65fdb0c2186c2f222e0c
4
+ data.tar.gz: 5f05bab577b56d9a1d07cd9daa46d2913dae589c09b0d6706d79369dbb42df12
5
5
  SHA512:
6
- metadata.gz: 80d20a98f5c89301ae155ffbababe7be169ec5d4bde567fcde0a0117169851a15158767e3bfbc089352bbe7423052aefb237c8e14a0c5d37e1fef3cef70afdf8
7
- data.tar.gz: 2499f09c2c41b7eacdb0fb5a4db48d9ef2ffeaca3bfae8d7d089382ac9b769c06dbdf1685a72852fac21bba0844e66ba48bb3b7689d05b324e2cac832f4b2ab1
6
+ metadata.gz: 44d8f946d6d993a1629873808ff1dca95b147b82590ce77f6a5777fa5ee71e21ea6500ad64814cab37edb2f9513bd81708bd3c7695feba5ec82adefb86833515
7
+ data.tar.gz: cee074981ca16c9b5ea5446b3c5b9a829bab8b412e902d57454c764dbb7119b46430bebaa695dffa161179afdbfa7f44dbd7f3156e328620cbcd5976f3916f7f
@@ -1,3 +1,6 @@
1
+ ## 4.4.0
2
+ - Changed timeout handling using the Timeout class [#84](https://github.com/logstash-plugins/logstash-filter-kv/pull/84)
3
+
1
4
  ## 4.3.3
2
5
  - Fixed asciidoc formatting in docs
3
6
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "logstash/filters/base"
4
4
  require "logstash/namespace"
5
+ require "timeout"
5
6
 
6
7
  # This filter helps automatically parse messages (or specific event fields)
7
8
  # which are of the `foo=bar` variety.
@@ -319,8 +320,6 @@ class LogStash::Filters::KV < LogStash::Filters::Base
319
320
 
320
321
  # Attempt to terminate regexps after this amount of time.
321
322
  # This applies per source field value if event has multiple values in the source field.
322
- # This will never timeout early, but may take a little longer to timeout.
323
- # Actual timeout is approximate based on a 250ms quantization.
324
323
  # Set to 0 to disable timeouts
325
324
  config :timeout_millis, :validate => :number, :default => 30_000
326
325
 
@@ -406,26 +405,17 @@ class LogStash::Filters::KV < LogStash::Filters::Base
406
405
 
407
406
  @logger.debug? && @logger.debug("KV scan regex", :regex => @scan_re.inspect)
408
407
 
409
- @timeout_enforcer = initialize_timeout_enforcer
410
- @timeout_enforcer.start!
408
+ # divide by float to allow fractionnal seconds, the Timeout class timeout value is in seconds but the underlying
409
+ # executor resolution is in microseconds so fractionnal second parameter down to microseconds is possible.
410
+ # see https://github.com/jruby/jruby/blob/9.2.7.0/core/src/main/java/org/jruby/ext/timeout/Timeout.java#L125
411
+ @timeout_seconds = @timeout_millis / 1000.0
411
412
  end
412
413
 
413
414
  def filter(event)
414
- kv = Hash.new
415
415
  value = event.get(@source)
416
416
 
417
- @timeout_enforcer.execute do
418
- case value
419
- when nil
420
- # Nothing to do
421
- when String
422
- parse(value, event, kv)
423
- when Array
424
- value.each { |v| parse(v, event, kv) }
425
- else
426
- @logger.warn("kv filter has no support for this type of data", :type => value.class, :value => value)
427
- end
428
- end
417
+ # if timeout is 0 avoid creating a closure although Timeout.timeout has a bypass for 0s timeouts.
418
+ kv = @timeout_seconds > 0.0 ? Timeout.timeout(@timeout_seconds, TimeoutException) { parse_value(value, event) } : parse_value(value, event)
429
419
 
430
420
  # Add default key-values for missing keys
431
421
  kv = @default_keys.merge(kv)
@@ -452,11 +442,27 @@ class LogStash::Filters::KV < LogStash::Filters::Base
452
442
  end
453
443
 
454
444
  def close
455
- @timeout_enforcer.stop!
456
445
  end
457
446
 
458
447
  private
459
448
 
449
+ def parse_value(value, event)
450
+ kv = Hash.new
451
+
452
+ case value
453
+ when nil
454
+ # Nothing to do
455
+ when String
456
+ parse(value, event, kv)
457
+ when Array
458
+ value.each { |v| parse(v, event, kv) }
459
+ else
460
+ @logger.warn("kv filter has no support for this type of data", :type => value.class, :value => value)
461
+ end
462
+
463
+ kv
464
+ end
465
+
460
466
  # @overload summarize(value)
461
467
  # @param value [Array]
462
468
  # @return [String]
@@ -474,13 +480,7 @@ class LogStash::Filters::KV < LogStash::Filters::Base
474
480
 
475
481
  value.bytesize < 255 ? "`#{value}`" : "entry too large; first 255 chars are `#{value[0..255].dump}`"
476
482
  end
477
-
478
- def initialize_timeout_enforcer
479
- return NULL_TIMEOUT_ENFORCER if @timeout_millis <= 0
480
-
481
- TimeoutEnforcer.new(logger, @timeout_millis * 1_000_000)
482
- end
483
-
483
+
484
484
  def has_value_splitter?(s)
485
485
  s =~ @value_split_re
486
486
  end
@@ -596,100 +596,4 @@ class LogStash::Filters::KV < LogStash::Filters::Base
596
596
 
597
597
  class TimeoutException < RuntimeError
598
598
  end
599
-
600
- class TimeoutEnforcer
601
- def initialize(logger, timeout_nanos)
602
- @logger = logger
603
- @running = java.util.concurrent.atomic.AtomicBoolean.new(false)
604
- @timeout_nanos = timeout_nanos
605
-
606
- # Stores running matches with their start time, this is used to cancel long running matches
607
- # Is a map of Thread => start_time
608
- @threads_to_start_time = java.util.concurrent.ConcurrentHashMap.new
609
- end
610
-
611
- def execute(&block)
612
- # If the enforcer is not running, either we failed to start it or it has
613
- # already been stopped; in either case, we cannot reliably enforce the timeout
614
- # so we raise a RuntimeError instead.
615
- fail("TimeoutEnforcer not running.") unless alive?
616
-
617
- begin
618
- thread = java.lang.Thread.currentThread()
619
- @threads_to_start_time.put(thread, java.lang.System.nanoTime)
620
-
621
- yield
622
-
623
- rescue InterruptedRegexpError, java.lang.InterruptedException => e
624
- raise TimeoutException.new
625
- ensure
626
- # If the block finished, but interrupt was called after, we'll want to
627
- # clear the interrupted status anyway
628
- @threads_to_start_time.remove(thread)
629
- thread.interrupted
630
- end
631
- end
632
-
633
- def start!
634
- @running.set(true)
635
- @logger.debug("Starting timeout enforcer (#{@timeout_nanos}ns)")
636
- @timer_thread = Thread.new do
637
- while @running.get() || !@threads_to_start_time.is_empty
638
- begin
639
- cancel_timed_out!
640
- rescue Exception => e
641
- @logger.error("Error while attempting to check/cancel excessively long kv patterns",
642
- :message => e.message,
643
- :class => e.class.name,
644
- :backtrace => e.backtrace
645
- )
646
- end
647
- sleep 0.25
648
- end
649
- end
650
- end
651
-
652
- def stop!
653
- @running.set(false)
654
- @logger.debug("Shutting down timeout enforcer")
655
- # Check for the thread mostly for a fast start/shutdown scenario
656
- @timer_thread.join if @timer_thread
657
- end
658
-
659
- def alive?
660
- @running.get() && @timer_thread && @timer_thread.alive?
661
- end
662
-
663
- private
664
-
665
- def cancel_timed_out!
666
- now = java.lang.System.nanoTime # save ourselves some nanotime calls
667
- @threads_to_start_time.keySet.each do |thread|
668
- # Use compute to lock this value
669
- @threads_to_start_time.computeIfPresent(thread) do |thread, start_time|
670
- if start_time < now && now - start_time > @timeout_nanos
671
- thread.interrupt
672
- nil # Delete the key
673
- else
674
- start_time # preserve the key
675
- end
676
- end
677
- end
678
- end
679
- end
680
-
681
- class NullTimeoutEnforcer
682
- def execute(&block)
683
- yield
684
- end
685
-
686
- def start!
687
- # no-op
688
- end
689
-
690
- def stop!
691
- # no-op
692
- end
693
- end
694
- NULL_TIMEOUT_ENFORCER = NullTimeoutEnforcer.new
695
599
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-filter-kv'
4
- s.version = '4.3.3'
4
+ s.version = '4.4.0'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Parses key-value pairs"
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"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-filter-kv
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.3
4
+ version: 4.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-21 00:00:00.000000000 Z
11
+ date: 2019-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement