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 +4 -4
- data/CHANGELOG.md +3 -0
- data/lib/logstash/filters/kv.rb +25 -121
- data/logstash-filter-kv.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1652dfe568f80f6a0edf650e3cf380e04c85c0e140db65fdb0c2186c2f222e0c
|
4
|
+
data.tar.gz: 5f05bab577b56d9a1d07cd9daa46d2913dae589c09b0d6706d79369dbb42df12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44d8f946d6d993a1629873808ff1dca95b147b82590ce77f6a5777fa5ee71e21ea6500ad64814cab37edb2f9513bd81708bd3c7695feba5ec82adefb86833515
|
7
|
+
data.tar.gz: cee074981ca16c9b5ea5446b3c5b9a829bab8b412e902d57454c764dbb7119b46430bebaa695dffa161179afdbfa7f44dbd7f3156e328620cbcd5976f3916f7f
|
data/CHANGELOG.md
CHANGED
data/lib/logstash/filters/kv.rb
CHANGED
@@ -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
|
-
|
410
|
-
|
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
|
-
|
418
|
-
|
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
|
data/logstash-filter-kv.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-filter-kv'
|
4
|
-
s.version = '4.
|
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.
|
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-
|
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
|