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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core/logstash-core.jar +0 -0
  3. data/lib/logstash-core/version.rb +1 -1
  4. data/lib/logstash/api/commands/hot_threads_reporter.rb +2 -2
  5. data/lib/logstash/api/commands/node.rb +0 -1
  6. data/lib/logstash/api/commands/stats.rb +0 -1
  7. data/lib/logstash/config/mixin.rb +5 -43
  8. data/lib/logstash/config/modules_common.rb +71 -0
  9. data/lib/logstash/elasticsearch_client.rb +120 -0
  10. data/lib/logstash/environment.rb +14 -3
  11. data/lib/logstash/errors.rb +1 -0
  12. data/lib/logstash/execution_context.rb +11 -3
  13. data/lib/logstash/inputs/base.rb +2 -0
  14. data/lib/logstash/instrument/global_metrics.rb +13 -0
  15. data/lib/logstash/instrument/metric_type/mean.rb +5 -0
  16. data/lib/logstash/instrument/periodic_poller/jvm.rb +5 -5
  17. data/lib/logstash/logging/logger.rb +26 -1
  18. data/lib/logstash/modules/cli_parser.rb +74 -0
  19. data/lib/logstash/modules/elasticsearch_config.rb +22 -0
  20. data/lib/logstash/modules/elasticsearch_resource.rb +10 -0
  21. data/lib/logstash/modules/file_reader.rb +36 -0
  22. data/lib/logstash/modules/importer.rb +37 -0
  23. data/lib/logstash/modules/kibana_base_resource.rb +10 -0
  24. data/lib/logstash/modules/kibana_config.rb +104 -0
  25. data/lib/logstash/modules/kibana_resource.rb +10 -0
  26. data/lib/logstash/modules/logstash_config.rb +48 -0
  27. data/lib/logstash/modules/resource_base.rb +37 -0
  28. data/lib/logstash/modules/scaffold.rb +44 -0
  29. data/lib/logstash/namespace.rb +1 -0
  30. data/lib/logstash/outputs/base.rb +2 -0
  31. data/lib/logstash/pipeline.rb +18 -4
  32. data/lib/logstash/plugin.rb +1 -0
  33. data/lib/logstash/plugins/registry.rb +5 -0
  34. data/lib/logstash/runner.rb +42 -2
  35. data/lib/logstash/settings.rb +7 -1
  36. data/lib/logstash/timestamp.rb +4 -0
  37. data/lib/logstash/util/dead_letter_queue_manager.rb +61 -0
  38. data/lib/logstash/util/safe_uri.rb +130 -11
  39. data/lib/logstash/util/thread_dump.rb +3 -1
  40. data/lib/logstash/util/wrapped_acked_queue.rb +24 -6
  41. data/lib/logstash/util/wrapped_synchronous_queue.rb +19 -5
  42. data/lib/logstash/version.rb +1 -1
  43. data/locales/en.yml +46 -0
  44. data/logstash-core.gemspec +7 -2
  45. data/spec/{api/lib/commands/stats.rb → logstash/api/commands/stats_spec.rb} +7 -2
  46. data/spec/{api/lib → logstash/api}/errors_spec.rb +1 -1
  47. data/spec/{api/lib/api → logstash/api/modules}/logging_spec.rb +1 -10
  48. data/spec/{api/lib/api → logstash/api/modules}/node_plugins_spec.rb +2 -3
  49. data/spec/{api/lib/api → logstash/api/modules}/node_spec.rb +6 -7
  50. data/spec/{api/lib/api → logstash/api/modules}/node_stats_spec.rb +2 -2
  51. data/spec/{api/lib/api → logstash/api/modules}/plugins_spec.rb +4 -3
  52. data/spec/{api/lib/api → logstash/api/modules}/root_spec.rb +3 -3
  53. data/spec/{api/lib → logstash/api}/rack_app_spec.rb +0 -0
  54. data/spec/logstash/config/mixin_spec.rb +2 -2
  55. data/spec/logstash/execution_context_spec.rb +20 -1
  56. data/spec/logstash/filter_delegator_spec.rb +2 -1
  57. data/spec/logstash/inputs/base_spec.rb +1 -1
  58. data/spec/logstash/output_delegator_spec.rb +2 -1
  59. data/spec/logstash/outputs/base_spec.rb +1 -1
  60. data/spec/logstash/pipeline_dlq_commit_spec.rb +107 -0
  61. data/spec/logstash/pipeline_pq_file_spec.rb +1 -1
  62. data/spec/logstash/plugin_spec.rb +1 -1
  63. data/spec/logstash/plugins/registry_spec.rb +22 -5
  64. data/spec/logstash/runner_spec.rb +122 -19
  65. data/spec/logstash/settings_spec.rb +91 -0
  66. data/spec/logstash/timestamp_spec.rb +6 -0
  67. data/spec/support/helpers.rb +80 -1
  68. data/spec/support/matchers.rb +13 -0
  69. data/spec/support/shared_contexts.rb +38 -0
  70. data/spec/support/shared_examples.rb +1 -1
  71. metadata +95 -40
  72. data/spec/api/lib/api/support/resource_dsl_methods.rb +0 -87
  73. 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 { Configurator.setLevel(path, Level.valueOf(level)) }
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,10 @@
1
+ # encoding: utf-8
2
+ require "logstash/namespace"
3
+ require_relative "resource_base"
4
+
5
+ module LogStash module Modules class ElasticsearchResource
6
+ include ResourceBase
7
+ def import_path
8
+ base + "/" + content_id
9
+ end
10
+ 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,10 @@
1
+ # encoding: utf-8
2
+ require "logstash/namespace"
3
+ require_relative "resource_base"
4
+
5
+ module LogStash module Modules class KibanaBaseResource
6
+ include ResourceBase
7
+ def import_path
8
+ base
9
+ end
10
+ end end end
@@ -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,10 @@
1
+ # encoding: utf-8
2
+ require "logstash/namespace"
3
+ require_relative "resource_base"
4
+
5
+ module LogStash module Modules class KibanaResource
6
+ include ResourceBase
7
+ def import_path
8
+ base + "/" + content_type + "/" + content_id
9
+ end
10
+ 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