logstash-core 2.2.4.snapshot1
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.
Potentially problematic release.
This version of logstash-core might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/lib/logstash-core.rb +1 -0
- data/lib/logstash-core/logstash-core.rb +3 -0
- data/lib/logstash-core/version.rb +8 -0
- data/lib/logstash/agent.rb +391 -0
- data/lib/logstash/codecs/base.rb +50 -0
- data/lib/logstash/config/config_ast.rb +550 -0
- data/lib/logstash/config/cpu_core_strategy.rb +32 -0
- data/lib/logstash/config/defaults.rb +12 -0
- data/lib/logstash/config/file.rb +39 -0
- data/lib/logstash/config/grammar.rb +3503 -0
- data/lib/logstash/config/mixin.rb +518 -0
- data/lib/logstash/config/registry.rb +13 -0
- data/lib/logstash/environment.rb +98 -0
- data/lib/logstash/errors.rb +12 -0
- data/lib/logstash/filters/base.rb +205 -0
- data/lib/logstash/inputs/base.rb +116 -0
- data/lib/logstash/inputs/threadable.rb +18 -0
- data/lib/logstash/java_integration.rb +116 -0
- data/lib/logstash/json.rb +61 -0
- data/lib/logstash/logging.rb +91 -0
- data/lib/logstash/namespace.rb +13 -0
- data/lib/logstash/output_delegator.rb +172 -0
- data/lib/logstash/outputs/base.rb +91 -0
- data/lib/logstash/patches.rb +5 -0
- data/lib/logstash/patches/bugfix_jruby_2558.rb +51 -0
- data/lib/logstash/patches/cabin.rb +35 -0
- data/lib/logstash/patches/profile_require_calls.rb +47 -0
- data/lib/logstash/patches/rubygems.rb +38 -0
- data/lib/logstash/patches/stronger_openssl_defaults.rb +68 -0
- data/lib/logstash/pipeline.rb +499 -0
- data/lib/logstash/pipeline_reporter.rb +114 -0
- data/lib/logstash/plugin.rb +120 -0
- data/lib/logstash/program.rb +14 -0
- data/lib/logstash/runner.rb +124 -0
- data/lib/logstash/shutdown_watcher.rb +100 -0
- data/lib/logstash/util.rb +203 -0
- data/lib/logstash/util/buftok.rb +139 -0
- data/lib/logstash/util/charset.rb +35 -0
- data/lib/logstash/util/decorators.rb +52 -0
- data/lib/logstash/util/defaults_printer.rb +31 -0
- data/lib/logstash/util/filetools.rb +186 -0
- data/lib/logstash/util/java_version.rb +66 -0
- data/lib/logstash/util/password.rb +25 -0
- data/lib/logstash/util/plugin_version.rb +56 -0
- data/lib/logstash/util/prctl.rb +10 -0
- data/lib/logstash/util/retryable.rb +40 -0
- data/lib/logstash/util/socket_peer.rb +7 -0
- data/lib/logstash/util/unicode_trimmer.rb +81 -0
- data/lib/logstash/util/worker_threads_default_printer.rb +29 -0
- data/lib/logstash/util/wrapped_synchronous_queue.rb +41 -0
- data/lib/logstash/version.rb +14 -0
- data/locales/en.yml +204 -0
- data/logstash-core.gemspec +58 -0
- data/spec/conditionals_spec.rb +429 -0
- data/spec/logstash/agent_spec.rb +85 -0
- data/spec/logstash/config/config_ast_spec.rb +146 -0
- data/spec/logstash/config/cpu_core_strategy_spec.rb +123 -0
- data/spec/logstash/config/defaults_spec.rb +10 -0
- data/spec/logstash/config/mixin_spec.rb +158 -0
- data/spec/logstash/environment_spec.rb +56 -0
- data/spec/logstash/filters/base_spec.rb +251 -0
- data/spec/logstash/inputs/base_spec.rb +74 -0
- data/spec/logstash/java_integration_spec.rb +304 -0
- data/spec/logstash/json_spec.rb +96 -0
- data/spec/logstash/output_delegator_spec.rb +144 -0
- data/spec/logstash/outputs/base_spec.rb +40 -0
- data/spec/logstash/patches_spec.rb +90 -0
- data/spec/logstash/pipeline_reporter_spec.rb +85 -0
- data/spec/logstash/pipeline_spec.rb +455 -0
- data/spec/logstash/plugin_spec.rb +169 -0
- data/spec/logstash/runner_spec.rb +68 -0
- data/spec/logstash/shutdown_watcher_spec.rb +113 -0
- data/spec/logstash/util/buftok_spec.rb +31 -0
- data/spec/logstash/util/charset_spec.rb +74 -0
- data/spec/logstash/util/defaults_printer_spec.rb +50 -0
- data/spec/logstash/util/java_version_spec.rb +79 -0
- data/spec/logstash/util/plugin_version_spec.rb +64 -0
- data/spec/logstash/util/unicode_trimmer_spec.rb +55 -0
- data/spec/logstash/util/worker_threads_default_printer_spec.rb +45 -0
- data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +28 -0
- data/spec/logstash/util_spec.rb +35 -0
- metadata +364 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "java"
|
3
|
+
|
4
|
+
# this is mainly for usage with JrJackson json parsing in :raw mode which genenerates
|
5
|
+
# Java::JavaUtil::ArrayList and Java::JavaUtil::LinkedHashMap native objects for speed.
|
6
|
+
# these object already quacks like their Ruby equivalents Array and Hash but they will
|
7
|
+
# not test for is_a?(Array) or is_a?(Hash) and we do not want to include tests for
|
8
|
+
# both classes everywhere. see LogStash::JSon.
|
9
|
+
|
10
|
+
class Array
|
11
|
+
# enable class equivalence between Array and ArrayList
|
12
|
+
# so that ArrayList will work with case o when Array ...
|
13
|
+
def self.===(other)
|
14
|
+
return true if other.is_a?(Java::JavaUtil::Collection)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Hash
|
20
|
+
# enable class equivalence between Hash and LinkedHashMap
|
21
|
+
# so that LinkedHashMap will work with case o when Hash ...
|
22
|
+
def self.===(other)
|
23
|
+
return true if other.is_a?(Java::JavaUtil::Map)
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# map_mixin to patch LinkedHashMap and HashMap. it must be done directly on the classes,
|
29
|
+
# using a module mixin does not work, and injecting in the Map interface does not work either
|
30
|
+
# but injecting in the class works.
|
31
|
+
|
32
|
+
map_mixin = lambda do
|
33
|
+
# this is a temporary fix to solve a bug in JRuby where classes implementing the Map interface, like LinkedHashMap
|
34
|
+
# have a bug in the has_key? method that is implemented in the Enumerable module that is somehow mixed in the Map interface.
|
35
|
+
# this bug makes has_key? (and all its aliases) return false for a key that has a nil value.
|
36
|
+
# Only LinkedHashMap is patched here because patching the Map interface is not working.
|
37
|
+
# TODO find proper fix, and submit upstream
|
38
|
+
# releavant JRuby files:
|
39
|
+
# https://github.com/jruby/jruby/blob/master/core/src/main/ruby/jruby/java/java_ext/java.util.rb
|
40
|
+
# https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/java/proxies/MapJavaProxy.java
|
41
|
+
def has_key?(key)
|
42
|
+
self.containsKey(key)
|
43
|
+
end
|
44
|
+
alias_method :include?, :has_key?
|
45
|
+
alias_method :member?, :has_key?
|
46
|
+
alias_method :key?, :has_key?
|
47
|
+
|
48
|
+
# Java 8 Map implements a merge method with a different signature from
|
49
|
+
# the Ruby Hash#merge. see https://github.com/jruby/jruby/issues/1249
|
50
|
+
# this can be removed when fixed upstream
|
51
|
+
if ENV_JAVA['java.specification.version'] >= '1.8'
|
52
|
+
def merge(other)
|
53
|
+
dup.merge!(other)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Java::JavaUtil::LinkedHashMap.module_exec(&map_mixin)
|
59
|
+
Java::JavaUtil::HashMap.module_exec(&map_mixin)
|
60
|
+
|
61
|
+
module java::util::Map
|
62
|
+
# have Map objects like LinkedHashMap objects report is_a?(Array) == true
|
63
|
+
def is_a?(clazz)
|
64
|
+
return true if clazz == Hash
|
65
|
+
super
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module java::util::Collection
|
70
|
+
# have Collections objects like ArrayList report is_a?(Array) == true
|
71
|
+
def is_a?(clazz)
|
72
|
+
return true if clazz == Array
|
73
|
+
super
|
74
|
+
end
|
75
|
+
|
76
|
+
# support the Ruby Array delete method on a Java Collection
|
77
|
+
def delete(o)
|
78
|
+
self.removeAll([o]) ? o : block_given? ? yield : nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def compact
|
82
|
+
duped = Java::JavaUtil::ArrayList.new(self)
|
83
|
+
duped.compact!
|
84
|
+
duped
|
85
|
+
end
|
86
|
+
|
87
|
+
def compact!
|
88
|
+
size_before = self.size
|
89
|
+
self.removeAll(java::util::Collections.singleton(nil))
|
90
|
+
if size_before == self.size
|
91
|
+
nil
|
92
|
+
else
|
93
|
+
self
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# support the Ruby intersection method on Java Collection
|
98
|
+
def &(other)
|
99
|
+
# transform self into a LinkedHashSet to remove duplicates and preserve order as defined by the Ruby Array intersection contract
|
100
|
+
duped = Java::JavaUtil::LinkedHashSet.new(self)
|
101
|
+
duped.retainAll(other)
|
102
|
+
duped
|
103
|
+
end
|
104
|
+
|
105
|
+
# support the Ruby union method on Java Collection
|
106
|
+
def |(other)
|
107
|
+
# transform self into a LinkedHashSet to remove duplicates and preserve order as defined by the Ruby Array union contract
|
108
|
+
duped = Java::JavaUtil::LinkedHashSet.new(self)
|
109
|
+
duped.addAll(other)
|
110
|
+
duped
|
111
|
+
end
|
112
|
+
|
113
|
+
def inspect
|
114
|
+
"<#{self.class.name}:#{self.hashCode} #{self.to_a(&:inspect)}>"
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/environment"
|
3
|
+
require "logstash/errors"
|
4
|
+
if LogStash::Environment.jruby?
|
5
|
+
require "jrjackson"
|
6
|
+
require "logstash/java_integration"
|
7
|
+
else
|
8
|
+
require "oj"
|
9
|
+
end
|
10
|
+
|
11
|
+
module LogStash
|
12
|
+
module Json
|
13
|
+
class ParserError < LogStash::Error; end
|
14
|
+
class GeneratorError < LogStash::Error; end
|
15
|
+
|
16
|
+
extend self
|
17
|
+
|
18
|
+
### MRI
|
19
|
+
|
20
|
+
def mri_load(data, options = {})
|
21
|
+
Oj.load(data)
|
22
|
+
rescue Oj::ParseError => e
|
23
|
+
raise LogStash::Json::ParserError.new(e.message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def mri_dump(o)
|
27
|
+
Oj.dump(o, :mode => :compat, :use_to_json => true)
|
28
|
+
rescue => e
|
29
|
+
raise LogStash::Json::GeneratorError.new(e.message)
|
30
|
+
end
|
31
|
+
|
32
|
+
### JRuby
|
33
|
+
|
34
|
+
def jruby_load(data, options = {})
|
35
|
+
# TODO [guyboertje] remove these comments in 5.0
|
36
|
+
# options[:symbolize_keys] ? JrJackson::Raw.parse_sym(data) : JrJackson::Raw.parse_raw(data)
|
37
|
+
|
38
|
+
JrJackson::Ruby.parse(data, options)
|
39
|
+
|
40
|
+
rescue JrJackson::ParseError => e
|
41
|
+
raise LogStash::Json::ParserError.new(e.message)
|
42
|
+
end
|
43
|
+
|
44
|
+
def jruby_dump(o)
|
45
|
+
# TODO [guyboertje] remove these comments in 5.0
|
46
|
+
# test for enumerable here to work around an omission in JrJackson::Json.dump to
|
47
|
+
# also look for Java::JavaUtil::ArrayList, see TODO submit issue
|
48
|
+
# o.is_a?(Enumerable) ? JrJackson::Raw.generate(o) : JrJackson::Json.dump(o)
|
49
|
+
|
50
|
+
JrJackson::Base.generate(o, {})
|
51
|
+
|
52
|
+
rescue => e
|
53
|
+
raise LogStash::Json::GeneratorError.new(e.message)
|
54
|
+
end
|
55
|
+
|
56
|
+
prefix = LogStash::Environment.jruby? ? "jruby" : "mri"
|
57
|
+
alias_method :load, "#{prefix}_load".to_sym
|
58
|
+
alias_method :dump, "#{prefix}_dump".to_sym
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require "cabin"
|
4
|
+
require "logger"
|
5
|
+
|
6
|
+
class LogStash::Logger
|
7
|
+
attr_accessor :target
|
8
|
+
|
9
|
+
public
|
10
|
+
def initialize(*args)
|
11
|
+
super()
|
12
|
+
|
13
|
+
#self[:program] = File.basename($0)
|
14
|
+
#subscribe(::Logger.new(*args))
|
15
|
+
@target = args[0]
|
16
|
+
@channel = Cabin::Channel.get(LogStash)
|
17
|
+
|
18
|
+
# lame hack until cabin's smart enough not to doubley-subscribe something.
|
19
|
+
# without this subscription count check, running the test suite
|
20
|
+
# causes Cabin to subscribe to STDOUT maaaaaany times.
|
21
|
+
subscriptions = @channel.instance_eval { @subscribers.count }
|
22
|
+
@channel.subscribe(@target) unless subscriptions > 0
|
23
|
+
|
24
|
+
# Set default loglevel to WARN unless $DEBUG is set (run with 'ruby -d')
|
25
|
+
@level = $DEBUG ? :debug : :warn
|
26
|
+
if ENV["LOGSTASH_DEBUG"]
|
27
|
+
@level = :debug
|
28
|
+
end
|
29
|
+
|
30
|
+
# Direct metrics elsewhere.
|
31
|
+
@channel.metrics.channel = Cabin::Channel.new
|
32
|
+
end # def initialize
|
33
|
+
|
34
|
+
# Delegation
|
35
|
+
def level=(value) @channel.level = value; end
|
36
|
+
def debug(*args); @channel.debug(*args); end
|
37
|
+
def debug?(*args); @channel.debug?(*args); end
|
38
|
+
def info(*args); @channel.info(*args); end
|
39
|
+
def info?(*args); @channel.info?(*args); end
|
40
|
+
def warn(*args); @channel.warn(*args); end
|
41
|
+
def warn?(*args); @channel.warn?(*args); end
|
42
|
+
def error(*args); @channel.error(*args); end
|
43
|
+
def error?(*args); @channel.error?(*args); end
|
44
|
+
def fatal(*args); @channel.fatal(*args); end
|
45
|
+
def fatal?(*args); @channel.fatal?(*args); end
|
46
|
+
|
47
|
+
def self.setup_log4j(logger)
|
48
|
+
require "java"
|
49
|
+
|
50
|
+
properties = java.util.Properties.new
|
51
|
+
log4j_level = "WARN"
|
52
|
+
case logger.level
|
53
|
+
when :debug
|
54
|
+
log4j_level = "DEBUG"
|
55
|
+
when :info
|
56
|
+
log4j_level = "INFO"
|
57
|
+
when :warn
|
58
|
+
log4j_level = "WARN"
|
59
|
+
end # case level
|
60
|
+
properties.setProperty("log4j.rootLogger", "#{log4j_level},logstash")
|
61
|
+
|
62
|
+
# TODO(sissel): This is a shitty hack to work around the fact that
|
63
|
+
# LogStash::Logger isn't used anymore. We should fix that.
|
64
|
+
target = logger.instance_eval { @subscribers }.values.first.instance_eval { @io }
|
65
|
+
case target
|
66
|
+
when STDOUT
|
67
|
+
properties.setProperty("log4j.appender.logstash",
|
68
|
+
"org.apache.log4j.ConsoleAppender")
|
69
|
+
properties.setProperty("log4j.appender.logstash.Target", "System.out")
|
70
|
+
when STDERR
|
71
|
+
properties.setProperty("log4j.appender.logstash",
|
72
|
+
"org.apache.log4j.ConsoleAppender")
|
73
|
+
properties.setProperty("log4j.appender.logstash.Target", "System.err")
|
74
|
+
when target.is_a?(File)
|
75
|
+
properties.setProperty("log4j.appender.logstash",
|
76
|
+
"org.apache.log4j.FileAppender")
|
77
|
+
properties.setProperty("log4j.appender.logstash.File", target.path)
|
78
|
+
else
|
79
|
+
properties.setProperty("log4j.appender.logstash", "org.apache.log4j.varia.NullAppender")
|
80
|
+
end # case target
|
81
|
+
|
82
|
+
properties.setProperty("log4j.appender.logstash.layout",
|
83
|
+
"org.apache.log4j.PatternLayout")
|
84
|
+
properties.setProperty("log4j.appender.logstash.layout.conversionPattern",
|
85
|
+
"log4j, [%d{yyyy-MM-dd}T%d{HH:mm:ss.SSS}] %5p: %c: %m%n")
|
86
|
+
|
87
|
+
org.apache.log4j.LogManager.resetConfiguration
|
88
|
+
org.apache.log4j.PropertyConfigurator.configure(properties)
|
89
|
+
logger.debug("log4j java properties setup", :log4j_level => log4j_level)
|
90
|
+
end
|
91
|
+
end # class LogStash::Logger
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module LogStash
|
3
|
+
module Inputs; end
|
4
|
+
module Outputs; end
|
5
|
+
module Filters; end
|
6
|
+
module Search; end
|
7
|
+
module Config; end
|
8
|
+
module File; end
|
9
|
+
module Web; end
|
10
|
+
module Util; end
|
11
|
+
module PluginMixins; end
|
12
|
+
module PluginManager; end
|
13
|
+
end # module LogStash
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "concurrent/atomic/atomic_fixnum"
|
3
|
+
java_import "java.util.concurrent.CopyOnWriteArrayList"
|
4
|
+
|
5
|
+
# This class goes hand in hand with the pipeline to provide a pool of
|
6
|
+
# free workers to be used by pipeline worker threads. The pool is
|
7
|
+
# internally represented with a SizedQueue set the the size of the number
|
8
|
+
# of 'workers' the output plugin is configured with.
|
9
|
+
#
|
10
|
+
# This plugin also records some basic statistics
|
11
|
+
module LogStash class OutputDelegator
|
12
|
+
attr_reader :workers, :config, :threadsafe
|
13
|
+
|
14
|
+
# The *args this takes are the same format that a Outputs::Base takes. A list of hashes with parameters in them
|
15
|
+
# Internally these just get merged together into a single hash
|
16
|
+
def initialize(logger, klass, default_worker_count, *plugin_args)
|
17
|
+
@logger = logger
|
18
|
+
@threadsafe = klass.threadsafe?
|
19
|
+
@config = plugin_args.reduce({}, :merge)
|
20
|
+
@klass = klass
|
21
|
+
@workers = java.util.concurrent.CopyOnWriteArrayList.new
|
22
|
+
@default_worker_count = default_worker_count
|
23
|
+
@registered = false
|
24
|
+
@events_received = Concurrent::AtomicFixnum.new(0)
|
25
|
+
end
|
26
|
+
|
27
|
+
def threadsafe?
|
28
|
+
!!@threadsafe
|
29
|
+
end
|
30
|
+
|
31
|
+
def warn_on_worker_override!
|
32
|
+
# The user has configured extra workers, but this plugin doesn't support it :(
|
33
|
+
if worker_limits_overriden?
|
34
|
+
message = @klass.workers_not_supported_message
|
35
|
+
warning_meta = {:plugin => @klass.config_name, :worker_count => @config["workers"]}
|
36
|
+
if message
|
37
|
+
warning_meta[:message] = message
|
38
|
+
@logger.warn(I18n.t("logstash.pipeline.output-worker-unsupported-with-message", warning_meta))
|
39
|
+
else
|
40
|
+
@logger.warn(I18n.t("logstash.pipeline.output-worker-unsupported", warning_meta))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def worker_limits_overriden?
|
46
|
+
@config["workers"] && @config["workers"] > 1 && @klass.workers_not_supported?
|
47
|
+
end
|
48
|
+
|
49
|
+
def target_worker_count
|
50
|
+
# Remove in 5.0 after all plugins upgraded to use class level declarations
|
51
|
+
raise ArgumentError, "Attempted to detect target worker count before instantiating a worker to test for legacy workers_not_supported!" if @workers.size == 0
|
52
|
+
|
53
|
+
if @threadsafe || @klass.workers_not_supported?
|
54
|
+
1
|
55
|
+
else
|
56
|
+
@config["workers"] || @default_worker_count
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def config_name
|
61
|
+
@klass.config_name
|
62
|
+
end
|
63
|
+
|
64
|
+
def register
|
65
|
+
raise ArgumentError, "Attempted to register #{self} twice!" if @registered
|
66
|
+
@registered = true
|
67
|
+
# We define this as an array regardless of threadsafety
|
68
|
+
# to make reporting simpler, even though a threadsafe plugin will just have
|
69
|
+
# a single instance
|
70
|
+
#
|
71
|
+
# Older plugins invoke the instance method Outputs::Base#workers_not_supported
|
72
|
+
# To detect these we need an instance to be created first :()
|
73
|
+
# TODO: In the next major version after 2.x remove support for this
|
74
|
+
@workers << @klass.new(@config)
|
75
|
+
@workers.first.register # Needed in case register calls `workers_not_supported`
|
76
|
+
|
77
|
+
@logger.debug("Will start workers for output", :worker_count => target_worker_count, :class => @klass)
|
78
|
+
|
79
|
+
# Threadsafe versions don't need additional workers
|
80
|
+
setup_additional_workers!(target_worker_count) unless @threadsafe
|
81
|
+
# We skip the first worker because that's pre-registered to deal with legacy workers_not_supported
|
82
|
+
@workers.subList(1,@workers.size).each(&:register)
|
83
|
+
setup_multi_receive!
|
84
|
+
end
|
85
|
+
|
86
|
+
def setup_additional_workers!(target_worker_count)
|
87
|
+
warn_on_worker_override!
|
88
|
+
|
89
|
+
(target_worker_count - 1).times do
|
90
|
+
inst = @klass.new(@config)
|
91
|
+
@workers << inst
|
92
|
+
end
|
93
|
+
|
94
|
+
# This queue is used to manage sharing across threads
|
95
|
+
@worker_queue = SizedQueue.new(target_worker_count)
|
96
|
+
@workers.each {|w| @worker_queue << w }
|
97
|
+
end
|
98
|
+
|
99
|
+
def setup_multi_receive!
|
100
|
+
# One might wonder why we don't use something like
|
101
|
+
# define_singleton_method(:multi_receive, method(:threadsafe_multi_receive)
|
102
|
+
# and the answer is this is buggy on Jruby 1.7.x . It works 98% of the time!
|
103
|
+
# The other 2% you get weird errors about rebinding to the same object
|
104
|
+
# Until we switch to Jruby 9.x keep the define_singleton_method parts
|
105
|
+
# the way they are, with a block
|
106
|
+
# See https://github.com/jruby/jruby/issues/3582
|
107
|
+
if threadsafe?
|
108
|
+
@threadsafe_worker = @workers.first
|
109
|
+
define_singleton_method(:multi_receive) do |events|
|
110
|
+
threadsafe_multi_receive(events)
|
111
|
+
end
|
112
|
+
else
|
113
|
+
define_singleton_method(:multi_receive) do |events|
|
114
|
+
worker_multi_receive(events)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def threadsafe_multi_receive(events)
|
120
|
+
@events_received.increment(events.length)
|
121
|
+
|
122
|
+
@threadsafe_worker.multi_receive(events)
|
123
|
+
end
|
124
|
+
|
125
|
+
def worker_multi_receive(events)
|
126
|
+
@events_received.increment(events.length)
|
127
|
+
|
128
|
+
worker = @worker_queue.pop
|
129
|
+
begin
|
130
|
+
worker.multi_receive(events)
|
131
|
+
ensure
|
132
|
+
@worker_queue.push(worker)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def do_close
|
137
|
+
@logger.debug("closing output delegator", :klass => @klass)
|
138
|
+
|
139
|
+
if @threadsafe
|
140
|
+
@workers.each(&:do_close)
|
141
|
+
else
|
142
|
+
worker_count.times do
|
143
|
+
worker = @worker_queue.pop
|
144
|
+
worker.do_close
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def events_received
|
150
|
+
@events_received.value
|
151
|
+
end
|
152
|
+
|
153
|
+
# There's no concept of 'busy' workers for a threadsafe plugin!
|
154
|
+
def busy_workers
|
155
|
+
if @threadsafe
|
156
|
+
0
|
157
|
+
else
|
158
|
+
# The pipeline reporter can run before the outputs are registered trying to pull a value here
|
159
|
+
# In that case @worker_queue is empty, we just return 0
|
160
|
+
return 0 unless @worker_queue
|
161
|
+
@workers.size - @worker_queue.size
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def worker_count
|
166
|
+
@workers.size
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
# Needed for testing, so private
|
171
|
+
attr_reader :threadsafe_worker, :worker_queue
|
172
|
+
end end
|