logstash-core 5.0.2-java → 5.1.1.1-java
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/gemspec_jars.rb +9 -0
- data/lib/logstash-core/logstash-core.jar +0 -0
- data/lib/logstash-core/logstash-core.rb +22 -0
- data/lib/logstash-core/version.rb +1 -1
- data/lib/logstash-core_jars.rb +20 -0
- data/lib/logstash/agent.rb +65 -14
- data/lib/logstash/api/commands/default_metadata.rb +2 -1
- data/lib/logstash/api/commands/stats.rb +3 -2
- data/lib/logstash/config/file.rb +0 -1
- data/lib/logstash/config/loader.rb +1 -0
- data/lib/logstash/config/mixin.rb +2 -6
- data/lib/logstash/environment.rb +25 -2
- data/lib/logstash/event_dispatcher.rb +40 -0
- data/lib/logstash/filter_delegator.rb +1 -1
- data/lib/logstash/filters/base.rb +10 -2
- data/lib/logstash/instrument/metric_store.rb +0 -1
- data/lib/logstash/instrument/metric_type/base.rb +0 -1
- data/lib/logstash/instrument/namespaced_null_metric.rb +54 -0
- data/lib/logstash/instrument/null_metric.rb +55 -46
- data/lib/logstash/instrument/periodic_poller/jvm.rb +26 -3
- data/lib/logstash/instrument/periodic_poller/load_average.rb +47 -0
- data/lib/logstash/instrument/snapshot.rb +0 -1
- data/lib/logstash/java_integration.rb +0 -1
- data/lib/logstash/logging/logger.rb +37 -4
- data/lib/logstash/outputs/base.rb +1 -1
- data/lib/logstash/patches.rb +1 -0
- data/lib/logstash/patches/exception_to_json.rb +5 -0
- data/lib/logstash/pipeline.rb +50 -17
- data/lib/logstash/plugin.rb +14 -48
- data/lib/logstash/plugins/hooks_registry.rb +57 -0
- data/lib/logstash/plugins/registry.rb +208 -45
- data/lib/logstash/runner.rb +10 -5
- data/lib/logstash/settings.rb +101 -9
- data/lib/logstash/universal_plugin.rb +13 -0
- data/lib/logstash/util/byte_value.rb +60 -0
- data/lib/logstash/util/loggable.rb +14 -2
- data/lib/logstash/util/safe_uri.rb +1 -0
- data/lib/logstash/util/time_value.rb +70 -0
- data/lib/logstash/util/wrapped_acked_queue.rb +347 -0
- data/lib/logstash/util/wrapped_synchronous_queue.rb +17 -33
- data/lib/logstash/version.rb +1 -1
- data/locales/en.yml +1 -1
- data/logstash-core.gemspec +13 -18
- data/spec/api/lib/api/node_stats_spec.rb +3 -1
- data/spec/api/lib/api/support/resource_dsl_methods.rb +14 -6
- data/spec/api/spec_helper.rb +1 -0
- data/spec/conditionals_spec.rb +3 -2
- data/spec/logstash/agent_spec.rb +142 -62
- data/spec/logstash/environment_spec.rb +38 -0
- data/spec/logstash/event_dispatcher_spec.rb +76 -0
- data/spec/logstash/filter_delegator_spec.rb +2 -1
- data/spec/logstash/instrument/namespaced_null_metric_spec.rb +33 -0
- data/spec/logstash/instrument/null_metric_spec.rb +9 -5
- data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +40 -0
- data/spec/logstash/instrument/periodic_poller/load_average_spec.rb +91 -0
- data/spec/logstash/output_delegator_spec.rb +2 -1
- data/spec/logstash/patches_spec.rb +15 -4
- data/spec/logstash/pipeline_pq_file_spec.rb +131 -0
- data/spec/logstash/pipeline_spec.rb +21 -17
- data/spec/logstash/plugin_spec.rb +4 -16
- data/spec/logstash/plugins/hooks_registry_spec.rb +60 -0
- data/spec/logstash/plugins/registry_spec.rb +22 -14
- data/spec/logstash/settings/bytes_spec.rb +53 -0
- data/spec/logstash/settings/time_value_spec.rb +31 -0
- data/spec/logstash/settings/writable_directory_spec.rb +125 -0
- data/spec/logstash/settings_spec.rb +39 -0
- data/spec/logstash/util/byte_value_spec.rb +33 -0
- data/spec/logstash/util/time_value_spec.rb +59 -0
- data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +2 -2
- data/spec/logstash/webserver_spec.rb +4 -7
- data/spec/support/helpers.rb +8 -0
- data/spec/support/mocks_classes.rb +61 -31
- metadata +73 -20
- data/lib/jars.rb +0 -7
- data/lib/logstash/config/registry.rb +0 -13
- data/lib/logstash/inputs/metrics.rb +0 -47
- data/spec/logstash/inputs/metrics_spec.rb +0 -51
- data/vendor/jars/com/fasterxml/jackson/core/jackson-core/2.7.4/jackson-core-2.7.4.jar +0 -0
- data/vendor/jars/com/fasterxml/jackson/core/jackson-databind/2.7.4/jackson-databind-2.7.4.jar +0 -0
- data/vendor/jars/org/apache/logging/log4j/log4j-1.2-api/2.6.2/log4j-1.2-api-2.6.2.jar +0 -0
- data/vendor/jars/org/apache/logging/log4j/log4j-api/2.6.2/log4j-api-2.6.2.jar +0 -0
- data/vendor/jars/org/apache/logging/log4j/log4j-core/2.6.2/log4j-core-2.6.2.jar +0 -0
- data/vendor/jars/org/logstash/logstash-core/5.0.2/logstash-core-5.0.2.jar +0 -0
data/lib/logstash/plugin.rb
CHANGED
|
@@ -5,7 +5,6 @@ require "logstash/config/mixin"
|
|
|
5
5
|
require "logstash/instrument/null_metric"
|
|
6
6
|
require "concurrent"
|
|
7
7
|
require "securerandom"
|
|
8
|
-
require "logstash/plugins/registry"
|
|
9
8
|
|
|
10
9
|
class LogStash::Plugin
|
|
11
10
|
include LogStash::Util::Loggable
|
|
@@ -39,13 +38,18 @@ class LogStash::Plugin
|
|
|
39
38
|
self.class.name.hash
|
|
40
39
|
end
|
|
41
40
|
|
|
42
|
-
|
|
43
41
|
def eql?(other)
|
|
44
42
|
self.class.name == other.class.name && @params == other.params
|
|
45
43
|
end
|
|
46
44
|
|
|
47
45
|
def initialize(params=nil)
|
|
48
46
|
@logger = self.logger
|
|
47
|
+
# need to access settings statically because plugins are initialized in config_ast with no context.
|
|
48
|
+
settings = LogStash::SETTINGS
|
|
49
|
+
@slow_logger = self.slow_logger(settings.get("slowlog.threshold.warn"),
|
|
50
|
+
settings.get("slowlog.threshold.info"),
|
|
51
|
+
settings.get("slowlog.threshold.debug"),
|
|
52
|
+
settings.get("slowlog.threshold.trace"))
|
|
49
53
|
@params = LogStash::Util.deep_clone(params)
|
|
50
54
|
# The id should always be defined normally, but in tests that might not be the case
|
|
51
55
|
# In the future we may make this more strict in the Plugin API
|
|
@@ -103,9 +107,9 @@ class LogStash::Plugin
|
|
|
103
107
|
# we will use the NullMetric in this case.
|
|
104
108
|
@metric_plugin ||= if @enable_metric
|
|
105
109
|
# Fallback when testing plugin and no metric collector are correctly configured.
|
|
106
|
-
@metric.nil? ? LogStash::Instrument::
|
|
110
|
+
@metric.nil? ? LogStash::Instrument::NamespacedNullMetric.new : @metric
|
|
107
111
|
else
|
|
108
|
-
LogStash::Instrument::
|
|
112
|
+
LogStash::Instrument::NamespacedNullMetric.new(@metric, :null)
|
|
109
113
|
end
|
|
110
114
|
end
|
|
111
115
|
# return the configured name of this plugin
|
|
@@ -114,50 +118,12 @@ class LogStash::Plugin
|
|
|
114
118
|
self.class.config_name
|
|
115
119
|
end
|
|
116
120
|
|
|
117
|
-
|
|
118
|
-
#
|
|
121
|
+
# This is keep for backward compatibility, the logic was moved into the registry class
|
|
122
|
+
# but some plugins use this method to return a specific instance on lookup
|
|
123
|
+
#
|
|
124
|
+
# Should I remove this now and make sure the pipeline invoke the Registry or I should wait for 6.0
|
|
125
|
+
# Its not really part of the public api but its used by the tests a lot to mock the plugins.
|
|
119
126
|
def self.lookup(type, name)
|
|
120
|
-
|
|
121
|
-
LogStash::Registry.instance.lookup(type ,name) do |plugin_klass, plugin_name|
|
|
122
|
-
is_a_plugin?(plugin_klass, plugin_name)
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
rescue LoadError, NameError => e
|
|
126
|
-
logger.debug("Problems loading the plugin with", :type => type, :name => name, :path => path)
|
|
127
|
-
raise(LogStash::PluginLoadingError, I18n.t("logstash.pipeline.plugin-loading-error", :type => type, :name => name, :path => path, :error => e.to_s))
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
public
|
|
131
|
-
def self.declare_plugin(type, name)
|
|
132
|
-
path = "logstash/#{type}s/#{name}"
|
|
133
|
-
registry = LogStash::Registry.instance
|
|
134
|
-
registry.register(path, self)
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
private
|
|
138
|
-
# lookup a plugin by type and name in the existing LogStash module namespace
|
|
139
|
-
# ex.: namespace_lookup("filter", "grok") looks for LogStash::Filters::Grok
|
|
140
|
-
# @param type [String] plugin type, "input", "ouput", "filter"
|
|
141
|
-
# @param name [String] plugin name, ex.: "grok"
|
|
142
|
-
# @return [Class] the plugin class or raises NameError
|
|
143
|
-
# @raise NameError if plugin class does not exist or is invalid
|
|
144
|
-
def self.namespace_lookup(type, name)
|
|
145
|
-
type_const = "#{type.capitalize}s"
|
|
146
|
-
namespace = LogStash.const_get(type_const)
|
|
147
|
-
# the namespace can contain constants which are not for plugins classes (do not respond to :config_name)
|
|
148
|
-
# namespace.constants is the shallow collection of all constants symbols in namespace
|
|
149
|
-
# note that below namespace.const_get(c) should never result in a NameError since c is from the constants collection
|
|
150
|
-
klass_sym = namespace.constants.find { |c| is_a_plugin?(namespace.const_get(c), name) }
|
|
151
|
-
klass = klass_sym && namespace.const_get(klass_sym)
|
|
152
|
-
raise(NameError) unless klass
|
|
153
|
-
klass
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
# check if klass is a valid plugin for name
|
|
157
|
-
# @param klass [Class] plugin class
|
|
158
|
-
# @param name [String] plugin name
|
|
159
|
-
# @return [Boolean] true if klass is a valid plugin for name
|
|
160
|
-
def self.is_a_plugin?(klass, name)
|
|
161
|
-
klass.ancestors.include?(LogStash::Plugin) && klass.respond_to?(:config_name) && klass.config_name == name
|
|
127
|
+
LogStash::PLUGIN_REGISTRY.lookup_pipeline_plugin(type, name)
|
|
162
128
|
end
|
|
163
129
|
end # class LogStash::Plugin
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module LogStash module Plugins
|
|
3
|
+
# This calls allow logstash to expose the endpoints for listeners
|
|
4
|
+
class HooksRegistry
|
|
5
|
+
java_import "java.util.concurrent.ConcurrentHashMap"
|
|
6
|
+
java_import "java.util.concurrent.CopyOnWriteArrayList"
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@registered_emmitters = ConcurrentHashMap.new
|
|
10
|
+
@registered_hooks = ConcurrentHashMap.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def register_emitter(emitter_scope, dispatcher)
|
|
14
|
+
@registered_emmitters.put(emitter_scope, dispatcher)
|
|
15
|
+
sync_hooks
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def remove_emitter(emitter_scope)
|
|
19
|
+
@registered_emmitters.remove(emitter_scope)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def register_hooks(emitter_scope, callback)
|
|
23
|
+
callbacks = @registered_hooks.computeIfAbsent(emitter_scope) do
|
|
24
|
+
CopyOnWriteArrayList.new
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
callbacks.add(callback)
|
|
28
|
+
sync_hooks
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def emmitters_count
|
|
32
|
+
@registered_emmitters.size
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def hooks_count(emitter_scope = nil)
|
|
36
|
+
if emitter_scope.nil?
|
|
37
|
+
@registered_hooks.elements().collect(&:size).reduce(0, :+)
|
|
38
|
+
else
|
|
39
|
+
callbacks = @registered_hooks.get(emitter_scope)
|
|
40
|
+
callbacks.nil? ? 0 : @registered_hooks.get(emitter_scope).size
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
def sync_hooks
|
|
46
|
+
@registered_emmitters.each do |emitter, dispatcher|
|
|
47
|
+
listeners = @registered_hooks.get(emitter)
|
|
48
|
+
|
|
49
|
+
unless listeners.nil?
|
|
50
|
+
listeners.each do |listener|
|
|
51
|
+
dispatcher.add_listener(listener)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end end
|
|
@@ -1,85 +1,248 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
-
require 'singleton'
|
|
3
2
|
require "rubygems/package"
|
|
4
3
|
require "logstash/util/loggable"
|
|
4
|
+
require "logstash/plugin"
|
|
5
|
+
require "logstash/plugins/hooks_registry"
|
|
5
6
|
|
|
6
|
-
module LogStash
|
|
7
|
+
module LogStash module Plugins
|
|
7
8
|
class Registry
|
|
8
9
|
include LogStash::Util::Loggable
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
class
|
|
14
|
-
|
|
11
|
+
# Add a bit more sanity with when interacting with the rubygems'
|
|
12
|
+
# specifications database, most of out code interact directly with really low level
|
|
13
|
+
# components of bundler/rubygems we need to encapsulate that and this is a start.
|
|
14
|
+
class GemRegistry
|
|
15
|
+
LOGSTASH_METADATA_KEY = "logstash_plugin"
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
class << self
|
|
18
|
+
def installed_gems
|
|
19
|
+
::Gem::Specification
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def logstash_plugins
|
|
23
|
+
installed_gems
|
|
24
|
+
.select { |spec| spec.metadata && spec.metadata[LOGSTASH_METADATA_KEY] }
|
|
25
|
+
.collect { |spec| PluginRawContext.new(spec) }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class PluginRawContext
|
|
31
|
+
HOOK_FILE = "logstash_registry.rb"
|
|
32
|
+
NAME_DELIMITER = "-"
|
|
33
|
+
|
|
34
|
+
attr_reader :spec
|
|
35
|
+
|
|
36
|
+
def initialize(spec)
|
|
37
|
+
@spec = spec
|
|
38
|
+
@destructured_name = spec.name.split(NAME_DELIMITER)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def name
|
|
42
|
+
@destructured_name[2..-1].join(NAME_DELIMITER)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def type
|
|
46
|
+
@destructured_name[1]
|
|
19
47
|
end
|
|
20
48
|
|
|
21
|
-
|
|
22
|
-
|
|
49
|
+
# In the context of the plugin, the hook file available need to exist in any top level
|
|
50
|
+
# required paths.
|
|
51
|
+
#
|
|
52
|
+
# Example for the logstash-output-elasticsearch we have this line in the gemspec.
|
|
53
|
+
#
|
|
54
|
+
# s.require_paths = ["lib"], so the we will expect to have a `logstash_registry.rb` file in the `lib`
|
|
55
|
+
# directory.
|
|
56
|
+
def hooks_file
|
|
57
|
+
@hook_file ||= spec.full_require_paths.collect do |path|
|
|
58
|
+
f = ::File.join(path, HOOK_FILE)
|
|
59
|
+
::File.exist?(f) ? f : nil
|
|
60
|
+
end.compact.first
|
|
23
61
|
end
|
|
24
62
|
|
|
25
|
-
def
|
|
26
|
-
|
|
63
|
+
def has_hooks?
|
|
64
|
+
!hooks_file.nil?
|
|
27
65
|
end
|
|
28
66
|
|
|
29
|
-
def
|
|
30
|
-
|
|
67
|
+
def execute_hooks!
|
|
68
|
+
require hooks_file
|
|
31
69
|
end
|
|
70
|
+
end
|
|
32
71
|
|
|
33
|
-
|
|
72
|
+
class PluginSpecification
|
|
73
|
+
attr_reader :type, :name, :klass
|
|
34
74
|
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
75
|
+
def initialize(type, name, klass)
|
|
76
|
+
@type = type.to_sym
|
|
77
|
+
@name = name
|
|
78
|
+
@klass = klass
|
|
38
79
|
end
|
|
80
|
+
end
|
|
39
81
|
|
|
40
|
-
|
|
41
|
-
|
|
82
|
+
class UniversalPluginSpecification < PluginSpecification
|
|
83
|
+
def initialize(type, name, klass)
|
|
84
|
+
super(type, name, klass)
|
|
85
|
+
@instance = klass.new
|
|
42
86
|
end
|
|
43
87
|
|
|
88
|
+
def register(hooks, settings)
|
|
89
|
+
@instance.register_hooks(hooks)
|
|
90
|
+
@instance.additionals_settings(settings)
|
|
91
|
+
end
|
|
44
92
|
end
|
|
45
93
|
|
|
46
|
-
|
|
94
|
+
attr_reader :hooks
|
|
47
95
|
|
|
48
96
|
def initialize
|
|
49
97
|
@registry = {}
|
|
50
|
-
@
|
|
98
|
+
@hooks = HooksRegistry.new
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def setup!
|
|
102
|
+
load_available_plugins
|
|
103
|
+
execute_universal_plugins
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def execute_universal_plugins
|
|
107
|
+
@registry.values
|
|
108
|
+
.select { |specification| specification.is_a?(UniversalPluginSpecification) }
|
|
109
|
+
.each { |specification| specification.register(hooks, LogStash::SETTINGS) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def load_available_plugins
|
|
113
|
+
GemRegistry.logstash_plugins.each do |plugin_context|
|
|
114
|
+
# When a plugin has a HOOK_FILE defined, its the responsability of the plugin
|
|
115
|
+
# to register itself to the registry of available plugins.
|
|
116
|
+
#
|
|
117
|
+
# Legacy plugin will lazy register themselves
|
|
118
|
+
if plugin_context.has_hooks?
|
|
119
|
+
begin
|
|
120
|
+
logger.debug("Executing hooks", :name => plugin_context.name, :type => plugin_context.type, :hooks_file => plugin_context.hooks_file)
|
|
121
|
+
plugin_context.execute_hooks!
|
|
122
|
+
rescue => e
|
|
123
|
+
logger.error("error occured when loading plugins hooks file", :name => plugin_context.name, :type => plugin_context.type, :exception => e.message, :stacktrace => e.backtrace )
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
51
127
|
end
|
|
52
128
|
|
|
53
129
|
def lookup(type, plugin_name, &block)
|
|
130
|
+
plugin = get(type, plugin_name)
|
|
131
|
+
# Assume that we have a legacy plugin
|
|
132
|
+
if plugin.nil?
|
|
133
|
+
plugin = legacy_lookup(type, plugin_name)
|
|
134
|
+
end
|
|
54
135
|
|
|
55
|
-
|
|
136
|
+
if block_given? # if provided pass a block to do validation
|
|
137
|
+
raise LoadError, "Block validation fails for plugin named #{plugin_name} of type #{type}," unless block.call(plugin.klass, plugin_name)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
return plugin.klass
|
|
141
|
+
end
|
|
56
142
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
143
|
+
# The legacy_lookup method uses the 1.5->5.0 file structure to find and match
|
|
144
|
+
# a plugin and will do a lookup on the namespace of the required class to find a matching
|
|
145
|
+
# plugin with the appropriate type.
|
|
146
|
+
def legacy_lookup(type, plugin_name)
|
|
147
|
+
begin
|
|
148
|
+
path = "logstash/#{type}s/#{plugin_name}"
|
|
149
|
+
|
|
150
|
+
begin
|
|
151
|
+
require path
|
|
152
|
+
rescue LoadError
|
|
153
|
+
# Plugin might be already defined in the current scope
|
|
154
|
+
# This scenario often happen in test when we write an adhoc class
|
|
63
155
|
end
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
156
|
+
|
|
157
|
+
klass = namespace_lookup(type, plugin_name)
|
|
158
|
+
plugin = lazy_add(type, plugin_name, klass)
|
|
159
|
+
rescue => e
|
|
160
|
+
logger.error("Problems loading a plugin with",
|
|
161
|
+
:type => type,
|
|
162
|
+
:name => plugin_name,
|
|
163
|
+
:path => path,
|
|
164
|
+
:error_message => e.message,
|
|
165
|
+
:error_class => e.class,
|
|
166
|
+
:error_backtrace => e.backtrace)
|
|
167
|
+
|
|
168
|
+
raise LoadError, "Problems loading the requested plugin named #{plugin_name} of type #{type}. Error: #{e.class} #{e.message}"
|
|
70
169
|
end
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
170
|
+
|
|
171
|
+
plugin
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def lookup_pipeline_plugin(type, name)
|
|
175
|
+
LogStash::PLUGIN_REGISTRY.lookup(type, name) do |plugin_klass, plugin_name|
|
|
176
|
+
is_a_plugin?(plugin_klass, plugin_name)
|
|
177
|
+
end
|
|
178
|
+
rescue LoadError, NameError => e
|
|
179
|
+
logger.debug("Problems loading the plugin with", :type => type, :name => name)
|
|
180
|
+
raise(LogStash::PluginLoadingError, I18n.t("logstash.pipeline.plugin-loading-error", :type => type, :name => name, :error => e.to_s))
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def lazy_add(type, name, klass)
|
|
184
|
+
logger.debug("On demand adding plugin to the registry", :name => name, :type => type, :class => klass)
|
|
185
|
+
add_plugin(type, name, klass)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def add(type, name, klass)
|
|
189
|
+
logger.debug("Adding plugin to the registry", :name => name, :type => type, :class => klass)
|
|
190
|
+
add_plugin(type, name, klass)
|
|
74
191
|
end
|
|
75
192
|
|
|
76
|
-
def
|
|
77
|
-
@registry[
|
|
193
|
+
def get(type, plugin_name)
|
|
194
|
+
@registry[key_for(type, plugin_name)]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def exists?(type, name)
|
|
198
|
+
@registry.include?(key_for(type, name))
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def size
|
|
202
|
+
@registry.size
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
private
|
|
206
|
+
# lookup a plugin by type and name in the existing LogStash module namespace
|
|
207
|
+
# ex.: namespace_lookup("filter", "grok") looks for LogStash::Filters::Grok
|
|
208
|
+
# @param type [String] plugin type, "input", "ouput", "filter"
|
|
209
|
+
# @param name [String] plugin name, ex.: "grok"
|
|
210
|
+
# @return [Class] the plugin class or raises NameError
|
|
211
|
+
# @raise NameError if plugin class does not exist or is invalid
|
|
212
|
+
def namespace_lookup(type, name)
|
|
213
|
+
type_const = "#{type.capitalize}s"
|
|
214
|
+
namespace = LogStash.const_get(type_const)
|
|
215
|
+
# the namespace can contain constants which are not for plugins classes (do not respond to :config_name)
|
|
216
|
+
# namespace.constants is the shallow collection of all constants symbols in namespace
|
|
217
|
+
# note that below namespace.const_get(c) should never result in a NameError since c is from the constants collection
|
|
218
|
+
klass_sym = namespace.constants.find { |c| is_a_plugin?(namespace.const_get(c), name) }
|
|
219
|
+
klass = klass_sym && namespace.const_get(klass_sym)
|
|
220
|
+
|
|
221
|
+
raise(NameError) unless klass
|
|
222
|
+
klass
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# check if klass is a valid plugin for name
|
|
226
|
+
# @param klass [Class] plugin class
|
|
227
|
+
# @param name [String] plugin name
|
|
228
|
+
# @return [Boolean] true if klass is a valid plugin for name
|
|
229
|
+
def is_a_plugin?(klass, name)
|
|
230
|
+
klass.ancestors.include?(LogStash::Plugin) && klass.respond_to?(:config_name) && klass.config_name == name
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def add_plugin(type, name, klass)
|
|
234
|
+
if !exists?(type, name)
|
|
235
|
+
specification_klass = type == :universal ? UniversalPluginSpecification : PluginSpecification
|
|
236
|
+
@registry[key_for(type, name)] = specification_klass.new(type, name, klass)
|
|
237
|
+
else
|
|
238
|
+
logger.debug("Ignoring, plugin already added to the registry", :name => name, :type => type, :klass => klass)
|
|
239
|
+
end
|
|
78
240
|
end
|
|
79
241
|
|
|
80
|
-
def
|
|
81
|
-
|
|
242
|
+
def key_for(type, plugin_name)
|
|
243
|
+
"#{type}-#{plugin_name}"
|
|
82
244
|
end
|
|
245
|
+
end end
|
|
83
246
|
|
|
84
|
-
|
|
247
|
+
PLUGIN_REGISTRY = Plugins::Registry.new
|
|
85
248
|
end
|
data/lib/logstash/runner.rb
CHANGED
|
@@ -5,17 +5,20 @@ $DEBUGLIST = (ENV["DEBUG"] || "").split(",")
|
|
|
5
5
|
|
|
6
6
|
require "clamp"
|
|
7
7
|
require "net/http"
|
|
8
|
+
|
|
9
|
+
require "logstash/namespace"
|
|
10
|
+
require "logstash-core/logstash-core"
|
|
8
11
|
require "logstash/environment"
|
|
9
12
|
|
|
10
13
|
LogStash::Environment.load_locale!
|
|
11
14
|
|
|
12
|
-
require "logstash/namespace"
|
|
13
15
|
require "logstash/agent"
|
|
14
16
|
require "logstash/config/defaults"
|
|
15
17
|
require "logstash/shutdown_watcher"
|
|
16
18
|
require "logstash/patches/clamp"
|
|
17
19
|
require "logstash/settings"
|
|
18
20
|
require "logstash/version"
|
|
21
|
+
require "logstash/plugins/registry"
|
|
19
22
|
|
|
20
23
|
class LogStash::Runner < Clamp::StrictCommand
|
|
21
24
|
include LogStash::Util::Loggable
|
|
@@ -28,7 +31,7 @@ class LogStash::Runner < Clamp::StrictCommand
|
|
|
28
31
|
|
|
29
32
|
# Node Settings
|
|
30
33
|
option ["-n", "--node.name"], "NAME",
|
|
31
|
-
I18n.t("logstash.runner.flag.
|
|
34
|
+
I18n.t("logstash.runner.flag.name"),
|
|
32
35
|
:attribute_name => "node.name",
|
|
33
36
|
:default => LogStash::SETTINGS.get_default("node.name")
|
|
34
37
|
|
|
@@ -196,6 +199,11 @@ class LogStash::Runner < Clamp::StrictCommand
|
|
|
196
199
|
logger.warn("--config.debug was specified, but log.level was not set to \'debug\'! No config info will be logged.")
|
|
197
200
|
end
|
|
198
201
|
|
|
202
|
+
# We configure the registry and load any plugin that can register hooks
|
|
203
|
+
# with logstash, this need to be done before any operation.
|
|
204
|
+
LogStash::PLUGIN_REGISTRY.setup!
|
|
205
|
+
@settings.validate_all
|
|
206
|
+
|
|
199
207
|
LogStash::Util::set_thread_name(self.class.name)
|
|
200
208
|
|
|
201
209
|
if RUBY_VERSION < "1.9.2"
|
|
@@ -221,8 +229,6 @@ class LogStash::Runner < Clamp::StrictCommand
|
|
|
221
229
|
|
|
222
230
|
return start_shell(setting("interactive"), binding) if setting("interactive")
|
|
223
231
|
|
|
224
|
-
@settings.validate_all
|
|
225
|
-
|
|
226
232
|
@settings.format_settings.each {|line| logger.debug(line) }
|
|
227
233
|
|
|
228
234
|
if setting("config.string").nil? && setting("path.config").nil?
|
|
@@ -335,7 +341,6 @@ class LogStash::Runner < Clamp::StrictCommand
|
|
|
335
341
|
LogStash::Agent.new(*args)
|
|
336
342
|
end
|
|
337
343
|
|
|
338
|
-
|
|
339
344
|
# Emit a failure message and abort.
|
|
340
345
|
def fail(message)
|
|
341
346
|
signal_usage_error(message)
|