logstash-core 5.4.3-java → 5.5.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.
- checksums.yaml +4 -4
- data/lib/logstash-core/logstash-core.jar +0 -0
- data/lib/logstash-core/version.rb +1 -1
- data/lib/logstash/api/commands/hot_threads_reporter.rb +2 -2
- data/lib/logstash/api/commands/node.rb +0 -1
- data/lib/logstash/api/commands/stats.rb +0 -1
- data/lib/logstash/config/mixin.rb +5 -43
- data/lib/logstash/config/modules_common.rb +71 -0
- data/lib/logstash/elasticsearch_client.rb +120 -0
- data/lib/logstash/environment.rb +14 -3
- data/lib/logstash/errors.rb +1 -0
- data/lib/logstash/execution_context.rb +11 -3
- data/lib/logstash/inputs/base.rb +2 -0
- data/lib/logstash/instrument/global_metrics.rb +13 -0
- data/lib/logstash/instrument/metric_type/mean.rb +5 -0
- data/lib/logstash/instrument/periodic_poller/jvm.rb +5 -5
- data/lib/logstash/logging/logger.rb +26 -1
- data/lib/logstash/modules/cli_parser.rb +74 -0
- data/lib/logstash/modules/elasticsearch_config.rb +22 -0
- data/lib/logstash/modules/elasticsearch_resource.rb +10 -0
- data/lib/logstash/modules/file_reader.rb +36 -0
- data/lib/logstash/modules/importer.rb +37 -0
- data/lib/logstash/modules/kibana_base_resource.rb +10 -0
- data/lib/logstash/modules/kibana_config.rb +104 -0
- data/lib/logstash/modules/kibana_resource.rb +10 -0
- data/lib/logstash/modules/logstash_config.rb +48 -0
- data/lib/logstash/modules/resource_base.rb +37 -0
- data/lib/logstash/modules/scaffold.rb +44 -0
- data/lib/logstash/namespace.rb +1 -0
- data/lib/logstash/outputs/base.rb +2 -0
- data/lib/logstash/pipeline.rb +18 -4
- data/lib/logstash/plugin.rb +1 -0
- data/lib/logstash/plugins/registry.rb +5 -0
- data/lib/logstash/runner.rb +42 -2
- data/lib/logstash/settings.rb +7 -1
- data/lib/logstash/timestamp.rb +4 -0
- data/lib/logstash/util/dead_letter_queue_manager.rb +61 -0
- data/lib/logstash/util/safe_uri.rb +130 -11
- data/lib/logstash/util/thread_dump.rb +3 -1
- data/lib/logstash/util/wrapped_acked_queue.rb +24 -6
- data/lib/logstash/util/wrapped_synchronous_queue.rb +19 -5
- data/lib/logstash/version.rb +1 -1
- data/locales/en.yml +46 -0
- data/logstash-core.gemspec +7 -2
- data/spec/{api/lib/commands/stats.rb → logstash/api/commands/stats_spec.rb} +7 -2
- data/spec/{api/lib → logstash/api}/errors_spec.rb +1 -1
- data/spec/{api/lib/api → logstash/api/modules}/logging_spec.rb +1 -10
- data/spec/{api/lib/api → logstash/api/modules}/node_plugins_spec.rb +2 -3
- data/spec/{api/lib/api → logstash/api/modules}/node_spec.rb +6 -7
- data/spec/{api/lib/api → logstash/api/modules}/node_stats_spec.rb +2 -2
- data/spec/{api/lib/api → logstash/api/modules}/plugins_spec.rb +4 -3
- data/spec/{api/lib/api → logstash/api/modules}/root_spec.rb +3 -3
- data/spec/{api/lib → logstash/api}/rack_app_spec.rb +0 -0
- data/spec/logstash/config/mixin_spec.rb +2 -2
- data/spec/logstash/execution_context_spec.rb +20 -1
- data/spec/logstash/filter_delegator_spec.rb +2 -1
- data/spec/logstash/inputs/base_spec.rb +1 -1
- data/spec/logstash/output_delegator_spec.rb +2 -1
- data/spec/logstash/outputs/base_spec.rb +1 -1
- data/spec/logstash/pipeline_dlq_commit_spec.rb +107 -0
- data/spec/logstash/pipeline_pq_file_spec.rb +1 -1
- data/spec/logstash/plugin_spec.rb +1 -1
- data/spec/logstash/plugins/registry_spec.rb +22 -5
- data/spec/logstash/runner_spec.rb +122 -19
- data/spec/logstash/settings_spec.rb +91 -0
- data/spec/logstash/timestamp_spec.rb +6 -0
- data/spec/support/helpers.rb +80 -1
- data/spec/support/matchers.rb +13 -0
- data/spec/support/shared_contexts.rb +38 -0
- data/spec/support/shared_examples.rb +1 -1
- metadata +95 -40
- data/spec/api/lib/api/support/resource_dsl_methods.rb +0 -87
- data/spec/api/spec_helper.rb +0 -111
@@ -7,6 +7,7 @@ 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
|
10
11
|
|
11
12
|
class Logger
|
12
13
|
@@config_mutex = Mutex.new
|
@@ -65,7 +66,7 @@ module LogStash
|
|
65
66
|
end
|
66
67
|
|
67
68
|
def self.configure_logging(level, path = LogManager::ROOT_LOGGER_NAME)
|
68
|
-
@@config_mutex.synchronize {
|
69
|
+
@@config_mutex.synchronize { set_level(level, path) }
|
69
70
|
rescue Exception => e
|
70
71
|
raise ArgumentError, "invalid level[#{level}] for logger[#{path}]"
|
71
72
|
end
|
@@ -90,6 +91,30 @@ module LogStash
|
|
90
91
|
def self.get_logging_context
|
91
92
|
return @@logging_context
|
92
93
|
end
|
94
|
+
|
95
|
+
# Clone of org.apache.logging.log4j.core.config.Configurator.setLevel(), but using initialized @@logging_context
|
96
|
+
def self.set_level(_level, path)
|
97
|
+
configuration = @@logging_context.getConfiguration()
|
98
|
+
level = Level.valueOf(_level)
|
99
|
+
if path.nil? || path.strip.empty?
|
100
|
+
root_logger = configuration.getRootLogger()
|
101
|
+
if root_logger.getLevel() != level
|
102
|
+
root_logger.setLevel(level)
|
103
|
+
@@logging_context.updateLoggers()
|
104
|
+
end
|
105
|
+
else
|
106
|
+
package_logger = configuration.getLoggerConfig(path)
|
107
|
+
if package_logger.name != path #no package logger found
|
108
|
+
configuration.addLogger(path, LoggerConfig.new(path, level, true))
|
109
|
+
@@logging_context.updateLoggers()
|
110
|
+
elsif package_logger.getLevel() != level
|
111
|
+
package_logger.setLevel(level)
|
112
|
+
@@logging_context.updateLoggers()
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
private_class_method :set_level
|
93
118
|
end
|
94
119
|
|
95
120
|
class SlowLogger
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require "logstash/logging"
|
4
|
+
require "logstash/errors"
|
5
|
+
|
6
|
+
module LogStash module Modules class CLIParser
|
7
|
+
include LogStash::Util::Loggable
|
8
|
+
|
9
|
+
attr_reader :output
|
10
|
+
def initialize(module_names, module_variables)
|
11
|
+
@output = []
|
12
|
+
# The #compact here catches instances when module_variables may be nil or
|
13
|
+
# [nil] and sets it to []
|
14
|
+
parse_it(module_names, Array(module_variables).compact)
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_modules(module_list)
|
18
|
+
parsed_modules = []
|
19
|
+
module_list.each do |module_value|
|
20
|
+
# Calling --modules but not filling it results in [nil], so skip that.
|
21
|
+
next if module_value.nil?
|
22
|
+
# Catch if --modules was launched empty but an option/flag (-something)
|
23
|
+
# follows immediately after
|
24
|
+
if module_value.start_with?('-')
|
25
|
+
raise LogStash::ConfigLoadingError, I18n.t("logstash.modules.configuration.modules-invalid-name", :module_name => module_value)
|
26
|
+
end
|
27
|
+
parsed_modules.concat module_value.split(',')
|
28
|
+
end
|
29
|
+
parsed_modules
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_kv(module_name, unparsed)
|
33
|
+
# Ensure that there is at least 1 equals sign in our variable string
|
34
|
+
# Using String#partition to split on the first '='
|
35
|
+
# This hackery is to catch the possibility of an equals (`=`) sign
|
36
|
+
# in a passphrase, which might result in an incomplete key. The
|
37
|
+
# portion before the first `=` should always be the key, leaving
|
38
|
+
# the rest to be the value
|
39
|
+
k, op, rest = unparsed.partition('=')
|
40
|
+
if rest.size.zero?
|
41
|
+
raise LogStash::ConfigLoadingError, I18n.t("logstash.modules.configuration.modules-variables-malformed", :rawvar => (module_name + '.' + unparsed))
|
42
|
+
end
|
43
|
+
return k.strip, rest.strip
|
44
|
+
end
|
45
|
+
|
46
|
+
def name_splitter(unparsed)
|
47
|
+
# It must have at least `modulename.something`
|
48
|
+
module_name, dot, rest = unparsed.partition('.')
|
49
|
+
if rest.count('.') >= 1
|
50
|
+
return module_name, rest
|
51
|
+
else
|
52
|
+
raise LogStash::ConfigLoadingError, I18n.t("logstash.modules.configuration.modules-variables-malformed", :rawvar => unparsed)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_vars(module_name, vars_list)
|
57
|
+
module_hash = {"name" => module_name}
|
58
|
+
vars_list.each do |unparsed|
|
59
|
+
extracted_name, modvar = name_splitter(unparsed)
|
60
|
+
next if extracted_name != module_name
|
61
|
+
k, v = get_kv(extracted_name, modvar)
|
62
|
+
module_hash[k] = v
|
63
|
+
end
|
64
|
+
module_hash
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_it(module_list, module_variable_list)
|
68
|
+
if module_list.is_a?(Array)
|
69
|
+
parse_modules(module_list).each do |module_name|
|
70
|
+
@output << parse_vars(module_name, module_variable_list)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end end end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require "logstash/logging"
|
4
|
+
|
5
|
+
require_relative "elasticsearch_resource"
|
6
|
+
|
7
|
+
module LogStash module Modules class ElasticsearchConfig
|
8
|
+
attr_reader :index_name
|
9
|
+
|
10
|
+
# We name it `modul` here because `module` has meaning in Ruby.
|
11
|
+
def initialize(modul, settings)
|
12
|
+
@directory = ::File.join(modul.directory, "elasticsearch")
|
13
|
+
@name = modul.module_name
|
14
|
+
@settings = settings
|
15
|
+
@full_path = ::File.join(@directory, "#{@name}.json")
|
16
|
+
@index_name = @settings.fetch("elasticsearch.template_path", "_template")
|
17
|
+
end
|
18
|
+
|
19
|
+
def resources
|
20
|
+
[ElasticsearchResource.new(@index_name, "not-used", @full_path)]
|
21
|
+
end
|
22
|
+
end end end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require "logstash/logging"
|
4
|
+
require "logstash/json"
|
5
|
+
|
6
|
+
module LogStash module Modules class FileReader
|
7
|
+
# stub these methods for testing
|
8
|
+
include LogStash::Util::Loggable
|
9
|
+
|
10
|
+
def self.read(path)
|
11
|
+
begin
|
12
|
+
::File.read(path)
|
13
|
+
rescue => e
|
14
|
+
logger.error("Error when reading file from path", :path => path)
|
15
|
+
""
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.read_json(path)
|
20
|
+
json = read(path)
|
21
|
+
begin
|
22
|
+
LogStash::Json.load(json)
|
23
|
+
rescue => e
|
24
|
+
logger.error("Error when parsing json from path", :path => path)
|
25
|
+
return {}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.glob(path)
|
30
|
+
files = Dir.glob(path)
|
31
|
+
if files.empty?
|
32
|
+
logger.warn("No files found for glob", :pattern => path)
|
33
|
+
end
|
34
|
+
files
|
35
|
+
end
|
36
|
+
end end end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require "logstash/logging"
|
4
|
+
|
5
|
+
module LogStash module Modules class Importer
|
6
|
+
include LogStash::Util::Loggable
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def put(resource, overwrite = true)
|
13
|
+
path = resource.import_path
|
14
|
+
logger.info("Attempting PUT", :url_path => path, :file_path => resource.content_path)
|
15
|
+
if !overwrite && content_exists?(path)
|
16
|
+
logger.debug("Found existing Elasticsearch resource.", :resource => path)
|
17
|
+
return
|
18
|
+
end
|
19
|
+
put_overwrite(path, resource.content)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def put_overwrite(path, content)
|
25
|
+
if content_exists?(path)
|
26
|
+
response = @client.delete(path)
|
27
|
+
end
|
28
|
+
# hmmm, versioning?
|
29
|
+
@client.put(path, content).status == 201
|
30
|
+
end
|
31
|
+
|
32
|
+
def content_exists?(path)
|
33
|
+
response = @client.head(path)
|
34
|
+
response.status >= 200 && response.status <= 299
|
35
|
+
end
|
36
|
+
|
37
|
+
end end end # class LogStash::Modules::Importer
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require "logstash/logging"
|
4
|
+
|
5
|
+
require_relative "file_reader"
|
6
|
+
require_relative "kibana_resource"
|
7
|
+
require_relative "kibana_base_resource"
|
8
|
+
|
9
|
+
module LogStash module Modules class KibanaConfig
|
10
|
+
include LogStash::Util::Loggable
|
11
|
+
|
12
|
+
ALLOWED_DIRECTORIES = ["search", "visualization"]
|
13
|
+
|
14
|
+
attr_reader :index_name
|
15
|
+
|
16
|
+
# We name it `modul` here because `module` has meaning in Ruby.
|
17
|
+
def initialize(modul, settings)
|
18
|
+
@directory = ::File.join(modul.directory, "kibana")
|
19
|
+
@name = modul.module_name
|
20
|
+
@settings = settings
|
21
|
+
@index_name = settings.fetch("dashboards.kibana_index", ".kibana")
|
22
|
+
end
|
23
|
+
|
24
|
+
def dashboards
|
25
|
+
# there can be more than one dashboard to load
|
26
|
+
filenames = FileReader.read_json(dynamic("dashboard"))
|
27
|
+
filenames.map do |filename|
|
28
|
+
KibanaResource.new(@index_name, "dashboard", dynamic("dashboard", filename))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def index_pattern
|
33
|
+
pattern_name = "#{@name}-*"
|
34
|
+
default_index_json = '{"defaultIndex": "#{pattern_name}"}'
|
35
|
+
default_index_content_id = @settings.fetch("index_pattern.kibana_version", "5.5.0")
|
36
|
+
[
|
37
|
+
KibanaResource.new(@index_name, "index-pattern", dynamic("index-pattern"),nil, pattern_name),
|
38
|
+
KibanaResource.new(@index_name, "config", nil, default_index_json, default_index_content_id)
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
def resources
|
43
|
+
list = index_pattern
|
44
|
+
dashboards.each do |board|
|
45
|
+
extract_panels_into(board, list)
|
46
|
+
end
|
47
|
+
list.concat(extract_saved_searches(list))
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def dynamic(dynamic_folder, filename = @name)
|
53
|
+
::File.join(@directory, dynamic_folder, "#{filename}.json")
|
54
|
+
end
|
55
|
+
|
56
|
+
def extract_panels_into(dashboard, list)
|
57
|
+
list << dashboard
|
58
|
+
|
59
|
+
dash = FileReader.read_json(dashboard.content_path)
|
60
|
+
|
61
|
+
if !dash.is_a?(Hash)
|
62
|
+
logger.warn("Kibana dashboard JSON is not an Object", :module => @name)
|
63
|
+
return
|
64
|
+
end
|
65
|
+
|
66
|
+
panelsjson = dash["panelsJSON"]
|
67
|
+
|
68
|
+
if panelsjson.nil?
|
69
|
+
logger.info("No panelJSON key found in kibana dashboard", :module => @name)
|
70
|
+
return
|
71
|
+
end
|
72
|
+
|
73
|
+
begin
|
74
|
+
panels = LogStash::Json.load(panelsjson)
|
75
|
+
rescue => e
|
76
|
+
logger.error("JSON parse error when reading kibana panelsJSON", :module => @name)
|
77
|
+
return
|
78
|
+
end
|
79
|
+
|
80
|
+
panels.each do |panel|
|
81
|
+
panel_type = panel["type"]
|
82
|
+
if ALLOWED_DIRECTORIES.member?(panel_type)
|
83
|
+
list << KibanaResource.new(@index_name, panel_type, dynamic(panel_type, panel["id"]))
|
84
|
+
else
|
85
|
+
logger.warn("panelJSON contained unknown type", :type => panel_type)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def extract_saved_searches(list)
|
90
|
+
result = [] # must not add to list while iterating
|
91
|
+
list.each do |resource|
|
92
|
+
next unless resource.contains?("savedSearchId")
|
93
|
+
content = resource.content_as_object
|
94
|
+
next if content.nil?
|
95
|
+
saved_search = content["savedSearchId"]
|
96
|
+
next if saved_search.nil?
|
97
|
+
ss_resource = KibanaResource.new(@index_name, "search", dynamic("search", saved_search))
|
98
|
+
next if list.member?(ss_resource) || result.member?(ss_resource)
|
99
|
+
result << ss_resource
|
100
|
+
end
|
101
|
+
result
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end end end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require_relative "file_reader"
|
4
|
+
|
5
|
+
module LogStash module Modules class LogStashConfig
|
6
|
+
|
7
|
+
# We name it `modul` here because `module` has meaning in Ruby.
|
8
|
+
def initialize(modul, settings)
|
9
|
+
@directory = ::File.join(modul.directory, "logstash")
|
10
|
+
@name = modul.module_name
|
11
|
+
@settings = settings
|
12
|
+
end
|
13
|
+
|
14
|
+
def template
|
15
|
+
::File.join(@directory, "#{@name}.conf.erb")
|
16
|
+
end
|
17
|
+
|
18
|
+
def setting(value, default)
|
19
|
+
@settings.fetch(value, default)
|
20
|
+
end
|
21
|
+
|
22
|
+
def elasticsearch_output_config(type_string = nil)
|
23
|
+
hosts = setting("var.output.elasticsearch.hosts", "localhost:9200").split(',').map do |s|
|
24
|
+
'"' + s.strip + '"'
|
25
|
+
end.join(',')
|
26
|
+
index = "#{@name}-#{setting("var.output.elasticsearch.index_suffix", "%{+YYYY.MM.dd}")}"
|
27
|
+
password = "#{setting("var.output.elasticsearch.password", "changeme")}"
|
28
|
+
user = "#{setting("var.output.elasticsearch.user", "elastic")}"
|
29
|
+
document_type_line = type_string ? "document_type => #{type_string}" : ""
|
30
|
+
<<-CONF
|
31
|
+
elasticsearch {
|
32
|
+
hosts => [#{hosts}]
|
33
|
+
index => "#{index}"
|
34
|
+
password => "#{password}"
|
35
|
+
user => "#{user}"
|
36
|
+
manage_template => false
|
37
|
+
#{document_type_line}
|
38
|
+
}
|
39
|
+
CONF
|
40
|
+
end
|
41
|
+
|
42
|
+
def config_string
|
43
|
+
# process the template and settings
|
44
|
+
# send back as a string
|
45
|
+
renderer = ERB.new(FileReader.read(template))
|
46
|
+
renderer.result(binding)
|
47
|
+
end
|
48
|
+
end end end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require_relative "file_reader"
|
4
|
+
|
5
|
+
module LogStash module Modules module ResourceBase
|
6
|
+
attr_reader :base, :content_type, :content_path, :content_id
|
7
|
+
|
8
|
+
def initialize(base, content_type, content_path, content = nil, content_id = nil)
|
9
|
+
@base, @content_type, @content_path = base, content_type, content_path
|
10
|
+
@content_id = content_id || ::File.basename(@content_path, ".*")
|
11
|
+
@content = content
|
12
|
+
end
|
13
|
+
|
14
|
+
def content
|
15
|
+
@content ||= FileReader.read(@content_path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{base}, #{content_type}, #{content_path}, #{content_id}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def contains?(text)
|
23
|
+
content.include?(text)
|
24
|
+
end
|
25
|
+
|
26
|
+
def content_as_object
|
27
|
+
LogStash::Json.load(content) rescue nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def <=>(other)
|
31
|
+
to_s <=> other.to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
def ==(other)
|
35
|
+
to_s == other.to_s
|
36
|
+
end
|
37
|
+
end end end
|