logstash-core 5.4.3-java → 5.5.0-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|