logstash-core 5.6.16-java → 6.0.0.alpha1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/gemspec_jars.rb +4 -7
- data/lib/logstash-core/logstash-core.jar +0 -0
- data/lib/logstash-core/version.rb +4 -8
- data/lib/logstash-core_jars.rb +12 -26
- data/lib/logstash/agent.rb +261 -246
- data/lib/logstash/api/commands/default_metadata.rb +1 -1
- data/lib/logstash/api/commands/hot_threads_reporter.rb +5 -11
- data/lib/logstash/api/commands/node.rb +3 -2
- data/lib/logstash/api/commands/stats.rb +3 -2
- data/lib/logstash/bootstrap_check/bad_java.rb +16 -0
- data/lib/logstash/bootstrap_check/bad_ruby.rb +12 -0
- data/lib/logstash/bootstrap_check/default_config.rb +17 -0
- data/lib/logstash/compiler.rb +38 -0
- data/lib/logstash/compiler/lscl.rb +566 -0
- data/lib/logstash/compiler/lscl/lscl_grammar.rb +3503 -0
- data/lib/logstash/compiler/treetop_monkeypatches.rb +92 -0
- data/lib/logstash/config/config_ast.rb +4 -82
- data/lib/logstash/config/mixin.rb +73 -41
- data/lib/logstash/config/pipeline_config.rb +48 -0
- data/lib/logstash/config/source/base.rb +16 -0
- data/lib/logstash/config/source/local.rb +215 -0
- data/lib/logstash/config/source_loader.rb +125 -0
- data/lib/logstash/converge_result.rb +103 -0
- data/lib/logstash/environment.rb +6 -19
- data/lib/logstash/errors.rb +2 -0
- data/lib/logstash/execution_context.rb +4 -7
- data/lib/logstash/filter_delegator.rb +6 -9
- data/lib/logstash/inputs/base.rb +0 -2
- data/lib/logstash/instrument/collector.rb +5 -7
- data/lib/logstash/instrument/metric_store.rb +12 -12
- data/lib/logstash/instrument/metric_type/mean.rb +0 -5
- data/lib/logstash/instrument/namespaced_metric.rb +0 -4
- data/lib/logstash/instrument/namespaced_null_metric.rb +0 -4
- data/lib/logstash/instrument/null_metric.rb +0 -10
- data/lib/logstash/instrument/periodic_poller/cgroup.rb +85 -168
- data/lib/logstash/instrument/periodic_poller/jvm.rb +5 -5
- data/lib/logstash/instrument/periodic_poller/pq.rb +3 -7
- data/lib/logstash/instrument/periodic_pollers.rb +1 -3
- data/lib/logstash/instrument/wrapped_write_client.rb +24 -33
- data/lib/logstash/logging/logger.rb +15 -47
- data/lib/logstash/namespace.rb +0 -1
- data/lib/logstash/output_delegator.rb +5 -7
- data/lib/logstash/outputs/base.rb +0 -2
- data/lib/logstash/pipeline.rb +159 -87
- data/lib/logstash/pipeline_action.rb +13 -0
- data/lib/logstash/pipeline_action/base.rb +29 -0
- data/lib/logstash/pipeline_action/create.rb +47 -0
- data/lib/logstash/pipeline_action/reload.rb +48 -0
- data/lib/logstash/pipeline_action/stop.rb +23 -0
- data/lib/logstash/plugin.rb +0 -1
- data/lib/logstash/plugins/hooks_registry.rb +6 -0
- data/lib/logstash/plugins/registry.rb +0 -1
- data/lib/logstash/program.rb +14 -0
- data/lib/logstash/queue_factory.rb +5 -1
- data/lib/logstash/runner.rb +58 -80
- data/lib/logstash/settings.rb +3 -27
- data/lib/logstash/state_resolver.rb +41 -0
- data/lib/logstash/util/java_version.rb +6 -0
- data/lib/logstash/util/safe_uri.rb +12 -148
- data/lib/logstash/util/thread_dump.rb +4 -7
- data/lib/logstash/util/wrapped_acked_queue.rb +36 -39
- data/lib/logstash/util/wrapped_synchronous_queue.rb +29 -39
- data/lib/logstash/version.rb +10 -8
- data/locales/en.yml +3 -54
- data/logstash-core.gemspec +8 -35
- data/spec/{logstash/api/modules → api/lib/api}/logging_spec.rb +10 -1
- data/spec/{logstash/api/modules → api/lib/api}/node_plugins_spec.rb +2 -1
- data/spec/{logstash/api/modules → api/lib/api}/node_spec.rb +3 -3
- data/spec/{logstash/api/modules → api/lib/api}/node_stats_spec.rb +3 -7
- data/spec/{logstash/api/modules → api/lib/api}/plugins_spec.rb +3 -4
- data/spec/{logstash/api/modules → api/lib/api}/root_spec.rb +2 -2
- data/spec/api/lib/api/support/resource_dsl_methods.rb +87 -0
- data/spec/{logstash/api/commands/stats_spec.rb → api/lib/commands/stats.rb} +2 -7
- data/spec/{logstash/api → api/lib}/errors_spec.rb +1 -1
- data/spec/{logstash/api → api/lib}/rack_app_spec.rb +0 -0
- data/spec/api/spec_helper.rb +106 -0
- data/spec/logstash/agent/converge_spec.rb +286 -0
- data/spec/logstash/agent/metrics_spec.rb +244 -0
- data/spec/logstash/agent_spec.rb +213 -225
- data/spec/logstash/compiler/compiler_spec.rb +584 -0
- data/spec/logstash/config/config_ast_spec.rb +8 -47
- data/spec/logstash/config/mixin_spec.rb +2 -42
- data/spec/logstash/config/pipeline_config_spec.rb +75 -0
- data/spec/logstash/config/source/local_spec.rb +395 -0
- data/spec/logstash/config/source_loader_spec.rb +122 -0
- data/spec/logstash/converge_result_spec.rb +179 -0
- data/spec/logstash/event_spec.rb +0 -66
- data/spec/logstash/execution_context_spec.rb +8 -12
- data/spec/logstash/filter_delegator_spec.rb +12 -24
- data/spec/logstash/inputs/base_spec.rb +7 -5
- data/spec/logstash/instrument/periodic_poller/cgroup_spec.rb +92 -225
- data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +1 -1
- data/spec/logstash/instrument/periodic_poller/os_spec.rb +32 -29
- data/spec/logstash/instrument/wrapped_write_client_spec.rb +33 -33
- data/spec/logstash/legacy_ruby_event_spec.rb +13 -4
- data/spec/logstash/output_delegator_spec.rb +11 -20
- data/spec/logstash/outputs/base_spec.rb +7 -5
- data/spec/logstash/pipeline_action/create_spec.rb +83 -0
- data/spec/logstash/pipeline_action/reload_spec.rb +83 -0
- data/spec/logstash/pipeline_action/stop_spec.rb +37 -0
- data/spec/logstash/pipeline_pq_file_spec.rb +1 -1
- data/spec/logstash/pipeline_spec.rb +81 -137
- data/spec/logstash/plugin_spec.rb +2 -1
- data/spec/logstash/plugins/hooks_registry_spec.rb +6 -0
- data/spec/logstash/queue_factory_spec.rb +13 -1
- data/spec/logstash/runner_spec.rb +29 -140
- data/spec/logstash/settings/writable_directory_spec.rb +10 -13
- data/spec/logstash/settings_spec.rb +0 -91
- data/spec/logstash/state_resolver_spec.rb +156 -0
- data/spec/logstash/timestamp_spec.rb +2 -6
- data/spec/logstash/util/java_version_spec.rb +22 -0
- data/spec/logstash/util/safe_uri_spec.rb +0 -56
- data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +22 -0
- data/spec/support/helpers.rb +9 -11
- data/spec/support/matchers.rb +96 -6
- data/spec/support/mocks_classes.rb +80 -0
- data/spec/support/shared_contexts.rb +2 -27
- metadata +100 -149
- data/lib/logstash/config/loader.rb +0 -107
- data/lib/logstash/config/modules_common.rb +0 -103
- data/lib/logstash/config/source/modules.rb +0 -55
- data/lib/logstash/config/string_escape.rb +0 -27
- data/lib/logstash/dependency_report.rb +0 -131
- data/lib/logstash/dependency_report_runner.rb +0 -17
- data/lib/logstash/elasticsearch_client.rb +0 -142
- data/lib/logstash/instrument/global_metrics.rb +0 -13
- data/lib/logstash/instrument/periodic_poller/dlq.rb +0 -24
- data/lib/logstash/modules/cli_parser.rb +0 -74
- data/lib/logstash/modules/elasticsearch_config.rb +0 -22
- data/lib/logstash/modules/elasticsearch_importer.rb +0 -37
- data/lib/logstash/modules/elasticsearch_resource.rb +0 -10
- data/lib/logstash/modules/file_reader.rb +0 -36
- data/lib/logstash/modules/kibana_base.rb +0 -24
- data/lib/logstash/modules/kibana_client.rb +0 -124
- data/lib/logstash/modules/kibana_config.rb +0 -105
- data/lib/logstash/modules/kibana_dashboards.rb +0 -36
- data/lib/logstash/modules/kibana_importer.rb +0 -17
- data/lib/logstash/modules/kibana_resource.rb +0 -10
- data/lib/logstash/modules/kibana_settings.rb +0 -40
- data/lib/logstash/modules/logstash_config.rb +0 -120
- data/lib/logstash/modules/resource_base.rb +0 -38
- data/lib/logstash/modules/scaffold.rb +0 -52
- data/lib/logstash/modules/settings_merger.rb +0 -23
- data/lib/logstash/modules/util.rb +0 -17
- data/lib/logstash/util/dead_letter_queue_manager.rb +0 -61
- data/lib/logstash/util/environment_variables.rb +0 -43
- data/spec/logstash/config/loader_spec.rb +0 -38
- data/spec/logstash/config/string_escape_spec.rb +0 -24
- data/spec/logstash/instrument/periodic_poller/dlq_spec.rb +0 -17
- data/spec/logstash/modules/logstash_config_spec.rb +0 -56
- data/spec/logstash/modules/scaffold_spec.rb +0 -234
- data/spec/logstash/pipeline_dlq_commit_spec.rb +0 -109
- data/spec/logstash/settings/splittable_string_array_spec.rb +0 -51
- data/spec/logstash/util/wrapped_acked_queue_spec.rb +0 -49
- data/versions-gem-copy.yml +0 -12
@@ -7,13 +7,10 @@ module LogStash
|
|
7
7
|
java_import org.apache.logging.log4j.LogManager
|
8
8
|
java_import org.apache.logging.log4j.core.config.Configurator
|
9
9
|
java_import org.apache.logging.log4j.core.config.DefaultConfiguration
|
10
|
-
java_import org.apache.logging.log4j.core.config.LoggerConfig
|
11
|
-
java_import org.logstash.log.LogstashLoggerContextFactory
|
12
|
-
java_import org.apache.logging.log4j.core.LoggerContext
|
13
|
-
java_import java.net.URI
|
14
10
|
|
15
11
|
class Logger
|
16
12
|
@@config_mutex = Mutex.new
|
13
|
+
@@logging_context = nil
|
17
14
|
|
18
15
|
def initialize(name)
|
19
16
|
@logger = LogManager.getLogger(name)
|
@@ -68,60 +65,31 @@ module LogStash
|
|
68
65
|
end
|
69
66
|
|
70
67
|
def self.configure_logging(level, path = LogManager::ROOT_LOGGER_NAME)
|
71
|
-
@@config_mutex.synchronize {
|
68
|
+
@@config_mutex.synchronize { Configurator.setLevel(path, Level.valueOf(level)) }
|
72
69
|
rescue Exception => e
|
73
70
|
raise ArgumentError, "invalid level[#{level}] for logger[#{path}]"
|
74
71
|
end
|
75
72
|
|
76
|
-
def self.
|
73
|
+
def self.initialize(config_location)
|
77
74
|
@@config_mutex.synchronize do
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
# fall back to default config
|
90
|
-
puts "Could not find log4j2 configuration at path #{file_path}. Using default config which logs errors to the console"
|
75
|
+
if @@logging_context.nil?
|
76
|
+
file_path = URI(config_location).path
|
77
|
+
if ::File.exists?(file_path)
|
78
|
+
logs_location = java.lang.System.getProperty("ls.logs")
|
79
|
+
puts "Sending Logstash's logs to #{logs_location} which is now configured via log4j2.properties"
|
80
|
+
@@logging_context = Configurator.initialize(nil, config_location)
|
81
|
+
else
|
82
|
+
# fall back to default config
|
83
|
+
puts "Could not find log4j2 configuration at path #{file_path}. Using default config which logs to console"
|
84
|
+
@@logging_context = Configurator.initialize(DefaultConfiguration.new)
|
85
|
+
end
|
91
86
|
end
|
92
87
|
end
|
93
88
|
end
|
94
89
|
|
95
|
-
# until dev_utils/rspec/spec_helper is changed, we need to have both methods
|
96
|
-
singleton_class.send(:alias_method, :initialize, :reconfigure)
|
97
|
-
|
98
90
|
def self.get_logging_context
|
99
|
-
return
|
100
|
-
end
|
101
|
-
|
102
|
-
# Clone of org.apache.logging.log4j.core.config.Configurator.setLevel(), but ensure the proper context is used
|
103
|
-
def self.set_level(_level, path)
|
104
|
-
configuration = get_logging_context.getConfiguration()
|
105
|
-
level = Level.valueOf(_level)
|
106
|
-
if path.nil? || path.strip.empty?
|
107
|
-
root_logger = configuration.getRootLogger()
|
108
|
-
if root_logger.getLevel() != level
|
109
|
-
root_logger.setLevel(level)
|
110
|
-
get_logging_context.updateLoggers()
|
111
|
-
end
|
112
|
-
else
|
113
|
-
package_logger = configuration.getLoggerConfig(path)
|
114
|
-
if package_logger.name != path #no package logger found
|
115
|
-
configuration.addLogger(path, LoggerConfig.new(path, level, true))
|
116
|
-
get_logging_context.updateLoggers()
|
117
|
-
elsif package_logger.getLevel() != level
|
118
|
-
package_logger.setLevel(level)
|
119
|
-
get_logging_context.updateLoggers()
|
120
|
-
end
|
121
|
-
end
|
91
|
+
return @@logging_context
|
122
92
|
end
|
123
|
-
|
124
|
-
private_class_method :set_level
|
125
93
|
end
|
126
94
|
|
127
95
|
class SlowLogger
|
data/lib/logstash/namespace.rb
CHANGED
@@ -19,9 +19,7 @@ module LogStash class OutputDelegator
|
|
19
19
|
@namespaced_metric = metric.namespace(id.to_sym)
|
20
20
|
@namespaced_metric.gauge(:name, config_name)
|
21
21
|
@metric_events = @namespaced_metric.namespace(:events)
|
22
|
-
|
23
|
-
@out_counter = @metric_events.counter(:out)
|
24
|
-
@time_metric = @metric_events.counter(:duration_in_millis)
|
22
|
+
|
25
23
|
@strategy = strategy_registry.
|
26
24
|
class_for(self.concurrency).
|
27
25
|
new(@logger, @output_class, @namespaced_metric, execution_context, plugin_args)
|
@@ -44,11 +42,11 @@ module LogStash class OutputDelegator
|
|
44
42
|
end
|
45
43
|
|
46
44
|
def multi_receive(events)
|
47
|
-
@
|
48
|
-
|
45
|
+
@metric_events.increment(:in, events.length)
|
46
|
+
clock = @metric_events.time(:duration_in_millis)
|
49
47
|
@strategy.multi_receive(events)
|
50
|
-
|
51
|
-
@
|
48
|
+
clock.stop
|
49
|
+
@metric_events.increment(:out, events.length)
|
52
50
|
end
|
53
51
|
|
54
52
|
def do_close
|
@@ -109,8 +109,6 @@ class LogStash::Outputs::Base < LogStash::Plugin
|
|
109
109
|
super
|
110
110
|
# There is no easy way to propage an instance variable into the codec, because the codec
|
111
111
|
# are created at the class level
|
112
|
-
# TODO(talevy): Codecs should have their own execution_context, for now they will inherit their
|
113
|
-
# parent plugin's
|
114
112
|
@codec.execution_context = context
|
115
113
|
context
|
116
114
|
end
|
data/lib/logstash/pipeline.rb
CHANGED
@@ -18,25 +18,26 @@ require "logstash/instrument/null_metric"
|
|
18
18
|
require "logstash/instrument/namespaced_null_metric"
|
19
19
|
require "logstash/instrument/collector"
|
20
20
|
require "logstash/instrument/wrapped_write_client"
|
21
|
-
require "logstash/util/dead_letter_queue_manager"
|
22
21
|
require "logstash/output_delegator"
|
23
22
|
require "logstash/filter_delegator"
|
24
23
|
require "logstash/queue_factory"
|
24
|
+
require "logstash/compiler"
|
25
25
|
require "logstash/execution_context"
|
26
26
|
|
27
|
-
java_import org.logstash.common.DeadLetterQueueFactory
|
28
|
-
java_import org.logstash.common.io.DeadLetterQueueWriter
|
29
|
-
|
30
27
|
module LogStash; class BasePipeline
|
31
28
|
include LogStash::Util::Loggable
|
32
29
|
|
33
|
-
attr_reader :config_str, :config_hash, :inputs, :filters, :outputs, :pipeline_id
|
30
|
+
attr_reader :settings, :config_str, :config_hash, :inputs, :filters, :outputs, :pipeline_id, :lir, :execution_context
|
34
31
|
|
35
|
-
def initialize(config_str, settings = SETTINGS)
|
32
|
+
def initialize(config_str, settings = SETTINGS, namespaced_metric = nil, agent = nil)
|
36
33
|
@logger = self.logger
|
37
|
-
|
34
|
+
|
38
35
|
@config_str = config_str
|
36
|
+
@settings = settings
|
39
37
|
@config_hash = Digest::SHA1.hexdigest(@config_str)
|
38
|
+
|
39
|
+
@lir = compile_lir
|
40
|
+
|
40
41
|
# Every time #plugin is invoked this is incremented to give each plugin
|
41
42
|
# a unique id when auto-generating plugin ids
|
42
43
|
@plugin_counter ||= 0
|
@@ -48,25 +49,18 @@ module LogStash; class BasePipeline
|
|
48
49
|
@inputs = nil
|
49
50
|
@filters = nil
|
50
51
|
@outputs = nil
|
51
|
-
|
52
|
-
if settings.get_value("dead_letter_queue.enable")
|
53
|
-
@dlq_writer = DeadLetterQueueFactory.getWriter(pipeline_id, settings.get_value("path.dead_letter_queue"), settings.get_value("dead_letter_queue.max_bytes"))
|
54
|
-
else
|
55
|
-
@dlq_writer = LogStash::Util::DummyDeadLetterQueueWriter.new
|
56
|
-
end
|
52
|
+
@execution_context = LogStash::ExecutionContext.new(self, agent)
|
57
53
|
|
58
54
|
grammar = LogStashConfigParser.new
|
59
55
|
parsed_config = grammar.parse(config_str)
|
60
56
|
raise(ConfigurationError, grammar.failure_reason) if parsed_config.nil?
|
61
57
|
|
62
|
-
parsed_config.process_escape_sequences = settings.get_value("config.support_escapes")
|
63
|
-
|
64
58
|
config_code = parsed_config.compile
|
65
59
|
|
66
60
|
# config_code = BasePipeline.compileConfig(config_str)
|
67
61
|
|
68
62
|
if settings.get_value("config.debug") && @logger.debug?
|
69
|
-
@logger.debug("Compiled pipeline code", :code => config_code)
|
63
|
+
@logger.debug("Compiled pipeline code", default_logging_keys(:code => config_code))
|
70
64
|
end
|
71
65
|
|
72
66
|
# Evaluate the config compiled code that will initialize all the plugins and define the
|
@@ -78,6 +72,10 @@ module LogStash; class BasePipeline
|
|
78
72
|
end
|
79
73
|
end
|
80
74
|
|
75
|
+
def compile_lir
|
76
|
+
LogStash::Compiler.compile_pipeline(self.config_str)
|
77
|
+
end
|
78
|
+
|
81
79
|
def plugin(plugin_type, name, *args)
|
82
80
|
@plugin_counter += 1
|
83
81
|
|
@@ -102,34 +100,34 @@ module LogStash; class BasePipeline
|
|
102
100
|
|
103
101
|
klass = Plugin.lookup(plugin_type, name)
|
104
102
|
|
105
|
-
execution_context = ExecutionContext.new(self, id, klass.config_name, @dlq_writer)
|
106
|
-
|
107
103
|
if plugin_type == "output"
|
108
|
-
OutputDelegator.new(@logger, klass, type_scoped_metric, execution_context, OutputDelegatorStrategyRegistry.instance, args)
|
104
|
+
OutputDelegator.new(@logger, klass, type_scoped_metric, @execution_context, OutputDelegatorStrategyRegistry.instance, args)
|
109
105
|
elsif plugin_type == "filter"
|
110
|
-
FilterDelegator.new(@logger, klass, type_scoped_metric, execution_context, args)
|
106
|
+
FilterDelegator.new(@logger, klass, type_scoped_metric, @execution_context, args)
|
111
107
|
else # input
|
112
108
|
input_plugin = klass.new(args)
|
113
109
|
scoped_metric = type_scoped_metric.namespace(id.to_sym)
|
114
110
|
scoped_metric.gauge(:name, input_plugin.config_name)
|
115
111
|
input_plugin.metric = scoped_metric
|
116
|
-
input_plugin.execution_context = execution_context
|
112
|
+
input_plugin.execution_context = @execution_context
|
117
113
|
input_plugin
|
118
114
|
end
|
119
115
|
end
|
120
116
|
|
121
117
|
def reloadable?
|
122
|
-
|
118
|
+
configured_as_reloadable? && reloadable_plugins?
|
123
119
|
end
|
124
120
|
|
125
|
-
def
|
126
|
-
(
|
121
|
+
def configured_as_reloadable?
|
122
|
+
settings.get("pipeline.reloadable")
|
127
123
|
end
|
128
124
|
|
129
|
-
|
125
|
+
def reloadable_plugins?
|
126
|
+
non_reloadable_plugins.empty?
|
127
|
+
end
|
130
128
|
|
131
|
-
def
|
132
|
-
{
|
129
|
+
def non_reloadable_plugins
|
130
|
+
(inputs + filters + outputs).select { |plugin| !plugin.reloadable? }
|
133
131
|
end
|
134
132
|
end; end
|
135
133
|
|
@@ -149,7 +147,7 @@ module LogStash; class Pipeline < BasePipeline
|
|
149
147
|
|
150
148
|
MAX_INFLIGHT_WARN_THRESHOLD = 10_000
|
151
149
|
|
152
|
-
def initialize(config_str, settings = SETTINGS, namespaced_metric = nil)
|
150
|
+
def initialize(config_str, settings = SETTINGS, namespaced_metric = nil, agent = nil)
|
153
151
|
# This needs to be configured before we call super which will evaluate the code to make
|
154
152
|
# sure the metric instance is correctly send to the plugins to make the namespace scoping work
|
155
153
|
@metric = if namespaced_metric
|
@@ -162,12 +160,12 @@ module LogStash; class Pipeline < BasePipeline
|
|
162
160
|
@reporter = PipelineReporter.new(@logger, self)
|
163
161
|
@worker_threads = []
|
164
162
|
|
165
|
-
super
|
163
|
+
super
|
166
164
|
|
167
165
|
begin
|
168
166
|
@queue = LogStash::QueueFactory.create(settings)
|
169
167
|
rescue => e
|
170
|
-
@logger.error("Logstash failed to create queue", "exception" => e.message, "backtrace" => e.backtrace)
|
168
|
+
@logger.error("Logstash failed to create queue", default_logging_keys("exception" => e.message, "backtrace" => e.backtrace))
|
171
169
|
raise e
|
172
170
|
end
|
173
171
|
|
@@ -182,7 +180,6 @@ module LogStash; class Pipeline < BasePipeline
|
|
182
180
|
)
|
183
181
|
@drain_queue = @settings.get_value("queue.drain")
|
184
182
|
|
185
|
-
|
186
183
|
@events_filtered = Concurrent::AtomicFixnum.new(0)
|
187
184
|
@events_consumed = Concurrent::AtomicFixnum.new(0)
|
188
185
|
|
@@ -191,8 +188,11 @@ module LogStash; class Pipeline < BasePipeline
|
|
191
188
|
@ready = Concurrent::AtomicBoolean.new(false)
|
192
189
|
@running = Concurrent::AtomicBoolean.new(false)
|
193
190
|
@flushing = Concurrent::AtomicReference.new(false)
|
191
|
+
@force_shutdown = Concurrent::AtomicBoolean.new(false)
|
194
192
|
end # def initialize
|
195
193
|
|
194
|
+
|
195
|
+
|
196
196
|
def ready?
|
197
197
|
@ready.value
|
198
198
|
end
|
@@ -207,15 +207,14 @@ module LogStash; class Pipeline < BasePipeline
|
|
207
207
|
|
208
208
|
if @settings.set?("pipeline.workers")
|
209
209
|
if pipeline_workers > 1
|
210
|
-
@logger.warn("Warning: Manual override - there are filters that might not work with multiple worker threads",
|
211
|
-
:worker_threads => pipeline_workers, :filters => plugins)
|
210
|
+
@logger.warn("Warning: Manual override - there are filters that might not work with multiple worker threads", default_logging_keys(:worker_threads => pipeline_workers, :filters => plugins))
|
212
211
|
end
|
213
212
|
else
|
214
213
|
# user did not specify a worker thread count
|
215
214
|
# warn if the default is multiple
|
216
215
|
if default > 1
|
217
216
|
@logger.warn("Defaulting pipeline worker threads to 1 because there are some filters that might not work with multiple worker threads",
|
218
|
-
:count_was => default, :filters => plugins)
|
217
|
+
default_logging_keys(:count_was => default, :filters => plugins))
|
219
218
|
return 1 # can't allow the default value to propagate if there are unsafe filters
|
220
219
|
end
|
221
220
|
end
|
@@ -226,15 +225,61 @@ module LogStash; class Pipeline < BasePipeline
|
|
226
225
|
return @filters.any?
|
227
226
|
end
|
228
227
|
|
228
|
+
def start
|
229
|
+
# Since we start lets assume that the metric namespace is cleared
|
230
|
+
# this is useful in the context of pipeline reloading
|
231
|
+
collect_stats
|
232
|
+
|
233
|
+
logger.debug("Starting pipeline", default_logging_keys)
|
234
|
+
|
235
|
+
@finished_execution = Concurrent::AtomicBoolean.new(false)
|
236
|
+
|
237
|
+
@thread = Thread.new do
|
238
|
+
begin
|
239
|
+
LogStash::Util.set_thread_name("pipeline.#{pipeline_id}")
|
240
|
+
run
|
241
|
+
@finished_execution.make_true
|
242
|
+
rescue => e
|
243
|
+
close
|
244
|
+
logger.error("Pipeline aborted due to error", default_logging_keys(:exception => e, :backtrace => e.backtrace))
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
status = wait_until_started
|
249
|
+
|
250
|
+
if status
|
251
|
+
logger.debug("Pipeline started successfully", default_logging_keys(:pipeline_id => pipeline_id))
|
252
|
+
end
|
253
|
+
|
254
|
+
status
|
255
|
+
end
|
256
|
+
|
257
|
+
def wait_until_started
|
258
|
+
while true do
|
259
|
+
# This should be changed with an appropriate FSM
|
260
|
+
# It's an edge case, if we have a pipeline with
|
261
|
+
# a generator { count => 1 } its possible that `Thread#alive?` doesn't return true
|
262
|
+
# because the execution of the thread was successful and complete
|
263
|
+
if @finished_execution.true?
|
264
|
+
return true
|
265
|
+
elsif !thread.alive?
|
266
|
+
return false
|
267
|
+
elsif running?
|
268
|
+
return true
|
269
|
+
else
|
270
|
+
sleep 0.01
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
229
275
|
def run
|
230
276
|
@started_at = Time.now
|
231
|
-
|
232
277
|
@thread = Thread.current
|
233
278
|
Util.set_thread_name("[#{pipeline_id}]-pipeline-manager")
|
234
279
|
|
235
280
|
start_workers
|
236
281
|
|
237
|
-
@logger.info("Pipeline
|
282
|
+
@logger.info("Pipeline started", default_logging_keys)
|
238
283
|
|
239
284
|
# Block until all inputs have stopped
|
240
285
|
# Generally this happens if SIGINT is sent and `shutdown` is called from an external thread
|
@@ -244,14 +289,14 @@ module LogStash; class Pipeline < BasePipeline
|
|
244
289
|
wait_inputs
|
245
290
|
transition_to_stopped
|
246
291
|
|
247
|
-
@logger.debug("Input plugins stopped! Will shutdown filter/output workers.")
|
292
|
+
@logger.debug("Input plugins stopped! Will shutdown filter/output workers.", default_logging_keys)
|
248
293
|
|
249
294
|
shutdown_flusher
|
250
295
|
shutdown_workers
|
251
296
|
|
252
297
|
close
|
253
298
|
|
254
|
-
@logger.debug("Pipeline
|
299
|
+
@logger.debug("Pipeline has been shutdown", default_logging_keys)
|
255
300
|
|
256
301
|
# exit code
|
257
302
|
return 0
|
@@ -260,7 +305,6 @@ module LogStash; class Pipeline < BasePipeline
|
|
260
305
|
def close
|
261
306
|
@filter_queue_client.close
|
262
307
|
@queue.close
|
263
|
-
@dlq_writer.close
|
264
308
|
end
|
265
309
|
|
266
310
|
def transition_to_running
|
@@ -290,7 +334,7 @@ module LogStash; class Pipeline < BasePipeline
|
|
290
334
|
plugin.register
|
291
335
|
plugin
|
292
336
|
rescue => e
|
293
|
-
@logger.error("Error registering plugin", :plugin => plugin.inspect, :error => e.message)
|
337
|
+
@logger.error("Error registering plugin", default_logging_keys(:plugin => plugin.inspect, :error => e.message))
|
294
338
|
raise e
|
295
339
|
end
|
296
340
|
|
@@ -322,18 +366,14 @@ module LogStash; class Pipeline < BasePipeline
|
|
322
366
|
config_metric.gauge(:batch_delay, batch_delay)
|
323
367
|
config_metric.gauge(:config_reload_automatic, @settings.get("config.reload.automatic"))
|
324
368
|
config_metric.gauge(:config_reload_interval, @settings.get("config.reload.interval"))
|
325
|
-
config_metric.gauge(:dead_letter_queue_enabled, dlq_enabled?)
|
326
|
-
config_metric.gauge(:dead_letter_queue_path, @dlq_writer.get_path.to_absolute_path.to_s) if dlq_enabled?
|
327
|
-
|
328
369
|
|
329
|
-
@logger.info("Starting pipeline",
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
"pipeline.max_inflight" => max_inflight)
|
370
|
+
@logger.info("Starting pipeline", default_logging_keys(
|
371
|
+
"pipeline.workers" => pipeline_workers,
|
372
|
+
"pipeline.batch.size" => batch_size,
|
373
|
+
"pipeline.batch.delay" => batch_delay,
|
374
|
+
"pipeline.max_inflight" => max_inflight))
|
335
375
|
if max_inflight > MAX_INFLIGHT_WARN_THRESHOLD
|
336
|
-
@logger.warn
|
376
|
+
@logger.warn("CAUTION: Recommended inflight events max exceeded! Logstash will run with up to #{max_inflight} events in memory in your current configuration. If your message sizes are large this may cause instability with the default heap size. Please consider setting a non-standard heap size, changing the batch size (currently #{batch_size}), or changing the number of pipeline workers (currently #{pipeline_workers})", default_logging_keys)
|
337
377
|
end
|
338
378
|
|
339
379
|
pipeline_workers.times do |t|
|
@@ -359,10 +399,6 @@ module LogStash; class Pipeline < BasePipeline
|
|
359
399
|
end
|
360
400
|
end
|
361
401
|
|
362
|
-
def dlq_enabled?
|
363
|
-
@settings.get("dead_letter_queue.enable")
|
364
|
-
end
|
365
|
-
|
366
402
|
# Main body of what a worker thread does
|
367
403
|
# Repeatedly takes batches off the queue, filters, then outputs them
|
368
404
|
def worker_loop(batch_size, batch_delay)
|
@@ -379,6 +415,7 @@ module LogStash; class Pipeline < BasePipeline
|
|
379
415
|
filter_batch(batch)
|
380
416
|
flush_filters_to_batch(batch, :final => false) if signal.flush?
|
381
417
|
output_batch(batch)
|
418
|
+
break if @force_shutdown.true? # Do not ack the current batch
|
382
419
|
@filter_queue_client.close_batch(batch)
|
383
420
|
|
384
421
|
# keep break at end of loop, after the read_batch operation, some pipeline specs rely on this "final read_batch" before shutdown.
|
@@ -390,14 +427,19 @@ module LogStash; class Pipeline < BasePipeline
|
|
390
427
|
batch = @filter_queue_client.new_batch
|
391
428
|
@filter_queue_client.start_metrics(batch) # explicitly call start_metrics since we dont do a read_batch here
|
392
429
|
flush_filters_to_batch(batch, :final => true)
|
430
|
+
return if @force_shutdown.true? # Do not ack the current batch
|
393
431
|
output_batch(batch)
|
394
432
|
@filter_queue_client.close_batch(batch)
|
395
433
|
end
|
396
434
|
|
397
435
|
def filter_batch(batch)
|
398
|
-
|
399
|
-
|
400
|
-
|
436
|
+
batch.each do |event|
|
437
|
+
return if @force_shutdown.true?
|
438
|
+
|
439
|
+
filter_func(event).each do |e|
|
440
|
+
#these are both original and generated events
|
441
|
+
batch.merge(e) unless e.cancelled?
|
442
|
+
end
|
401
443
|
end
|
402
444
|
@filter_queue_client.add_filtered_metrics(batch)
|
403
445
|
@events_filtered.increment(batch.size)
|
@@ -409,7 +451,7 @@ module LogStash; class Pipeline < BasePipeline
|
|
409
451
|
# Users need to check their configuration or see if there is a bug in the
|
410
452
|
# plugin.
|
411
453
|
@logger.error("Exception in pipelineworker, the pipeline stopped processing new events, please check your filter configuration and restart Logstash.",
|
412
|
-
"exception" => e.message, "backtrace" => e.backtrace)
|
454
|
+
default_logging_keys("exception" => e.message, "backtrace" => e.backtrace))
|
413
455
|
|
414
456
|
raise e
|
415
457
|
end
|
@@ -431,6 +473,7 @@ module LogStash; class Pipeline < BasePipeline
|
|
431
473
|
# Now that we have our output to event mapping we can just invoke each output
|
432
474
|
# once with its list of events
|
433
475
|
output_events_map.each do |output, events|
|
476
|
+
return if @force_shutdown.true?
|
434
477
|
output.multi_receive(events)
|
435
478
|
end
|
436
479
|
|
@@ -471,20 +514,21 @@ module LogStash; class Pipeline < BasePipeline
|
|
471
514
|
rescue => e
|
472
515
|
if plugin.stop?
|
473
516
|
@logger.debug("Input plugin raised exception during shutdown, ignoring it.",
|
474
|
-
:plugin => plugin.class.config_name, :exception => e.message,
|
475
|
-
:backtrace => e.backtrace)
|
517
|
+
default_logging_keys(:plugin => plugin.class.config_name, :exception => e.message, :backtrace => e.backtrace))
|
476
518
|
return
|
477
519
|
end
|
478
520
|
|
479
521
|
# otherwise, report error and restart
|
480
522
|
if @logger.debug?
|
481
523
|
@logger.error(I18n.t("logstash.pipeline.worker-error-debug",
|
482
|
-
|
483
|
-
|
484
|
-
|
524
|
+
default_logging_keys(
|
525
|
+
:plugin => plugin.inspect,
|
526
|
+
:error => e.message,
|
527
|
+
:exception => e.class,
|
528
|
+
:stacktrace => e.backtrace.join("\n"))))
|
485
529
|
else
|
486
530
|
@logger.error(I18n.t("logstash.pipeline.worker-error",
|
487
|
-
:plugin => plugin.inspect, :error => e.message))
|
531
|
+
default_logging_keys(:plugin => plugin.inspect, :error => e.message)))
|
488
532
|
end
|
489
533
|
|
490
534
|
# Assuming the failure that caused this exception is transient,
|
@@ -509,23 +553,42 @@ module LogStash; class Pipeline < BasePipeline
|
|
509
553
|
|
510
554
|
before_stop.call if block_given?
|
511
555
|
|
512
|
-
|
513
|
-
|
514
|
-
|
556
|
+
stop_inputs
|
557
|
+
|
558
|
+
# We make this call blocking, so we know for sure when the method return the shtudown is
|
559
|
+
# stopped
|
560
|
+
wait_for_workers
|
561
|
+
clear_pipeline_metrics
|
515
562
|
end # def shutdown
|
516
563
|
|
564
|
+
def force_shutdown!
|
565
|
+
@force_shutdown.make_true
|
566
|
+
end
|
567
|
+
|
568
|
+
def wait_for_workers
|
569
|
+
@logger.debug("Closing inputs", default_logging_keys)
|
570
|
+
@worker_threads.map(&:join)
|
571
|
+
@logger.debug("Worker closed", default_logging_keys)
|
572
|
+
end
|
573
|
+
|
574
|
+
def stop_inputs
|
575
|
+
@logger.debug("Closing inputs", default_logging_keys)
|
576
|
+
@inputs.each(&:do_stop)
|
577
|
+
@logger.debug("Closed inputs", default_logging_keys)
|
578
|
+
end
|
579
|
+
|
517
580
|
# After `shutdown` is called from an external thread this is called from the main thread to
|
518
581
|
# tell the worker threads to stop and then block until they've fully stopped
|
519
582
|
# This also stops all filter and output plugins
|
520
583
|
def shutdown_workers
|
521
584
|
# Each worker thread will receive this exactly once!
|
522
585
|
@worker_threads.each do |t|
|
523
|
-
@logger.debug("Pushing shutdown", :thread => t.inspect)
|
586
|
+
@logger.debug("Pushing shutdown", default_logging_keys(:thread => t.inspect))
|
524
587
|
@signal_queue.push(SHUTDOWN)
|
525
588
|
end
|
526
589
|
|
527
590
|
@worker_threads.each do |t|
|
528
|
-
@logger.debug("Shutdown waiting for worker thread
|
591
|
+
@logger.debug("Shutdown waiting for worker thread" , default_logging_keys(:thread => t.inspect))
|
529
592
|
t.join
|
530
593
|
end
|
531
594
|
|
@@ -537,7 +600,7 @@ module LogStash; class Pipeline < BasePipeline
|
|
537
600
|
# in the pipeline anymore.
|
538
601
|
def filter(event, &block)
|
539
602
|
# filter_func returns all filtered events, including cancelled ones
|
540
|
-
filter_func(
|
603
|
+
filter_func(event).each { |e| block.call(e) }
|
541
604
|
end
|
542
605
|
|
543
606
|
|
@@ -548,6 +611,7 @@ module LogStash; class Pipeline < BasePipeline
|
|
548
611
|
flushers = options[:final] ? @shutdown_flushers : @periodic_flushers
|
549
612
|
|
550
613
|
flushers.each do |flusher|
|
614
|
+
return if @force_shutdown.true?
|
551
615
|
flusher.call(options, &block)
|
552
616
|
end
|
553
617
|
end
|
@@ -570,12 +634,11 @@ module LogStash; class Pipeline < BasePipeline
|
|
570
634
|
|
571
635
|
def flush
|
572
636
|
if @flushing.compare_and_set(false, true)
|
573
|
-
@logger.debug? && @logger.debug("Pushing flush onto pipeline")
|
637
|
+
@logger.debug? && @logger.debug("Pushing flush onto pipeline", default_logging_keys)
|
574
638
|
@signal_queue.push(FLUSH)
|
575
639
|
end
|
576
640
|
end
|
577
641
|
|
578
|
-
|
579
642
|
# Calculate the uptime in milliseconds
|
580
643
|
#
|
581
644
|
# @return [Fixnum] Uptime in milliseconds, 0 if the pipeline is not started
|
@@ -590,8 +653,10 @@ module LogStash; class Pipeline < BasePipeline
|
|
590
653
|
# @param options [Hash]
|
591
654
|
def flush_filters_to_batch(batch, options = {})
|
592
655
|
flush_filters(options) do |event|
|
656
|
+
return if @force_shutdown.true?
|
657
|
+
|
593
658
|
unless event.cancelled?
|
594
|
-
@logger.debug? and @logger.debug("Pushing flushed events", :event => event)
|
659
|
+
@logger.debug? and @logger.debug("Pushing flushed events", default_logging_keys(:event => event))
|
595
660
|
batch.merge(event)
|
596
661
|
end
|
597
662
|
end
|
@@ -613,13 +678,6 @@ module LogStash; class Pipeline < BasePipeline
|
|
613
678
|
.each {|t| t.delete("status") }
|
614
679
|
end
|
615
680
|
|
616
|
-
def collect_dlq_stats
|
617
|
-
if dlq_enabled?
|
618
|
-
dlq_metric = @metric.namespace([:stats, :pipelines, pipeline_id.to_s.to_sym, :dlq])
|
619
|
-
dlq_metric.gauge(:queue_size_in_bytes, @dlq_writer.get_current_queue_size)
|
620
|
-
end
|
621
|
-
end
|
622
|
-
|
623
681
|
def collect_stats
|
624
682
|
pipeline_metric = @metric.namespace([:stats, :pipelines, pipeline_id.to_s.to_sym, :queue])
|
625
683
|
pipeline_metric.gauge(:type, settings.get("queue.type"))
|
@@ -645,6 +703,20 @@ module LogStash; class Pipeline < BasePipeline
|
|
645
703
|
end
|
646
704
|
end
|
647
705
|
|
706
|
+
def clear_pipeline_metrics
|
707
|
+
# TODO(ph): I think the metric should also proxy that call correctly to the collector
|
708
|
+
# this will simplify everything since the null metric would simply just do a noop
|
709
|
+
collector = @metric.collector
|
710
|
+
|
711
|
+
unless collector.nil?
|
712
|
+
# selectively reset metrics we don't wish to keep after reloading
|
713
|
+
# these include metrics about the plugins and number of processed events
|
714
|
+
# we want to keep other metrics like reload counts and error messages
|
715
|
+
collector.clear("stats/pipelines/#{pipeline_id}/plugins")
|
716
|
+
collector.clear("stats/pipelines/#{pipeline_id}/events")
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
648
720
|
# Sometimes we log stuff that will dump the pipeline which may contain
|
649
721
|
# sensitive information (like the raw syntax tree which can contain passwords)
|
650
722
|
# We want to hide most of what's in here
|
@@ -661,9 +733,12 @@ module LogStash; class Pipeline < BasePipeline
|
|
661
733
|
private
|
662
734
|
|
663
735
|
def default_logging_keys(other_keys = {})
|
664
|
-
|
665
|
-
|
666
|
-
|
736
|
+
default_options = if thread
|
737
|
+
{ :pipeline_id => pipeline_id, :thread => thread.inspect }
|
738
|
+
else
|
739
|
+
{ :pipeline_id => pipeline_id }
|
740
|
+
end
|
741
|
+
default_options.merge(other_keys)
|
667
742
|
end
|
668
743
|
|
669
744
|
def draining_queue?
|
@@ -671,9 +746,6 @@ module LogStash; class Pipeline < BasePipeline
|
|
671
746
|
end
|
672
747
|
|
673
748
|
def wrapped_write_client(plugin)
|
674
|
-
|
675
|
-
@mutex.synchronize do
|
676
|
-
LogStash::Instrument::WrappedWriteClient.new(@input_queue_client, self, metric, plugin)
|
677
|
-
end
|
749
|
+
LogStash::Instrument::WrappedWriteClient.new(@input_queue_client, self, metric, plugin)
|
678
750
|
end
|
679
751
|
end; end
|