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.
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