logstash-core 2.2.4.snapshot2-java → 2.3.0-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.
Potentially problematic release.
This version of logstash-core might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/logstash-core/version.rb +1 -1
- data/lib/logstash/agent.rb +248 -140
- data/lib/logstash/config/defaults.rb +8 -0
- data/lib/logstash/config/loader.rb +90 -0
- data/lib/logstash/config/mixin.rb +44 -15
- data/lib/logstash/output_delegator.rb +1 -1
- data/lib/logstash/pipeline.rb +29 -28
- data/lib/logstash/runner.rb +5 -0
- data/lib/logstash/shutdown_watcher.rb +3 -2
- data/lib/logstash/special_agent.rb +8 -0
- data/lib/logstash/version.rb +1 -1
- data/locales/en.yml +16 -6
- data/logstash-core.gemspec +2 -2
- data/spec/logstash/agent_spec.rb +278 -34
- data/spec/logstash/config/loader_spec.rb +36 -0
- data/spec/logstash/config/mixin_spec.rb +76 -4
- data/spec/logstash/json_spec.rb +15 -0
- data/spec/logstash/pipeline_spec.rb +2 -2
- data/spec/logstash/plugin_spec.rb +1 -1
- data/spec/logstash/runner_spec.rb +13 -22
- data/spec/logstash/shutdown_watcher_spec.rb +4 -0
- metadata +36 -32
@@ -0,0 +1,90 @@
|
|
1
|
+
require "logstash/config/defaults"
|
2
|
+
|
3
|
+
module LogStash; module Config; class Loader
|
4
|
+
def initialize(logger)
|
5
|
+
@logger = logger
|
6
|
+
end
|
7
|
+
|
8
|
+
def format_config(config_path, config_string)
|
9
|
+
config_string = config_string.to_s
|
10
|
+
if config_path
|
11
|
+
# Append the config string.
|
12
|
+
# This allows users to provide both -f and -e flags. The combination
|
13
|
+
# is rare, but useful for debugging.
|
14
|
+
config_string = config_string + load_config(config_path)
|
15
|
+
else
|
16
|
+
# include a default stdin input if no inputs given
|
17
|
+
if config_string !~ /input *{/
|
18
|
+
config_string += LogStash::Config::Defaults.input
|
19
|
+
end
|
20
|
+
# include a default stdout output if no outputs given
|
21
|
+
if config_string !~ /output *{/
|
22
|
+
config_string += LogStash::Config::Defaults.output
|
23
|
+
end
|
24
|
+
end
|
25
|
+
config_string
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_config(path)
|
29
|
+
begin
|
30
|
+
uri = URI.parse(path)
|
31
|
+
|
32
|
+
case uri.scheme
|
33
|
+
when nil then
|
34
|
+
local_config(path)
|
35
|
+
when /http/ then
|
36
|
+
fetch_config(uri)
|
37
|
+
when "file" then
|
38
|
+
local_config(uri.path)
|
39
|
+
else
|
40
|
+
fail(I18n.t("logstash.runner.configuration.scheme-not-supported", :path => path))
|
41
|
+
end
|
42
|
+
rescue URI::InvalidURIError
|
43
|
+
# fallback for windows.
|
44
|
+
# if the parsing of the file failed we assume we can reach it locally.
|
45
|
+
# some relative path on windows arent parsed correctly (.\logstash.conf)
|
46
|
+
local_config(path)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def local_config(path)
|
51
|
+
path = ::File.expand_path(path)
|
52
|
+
path = ::File.join(path, "*") if ::File.directory?(path)
|
53
|
+
|
54
|
+
if Dir.glob(path).length == 0
|
55
|
+
fail(I18n.t("logstash.runner.configuration.file-not-found", :path => path))
|
56
|
+
end
|
57
|
+
|
58
|
+
config = ""
|
59
|
+
encoding_issue_files = []
|
60
|
+
Dir.glob(path).sort.each do |file|
|
61
|
+
next unless ::File.file?(file)
|
62
|
+
if file.match(/~$/)
|
63
|
+
@logger.debug("NOT reading config file because it is a temp file", :config_file => file)
|
64
|
+
next
|
65
|
+
end
|
66
|
+
@logger.debug("Reading config file", :config_file => file)
|
67
|
+
cfg = ::File.read(file)
|
68
|
+
if !cfg.ascii_only? && !cfg.valid_encoding?
|
69
|
+
encoding_issue_files << file
|
70
|
+
end
|
71
|
+
config << cfg + "\n"
|
72
|
+
@logger.debug? && @logger.debug("\nThe following is the content of a file", :config_file => file.to_s)
|
73
|
+
@logger.debug? && @logger.debug("\n" + cfg + "\n\n")
|
74
|
+
end
|
75
|
+
if encoding_issue_files.any?
|
76
|
+
fail("The following config files contains non-ascii characters but are not UTF-8 encoded #{encoding_issue_files}")
|
77
|
+
end
|
78
|
+
@logger.debug? && @logger.debug("\nThe following is the merged configuration")
|
79
|
+
@logger.debug? && @logger.debug("\n" + config + "\n\n")
|
80
|
+
return config
|
81
|
+
end # def load_config
|
82
|
+
|
83
|
+
def fetch_config(uri)
|
84
|
+
begin
|
85
|
+
Net::HTTP.get(uri) + "\n"
|
86
|
+
rescue Exception => e
|
87
|
+
fail(I18n.t("logstash.runner.configuration.fetch-failed", :path => uri.to_s, :message => e.message))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end end end
|
@@ -38,6 +38,8 @@ module LogStash::Config::Mixin
|
|
38
38
|
PLUGIN_VERSION_1_0_0 = LogStash::Util::PluginVersion.new(1, 0, 0)
|
39
39
|
PLUGIN_VERSION_0_9_0 = LogStash::Util::PluginVersion.new(0, 9, 0)
|
40
40
|
|
41
|
+
ENV_PLACEHOLDER_REGEX = /\$(?<name>\w+)|\$\{(?<name>\w+)(\:(?<default>[^}]*))?\}/
|
42
|
+
|
41
43
|
# This method is called when someone does 'include LogStash::Config'
|
42
44
|
def self.included(base)
|
43
45
|
# Add the DSL methods to the 'base' given.
|
@@ -51,7 +53,7 @@ module LogStash::Config::Mixin
|
|
51
53
|
# Keep a copy of the original config params so that we can later
|
52
54
|
# differentiate between explicit configuration and implicit (default)
|
53
55
|
# configuration.
|
54
|
-
original_params = params.clone
|
56
|
+
@original_params = params.clone
|
55
57
|
|
56
58
|
# store the plugin type, turns LogStash::Inputs::Base into 'input'
|
57
59
|
@plugin_type = self.class.ancestors.find { |a| a.name =~ /::Base$/ }.config_name
|
@@ -99,6 +101,23 @@ module LogStash::Config::Mixin
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
104
|
+
# Resolve environment variables references
|
105
|
+
params.each do |name, value|
|
106
|
+
if (value.is_a?(Hash))
|
107
|
+
value.each do |valueHashKey, valueHashValue|
|
108
|
+
value[valueHashKey.to_s] = replace_env_placeholders(valueHashValue)
|
109
|
+
end
|
110
|
+
else
|
111
|
+
if (value.is_a?(Array))
|
112
|
+
value.each_index do |valueArrayIndex|
|
113
|
+
value[valueArrayIndex] = replace_env_placeholders(value[valueArrayIndex])
|
114
|
+
end
|
115
|
+
else
|
116
|
+
params[name.to_s] = replace_env_placeholders(value)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
102
121
|
if !self.class.validate(params)
|
103
122
|
raise LogStash::ConfigurationError,
|
104
123
|
I18n.t("logstash.agent.configuration.invalid_plugin_settings")
|
@@ -123,14 +142,32 @@ module LogStash::Config::Mixin
|
|
123
142
|
instance_variable_set("@#{key}", value)
|
124
143
|
end
|
125
144
|
|
126
|
-
# now that we know the parameters are valid, we can obfuscate the original copy
|
127
|
-
# of the parameters before storing them as an instance variable
|
128
|
-
self.class.secure_params!(original_params)
|
129
|
-
@original_params = original_params
|
130
|
-
|
131
145
|
@config = params
|
132
146
|
end # def config_init
|
133
147
|
|
148
|
+
# Replace all environment variable references in 'value' param by environment variable value and return updated value
|
149
|
+
# Process following patterns : $VAR, ${VAR}, ${VAR:defaultValue}
|
150
|
+
def replace_env_placeholders(value)
|
151
|
+
return value unless value.is_a?(String)
|
152
|
+
#raise ArgumentError, "Cannot replace ENV placeholders on non-strings. Got #{value.class}" if !value.is_a?(String)
|
153
|
+
|
154
|
+
value.gsub(ENV_PLACEHOLDER_REGEX) do |placeholder|
|
155
|
+
# Note: Ruby docs claim[1] Regexp.last_match is thread-local and scoped to
|
156
|
+
# the call, so this should be thread-safe.
|
157
|
+
#
|
158
|
+
# [1] http://ruby-doc.org/core-2.1.1/Regexp.html#method-c-last_match
|
159
|
+
name = Regexp.last_match(:name)
|
160
|
+
default = Regexp.last_match(:default)
|
161
|
+
|
162
|
+
replacement = ENV.fetch(name, default)
|
163
|
+
if replacement.nil?
|
164
|
+
raise LogStash::ConfigurationError, "Cannot evaluate `#{placeholder}`. Environment variable `#{name}` is not set and there is no default value given."
|
165
|
+
end
|
166
|
+
@logger.info? && @logger.info("Evaluating environment variable placeholder", :placeholder => placeholder, :replacement => replacement)
|
167
|
+
replacement
|
168
|
+
end
|
169
|
+
end # def replace_env_placeholders
|
170
|
+
|
134
171
|
module DSL
|
135
172
|
attr_accessor :flags
|
136
173
|
|
@@ -152,7 +189,7 @@ module LogStash::Config::Mixin
|
|
152
189
|
# inside the gemspec.
|
153
190
|
def milestone(m = nil)
|
154
191
|
@logger = Cabin::Channel.get(LogStash)
|
155
|
-
@logger.
|
192
|
+
@logger.debug(I18n.t('logstash.plugin.deprecated_milestone', :plugin => config_name))
|
156
193
|
end
|
157
194
|
|
158
195
|
# Define a new configuration setting
|
@@ -500,14 +537,6 @@ module LogStash::Config::Mixin
|
|
500
537
|
return true, result
|
501
538
|
end # def validate_value
|
502
539
|
|
503
|
-
def secure_params!(params)
|
504
|
-
params.each do |key, value|
|
505
|
-
if @config[key][:validate] == :password && !value.is_a?(::LogStash::Util::Password)
|
506
|
-
params[key] = ::LogStash::Util::Password.new(value)
|
507
|
-
end
|
508
|
-
end
|
509
|
-
end
|
510
|
-
|
511
540
|
def hash_or_array(value)
|
512
541
|
if !value.is_a?(Hash)
|
513
542
|
value = [*value] # coerce scalar to array if necessary
|
data/lib/logstash/pipeline.rb
CHANGED
@@ -17,21 +17,37 @@ require "logstash/pipeline_reporter"
|
|
17
17
|
require "logstash/output_delegator"
|
18
18
|
|
19
19
|
module LogStash; class Pipeline
|
20
|
-
attr_reader :inputs, :filters, :outputs, :worker_threads, :events_consumed, :events_filtered, :reporter, :pipeline_id, :logger
|
20
|
+
attr_reader :inputs, :filters, :outputs, :worker_threads, :events_consumed, :events_filtered, :reporter, :pipeline_id, :logger, :thread, :config_str, :original_settings
|
21
|
+
|
22
|
+
DEFAULT_OUTPUT_WORKERS = 1
|
21
23
|
|
22
24
|
DEFAULT_SETTINGS = {
|
23
25
|
:default_pipeline_workers => LogStash::Config::CpuCoreStrategy.maximum,
|
24
26
|
:pipeline_batch_size => 125,
|
25
27
|
:pipeline_batch_delay => 5, # in milliseconds
|
26
28
|
:flush_interval => 5, # in seconds
|
27
|
-
:flush_timeout_interval => 60
|
28
|
-
:debug_config => false
|
29
|
+
:flush_timeout_interval => 60 # in seconds
|
29
30
|
}
|
30
31
|
MAX_INFLIGHT_WARN_THRESHOLD = 10_000
|
31
32
|
|
33
|
+
RELOAD_INCOMPATIBLE_PLUGINS = [
|
34
|
+
"LogStash::Inputs::Stdin"
|
35
|
+
]
|
36
|
+
|
37
|
+
def self.validate_config(config_str, settings = {})
|
38
|
+
begin
|
39
|
+
# There should be a better way to test this
|
40
|
+
self.new(config_str, settings)
|
41
|
+
rescue => e
|
42
|
+
e.message
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
32
46
|
def initialize(config_str, settings = {})
|
33
|
-
@
|
47
|
+
@config_str = config_str
|
48
|
+
@original_settings = settings
|
34
49
|
@logger = Cabin::Channel.get(LogStash)
|
50
|
+
@pipeline_id = settings[:pipeline_id] || self.object_id
|
35
51
|
@settings = DEFAULT_SETTINGS.clone
|
36
52
|
settings.each {|setting, value| configure(setting, value) }
|
37
53
|
@reporter = LogStash::PipelineReporter.new(@logger, self)
|
@@ -53,9 +69,7 @@ module LogStash; class Pipeline
|
|
53
69
|
code = @config.compile
|
54
70
|
# The config code is hard to represent as a log message...
|
55
71
|
# So just print it.
|
56
|
-
|
57
|
-
@logger.debug? && @logger.debug("Compiled pipeline code:\n#{code}")
|
58
|
-
end
|
72
|
+
@logger.debug? && @logger.debug("Compiled pipeline code:\n#{code}")
|
59
73
|
begin
|
60
74
|
eval(code)
|
61
75
|
rescue => e
|
@@ -120,13 +134,12 @@ module LogStash; class Pipeline
|
|
120
134
|
end
|
121
135
|
|
122
136
|
def run
|
123
|
-
LogStash::Util.set_thread_name("[#{pipeline_id}]-pipeline-manager")
|
124
137
|
@logger.terminal(LogStash::Util::DefaultsPrinter.print(@settings))
|
138
|
+
@thread = Thread.current
|
125
139
|
|
126
140
|
start_workers
|
127
141
|
|
128
|
-
@logger.
|
129
|
-
@logger.terminal("Logstash startup completed")
|
142
|
+
@logger.log("Pipeline #{@pipeline_id} started")
|
130
143
|
|
131
144
|
# Block until all inputs have stopped
|
132
145
|
# Generally this happens if SIGINT is sent and `shutdown` is called from an external thread
|
@@ -141,8 +154,7 @@ module LogStash; class Pipeline
|
|
141
154
|
shutdown_flusher
|
142
155
|
shutdown_workers
|
143
156
|
|
144
|
-
@logger.
|
145
|
-
@logger.terminal("Logstash shutdown completed")
|
157
|
+
@logger.log("Pipeline #{@pipeline_id} has been shutdown")
|
146
158
|
|
147
159
|
# exit code
|
148
160
|
return 0
|
@@ -403,16 +415,12 @@ module LogStash; class Pipeline
|
|
403
415
|
klass = LogStash::Plugin.lookup(plugin_type, name)
|
404
416
|
|
405
417
|
if plugin_type == "output"
|
406
|
-
LogStash::OutputDelegator.new(@logger, klass,
|
418
|
+
LogStash::OutputDelegator.new(@logger, klass, DEFAULT_OUTPUT_WORKERS, *args)
|
407
419
|
else
|
408
420
|
klass.new(*args)
|
409
421
|
end
|
410
422
|
end
|
411
423
|
|
412
|
-
def default_output_workers
|
413
|
-
@settings[:pipeline_workers] || @settings[:default_pipeline_workers]
|
414
|
-
end
|
415
|
-
|
416
424
|
# for backward compatibility in devutils for the rspec helpers, this method is not used
|
417
425
|
# in the pipeline anymore.
|
418
426
|
def filter(event, &block)
|
@@ -483,17 +491,10 @@ module LogStash; class Pipeline
|
|
483
491
|
.each {|t| t.delete("status") }
|
484
492
|
end
|
485
493
|
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
{
|
491
|
-
:pipeline_id => @pipeline_id,
|
492
|
-
:settings => @settings.inspect,
|
493
|
-
:ready => @ready,
|
494
|
-
:running => @running,
|
495
|
-
:flushing => @flushing
|
496
|
-
}
|
494
|
+
def non_reloadable_plugins
|
495
|
+
(inputs + filters + outputs).select do |plugin|
|
496
|
+
RELOAD_INCOMPATIBLE_PLUGINS.include?(plugin.class.name)
|
497
|
+
end
|
497
498
|
end
|
498
499
|
|
499
500
|
end end
|
data/lib/logstash/runner.rb
CHANGED
@@ -9,11 +9,15 @@ LogStash::Environment.load_locale!
|
|
9
9
|
|
10
10
|
require "logstash/namespace"
|
11
11
|
require "logstash/program"
|
12
|
+
require "logstash/config/defaults"
|
12
13
|
|
13
14
|
class LogStash::Runner
|
14
15
|
include LogStash::Program
|
15
16
|
|
17
|
+
attr_reader :agent
|
18
|
+
|
16
19
|
def main(args)
|
20
|
+
|
17
21
|
require "logstash/util"
|
18
22
|
require "logstash/util/java_version"
|
19
23
|
require "stud/trap"
|
@@ -121,4 +125,5 @@ Available commands:
|
|
121
125
|
def show_help(command)
|
122
126
|
puts command.help
|
123
127
|
end
|
128
|
+
|
124
129
|
end # class LogStash::Runner
|
@@ -34,8 +34,8 @@ module LogStash
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.start(pipeline, cycle_period=CHECK_EVERY, report_every=REPORT_EVERY, abort_threshold=ABORT_AFTER)
|
37
|
-
|
38
|
-
Thread.new(
|
37
|
+
controller = self.new(pipeline, cycle_period, report_every, abort_threshold)
|
38
|
+
Thread.new(controller) { |controller| controller.start }
|
39
39
|
end
|
40
40
|
|
41
41
|
def logger
|
@@ -47,6 +47,7 @@ module LogStash
|
|
47
47
|
cycle_number = 0
|
48
48
|
stalled_count = 0
|
49
49
|
Stud.interval(@cycle_period) do
|
50
|
+
break unless @pipeline.thread.alive?
|
50
51
|
@reports << pipeline_report_snapshot
|
51
52
|
@reports.delete_at(0) if @reports.size > @report_every # expire old report
|
52
53
|
if cycle_number == (@report_every - 1) # it's report time!
|
data/lib/logstash/version.rb
CHANGED
data/locales/en.yml
CHANGED
@@ -59,18 +59,25 @@ en:
|
|
59
59
|
missing-configuration: >-
|
60
60
|
No configuration file was specified. Perhaps you forgot to provide
|
61
61
|
the '-f yourlogstash.conf' flag?
|
62
|
+
reload-without-config-path: >-
|
63
|
+
Configuration reloading also requires passing a configuration path with '-f yourlogstash.conf'
|
62
64
|
error: >-
|
63
65
|
Error: %{error}
|
64
66
|
sigint: >-
|
65
|
-
SIGINT received. Shutting down the
|
67
|
+
SIGINT received. Shutting down the agent.
|
66
68
|
sigterm: >-
|
67
|
-
SIGTERM received. Shutting down the
|
69
|
+
SIGTERM received. Shutting down the agent.
|
68
70
|
slow_shutdown: |-
|
69
71
|
Received shutdown signal, but pipeline is still waiting for in-flight events
|
70
72
|
to be processed. Sending another ^C will force quit Logstash, but this may cause
|
71
73
|
data loss.
|
72
74
|
forced_sigint: >-
|
73
75
|
SIGINT received. Terminating immediately..
|
76
|
+
non_reloadable_config_reload: >-
|
77
|
+
Unable to reload configuration because it does not support dynamic reloading
|
78
|
+
non_reloadable_config_register: |-
|
79
|
+
Logstash was not able to load configuration since it does not support
|
80
|
+
dynamic reloading and -r or --auto-reload flag was enabled
|
74
81
|
configtest-flag-information: |-
|
75
82
|
You may be interested in the '--configtest' flag which you can
|
76
83
|
use to validate logstash's configuration before you choose
|
@@ -163,6 +170,13 @@ en:
|
|
163
170
|
pipeline-batch-delay: |+
|
164
171
|
When creating pipeline batches, how long to wait while polling
|
165
172
|
for the next event.
|
173
|
+
auto_reload: |+
|
174
|
+
Monitor configuration changes and reload
|
175
|
+
whenever it is changed.
|
176
|
+
NOTE: use SIGHUP to manually reload the config
|
177
|
+
reload_interval: |+
|
178
|
+
How frequently to poll the configuration location
|
179
|
+
for changes, in seconds.
|
166
180
|
log: |+
|
167
181
|
Write logstash internal logs to the given
|
168
182
|
file. Without this flag, logstash will emit
|
@@ -193,10 +207,6 @@ en:
|
|
193
207
|
debug: |+
|
194
208
|
Most verbose logging. This causes 'debug'
|
195
209
|
level logs to be emitted.
|
196
|
-
debug-config: |+
|
197
|
-
Print the compiled config ruby code out as a debug log (you must also have --debug enabled).
|
198
|
-
WARNING: This will include any 'password' options passed to plugin configs as plaintext, and may result
|
199
|
-
in plaintext passwords appearing in your logs!
|
200
210
|
unsafe_shutdown: |+
|
201
211
|
Force logstash to exit during shutdown even
|
202
212
|
if there are still inflight events in memory.
|