logstash-core 5.0.0.alpha6.snapshot5-java → 5.0.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.

Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jars.rb +1 -1
  3. data/lib/logstash-core/version.rb +1 -1
  4. data/lib/logstash/agent.rb +45 -11
  5. data/lib/logstash/api/app_helpers.rb +43 -7
  6. data/lib/logstash/api/commands/stats.rb +2 -1
  7. data/lib/logstash/api/errors.rb +28 -0
  8. data/lib/logstash/api/modules/base.rb +9 -7
  9. data/lib/logstash/api/modules/logging.rb +52 -0
  10. data/lib/logstash/api/modules/node.rb +13 -9
  11. data/lib/logstash/api/modules/root.rb +0 -2
  12. data/lib/logstash/api/modules/stats.rb +0 -2
  13. data/lib/logstash/api/rack_app.rb +5 -3
  14. data/lib/logstash/environment.rb +4 -5
  15. data/lib/logstash/instrument/collector.rb +4 -0
  16. data/lib/logstash/instrument/metric_store.rb +27 -2
  17. data/lib/logstash/logging/logger.rb +15 -4
  18. data/lib/logstash/patches/puma.rb +44 -0
  19. data/lib/logstash/pipeline.rb +8 -15
  20. data/lib/logstash/runner.rb +31 -17
  21. data/lib/logstash/settings.rb +34 -9
  22. data/lib/logstash/util/wrapped_synchronous_queue.rb +26 -9
  23. data/lib/logstash/version.rb +1 -1
  24. data/lib/logstash/webserver.rb +13 -2
  25. data/locales/en.yml +7 -2
  26. data/logstash-core.gemspec +1 -1
  27. data/spec/api/lib/api/logging_spec.rb +41 -0
  28. data/spec/api/lib/api/node_plugins_spec.rb +4 -3
  29. data/spec/api/lib/api/node_spec.rb +2 -0
  30. data/spec/api/lib/api/node_stats_spec.rb +2 -0
  31. data/spec/api/lib/api/plugins_spec.rb +3 -1
  32. data/spec/api/lib/api/root_spec.rb +3 -0
  33. data/spec/api/lib/errors_spec.rb +27 -0
  34. data/spec/api/lib/rack_app_spec.rb +4 -4
  35. data/spec/logstash/agent_spec.rb +112 -26
  36. data/spec/logstash/instrument/metric_store_spec.rb +37 -0
  37. data/spec/logstash/pipeline_spec.rb +54 -0
  38. data/spec/logstash/runner_spec.rb +2 -1
  39. data/spec/logstash/setting_spec.rb +23 -1
  40. data/spec/logstash/settings/string_spec.rb +1 -1
  41. data/spec/logstash/settings_spec.rb +27 -0
  42. data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +49 -11
  43. data/spec/logstash/webserver_spec.rb +76 -18
  44. data/spec/support/helpers.rb +8 -0
  45. data/spec/support/mocks_classes.rb +22 -0
  46. data/spec/support/shared_examples.rb +10 -0
  47. data/vendor/jars/org/logstash/logstash-core/{5.0.0-alpha6/logstash-core-5.0.0-alpha6.jar → 5.0.0/logstash-core-5.0.0.jar} +0 -0
  48. metadata +16 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb6a76091c290d8e2c2a2fb804473617e09125fb
4
- data.tar.gz: 87918ac0fa2113c2e8e71020358089947dde54dc
3
+ metadata.gz: 580f202da437b439172ac7d75a2040fe78b5b2f5
4
+ data.tar.gz: 5a33bf37b1e0d52b16d71e996bae012f02cbe7d1
5
5
  SHA512:
6
- metadata.gz: 5cba39c4ec6cba7b92981896a9130ce256bbb78a07b9ce8e332f3711756556ea010dab2933975970c1e141a0f942fa2c8f82de5af10126996835f51d7e47ab05
7
- data.tar.gz: 0915d7af51c1430cdaa75f8b23d6f89ca41d05620b0cb8a51e0f50cec919df169f6d204004b0d8f54bf461fabd49edb0d2462fac61a592e517bc9c56fed90aaf
6
+ metadata.gz: 77708d863472390ae13396223803caa3aa95392a6755811e3d8b5e14085d84904712f97e2dc9911bfc675edfca9c67c0d28a57a2fc92449791d2cc5826d4eec0
7
+ data.tar.gz: ba5fa135b749b89e3f908b39d4381c45dcb004b3a1c8763cdf94339fc710e6bb3efc17a6c9ff65611cea88d2901d093986c0aaea45d59dd7f8c1b1bdc6b4947e
@@ -4,4 +4,4 @@ require_jar('org.apache.logging.log4j', 'log4j-api', '2.6.2')
4
4
  require_jar('org.apache.logging.log4j', 'log4j-core', '2.6.2')
5
5
  require_jar('com.fasterxml.jackson.core', 'jackson-core', '2.7.4')
6
6
  require_jar('com.fasterxml.jackson.core', 'jackson-databind', '2.7.4')
7
- require_jar('org.logstash', 'logstash-core', '5.0.0-alpha6')
7
+ require_jar('org.logstash', 'logstash-core', '5.0.0')
@@ -5,4 +5,4 @@
5
5
  # Note to authors: this should not include dashes because 'gem' barfs if
6
6
  # you include a dash in the version string.
7
7
 
8
- LOGSTASH_CORE_VERSION = "5.0.0.alpha6.snapshot5"
8
+ LOGSTASH_CORE_VERSION = "5.0.0"
@@ -48,11 +48,13 @@ class LogStash::Agent
48
48
 
49
49
  # Create the collectors and configured it with the library
50
50
  configure_metrics_collectors
51
+
52
+ @reload_metric = metric.namespace([:stats, :pipelines])
51
53
  end
52
54
 
53
55
  def execute
54
56
  @thread = Thread.current # this var is implicilty used by Stud.stop?
55
- @logger.info("starting agent")
57
+ @logger.debug("starting agent")
56
58
 
57
59
  start_pipelines
58
60
  start_webserver
@@ -99,6 +101,11 @@ class LogStash::Agent
99
101
  begin
100
102
  reload_pipeline!(pipeline_id)
101
103
  rescue => e
104
+ @reload_metric.namespace([pipeline_id.to_sym, :reloads]).tap do |n|
105
+ n.increment(:failures)
106
+ n.gauge(:last_error, { :message => e.message, :backtrace => e.backtrace})
107
+ n.gauge(:last_failure_timestamp, LogStash::Timestamp.now)
108
+ end
102
109
  @logger.error(I18n.t("oops"), :message => e.message, :class => e.class.name, :backtrace => e.backtrace)
103
110
  end
104
111
  end
@@ -162,9 +169,12 @@ class LogStash::Agent
162
169
  @periodic_pollers.start
163
170
  end
164
171
 
165
- def reset_metrics_collectors
166
- stop_collecting_metrics
167
- configure_metrics_collectors
172
+ def reset_pipeline_metrics(id)
173
+ # selectively reset metrics we don't wish to keep after reloading
174
+ # these include metrics about the plugins and number of processed events
175
+ # we want to keep other metrics like reload counts and error messages
176
+ @collector.clear("stats/pipelines/#{id}/plugins")
177
+ @collector.clear("stats/pipelines/#{id}/events")
168
178
  end
169
179
 
170
180
  def collect_metrics?
@@ -184,6 +194,11 @@ class LogStash::Agent
184
194
  begin
185
195
  LogStash::Pipeline.new(config, settings, metric)
186
196
  rescue => e
197
+ @reload_metric.namespace([settings.get("pipeline.id").to_sym, :reloads]).tap do |n|
198
+ n.increment(:failures)
199
+ n.gauge(:last_error, { :message => e.message, :backtrace => e.backtrace})
200
+ n.gauge(:last_failure_timestamp, LogStash::Timestamp.now)
201
+ end
187
202
  if @logger.debug?
188
203
  @logger.error("fetched an invalid config", :config => config, :reason => e.message, :backtrace => e.backtrace)
189
204
  else
@@ -208,11 +223,6 @@ class LogStash::Agent
208
223
  return
209
224
  end
210
225
 
211
- # Reset the current collected stats,
212
- # starting a pipeline with a new configuration should be the same as restarting
213
- # logstash.
214
- reset_metrics_collectors
215
-
216
226
  new_pipeline = create_pipeline(old_pipeline.settings, new_config)
217
227
 
218
228
  return if new_pipeline.nil?
@@ -233,12 +243,17 @@ class LogStash::Agent
233
243
  pipeline = @pipelines[id]
234
244
  return unless pipeline.is_a?(LogStash::Pipeline)
235
245
  return if pipeline.ready?
236
- @logger.info("starting pipeline", :id => id)
246
+ @logger.debug("starting pipeline", :id => id)
237
247
  Thread.new do
238
248
  LogStash::Util.set_thread_name("pipeline.#{id}")
239
249
  begin
240
250
  pipeline.run
241
251
  rescue => e
252
+ @reload_metric.namespace([id.to_sym, :reloads]) do |n|
253
+ n.increment(:failures)
254
+ n.gauge(:last_error, { :message => e.message, :backtrace => e.backtrace})
255
+ n.gauge(:last_failure_timestamp, LogStash::Timestamp.now)
256
+ end
242
257
  @logger.error("Pipeline aborted due to error", :exception => e, :backtrace => e.backtrace)
243
258
  end
244
259
  end
@@ -254,7 +269,11 @@ class LogStash::Agent
254
269
  end
255
270
 
256
271
  def start_pipelines
257
- @pipelines.each { |id, _| start_pipeline(id) }
272
+ @pipelines.each do |id, _|
273
+ start_pipeline(id)
274
+ # no reloads yet, initalize all the reload metrics
275
+ init_pipeline_reload_metrics(id)
276
+ end
258
277
  end
259
278
 
260
279
  def shutdown_pipelines
@@ -268,8 +287,13 @@ class LogStash::Agent
268
287
 
269
288
  def upgrade_pipeline(pipeline_id, new_pipeline)
270
289
  stop_pipeline(pipeline_id)
290
+ reset_pipeline_metrics(pipeline_id)
271
291
  @pipelines[pipeline_id] = new_pipeline
272
292
  start_pipeline(pipeline_id)
293
+ @reload_metric.namespace([pipeline_id.to_sym, :reloads]).tap do |n|
294
+ n.increment(:successes)
295
+ n.gauge(:last_success_timestamp, LogStash::Timestamp.now)
296
+ end
273
297
  end
274
298
 
275
299
  def clean_state?
@@ -279,4 +303,14 @@ class LogStash::Agent
279
303
  def setting(key)
280
304
  @settings.get(key)
281
305
  end
306
+
307
+ def init_pipeline_reload_metrics(id)
308
+ @reload_metric.namespace([id.to_sym, :reloads]).tap do |n|
309
+ n.increment(:successes, 0)
310
+ n.increment(:failures, 0)
311
+ n.gauge(:last_error, nil)
312
+ n.gauge(:last_success_timestamp, nil)
313
+ n.gauge(:last_failure_timestamp, nil)
314
+ end
315
+ end
282
316
  end # class LogStash::Agent
@@ -1,27 +1,43 @@
1
1
  # encoding: utf-8
2
2
  require "logstash/json"
3
+ require "logstash/api/errors"
3
4
 
4
5
  module LogStash::Api::AppHelpers
5
-
6
+ # This method handle both of the normal flow *happy path*
7
+ # and the display or errors, if more custom logic is added here
8
+ # it will make sense to separate them.
9
+ #
10
+ # See `#error` method in the `LogStash::Api::Module::Base`
6
11
  def respond_with(data, options={})
7
12
  as = options.fetch(:as, :json)
8
13
  filter = options.fetch(:filter, "")
9
- pretty = params.has_key?("pretty")
14
+
15
+ status data.respond_to?(:status_code) ? data.status_code : 200
10
16
 
11
17
  if as == :json
12
- selected_fields = extract_fields(filter.to_s.strip)
13
- data.select! { |k,v| selected_fields.include?(k) } unless selected_fields.empty?
14
- unless options.include?(:exclude_default_metadata)
15
- data = default_metadata.merge(data)
18
+ if api_error?(data)
19
+ data = generate_error_hash(data)
20
+ else
21
+ selected_fields = extract_fields(filter.to_s.strip)
22
+ data.select! { |k,v| selected_fields.include?(k) } unless selected_fields.empty?
23
+ unless options.include?(:exclude_default_metadata)
24
+ data = data.to_hash
25
+ if data.values.size == 0 && selected_fields.size > 0
26
+ raise LogStash::Api::NotFoundError
27
+ end
28
+ data = default_metadata.merge(data)
29
+ end
16
30
  end
31
+
17
32
  content_type "application/json"
18
- LogStash::Json.dump(data, {:pretty => pretty})
33
+ LogStash::Json.dump(data, {:pretty => pretty?})
19
34
  else
20
35
  content_type "text/plain"
21
36
  data.to_s
22
37
  end
23
38
  end
24
39
 
40
+ protected
25
41
  def extract_fields(filter_string)
26
42
  (filter_string.empty? ? [] : filter_string.split(",").map { |s| s.strip.to_sym })
27
43
  end
@@ -35,4 +51,24 @@ module LogStash::Api::AppHelpers
35
51
  def default_metadata
36
52
  @factory.build(:default_metadata).all
37
53
  end
54
+
55
+ def api_error?(error)
56
+ error.is_a?(LogStash::Api::ApiError)
57
+ end
58
+
59
+ def pretty?
60
+ params.has_key?("pretty")
61
+ end
62
+
63
+ def generate_error_hash(error)
64
+ {
65
+ :path => request.path,
66
+ :status => error.status_code,
67
+ :error => error.to_hash
68
+ }
69
+ end
70
+
71
+ def human?
72
+ params.has_key?("human") && (params["human"].nil? || as_boolean(params["human"]) == true)
73
+ end
38
74
  end
@@ -91,7 +91,8 @@ module LogStash
91
91
  :inputs => plugin_stats(stats, :inputs),
92
92
  :filters => plugin_stats(stats, :filters),
93
93
  :outputs => plugin_stats(stats, :outputs)
94
- }
94
+ },
95
+ :reloads => stats[:reloads],
95
96
  }
96
97
  end
97
98
  end # module PluginsStats
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ module LogStash
3
+ module Api
4
+ class ApiError < StandardError;
5
+ def initialize(message = nil)
6
+ super(message || "Api Error")
7
+ end
8
+
9
+ def status_code
10
+ 500
11
+ end
12
+
13
+ def to_hash
14
+ { :message => to_s }
15
+ end
16
+ end
17
+
18
+ class NotFoundError < ApiError
19
+ def initialize
20
+ super("Not Found")
21
+ end
22
+
23
+ def status_code
24
+ 404
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,11 +1,13 @@
1
1
  # encoding: utf-8
2
2
  require "logstash/api/app_helpers"
3
3
  require "logstash/api/command_factory"
4
+ require "logstash/api/errors"
4
5
 
5
6
  module LogStash
6
7
  module Api
7
8
  module Modules
8
9
  class Base < ::Sinatra::Base
10
+
9
11
  helpers AppHelpers
10
12
 
11
13
  # These options never change
@@ -29,15 +31,15 @@ module LogStash
29
31
  end
30
32
 
31
33
  not_found do
32
- status 404
33
- as = params.has_key?("human") ? :string : :json
34
- text = as == :string ? "" : {}
35
- respond_with(text, :as => as)
34
+ # We cannot raise here because it wont be catched by the `error` handler.
35
+ # So we manually create a new instance of NotFound and just pass it down.
36
+ respond_with(NotFoundError.new)
36
37
  end
37
38
 
38
- protected
39
- def human?
40
- params.has_key?("human") && (params["human"].nil? || as_boolean(params["human"]) == true)
39
+ # This allow to have custom exception but keep a consistent
40
+ # format to report them.
41
+ error ApiError do |error|
42
+ respond_with(error)
41
43
  end
42
44
  end
43
45
  end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ #
3
+ java_import org.apache.logging.log4j.core.LoggerContext
4
+
5
+ module LogStash
6
+ module Api
7
+ module Modules
8
+ class Logging < ::LogStash::Api::Modules::Base
9
+ # retrieve logging specific parameters from the provided settings
10
+ #
11
+ # return any unused configurations
12
+ def handle_logging(settings)
13
+ Hash[settings.map do |key, level|
14
+ if key.start_with?("logger.")
15
+ _, path = key.split("logger.")
16
+ LogStash::Logging::Logger::configure_logging(level, path)
17
+ nil
18
+ else
19
+ [key, level]
20
+ end
21
+ end]
22
+ end
23
+
24
+ put "/" do
25
+ begin
26
+ request.body.rewind
27
+ req_body = LogStash::Json.load(request.body.read)
28
+ remaining = handle_logging(req_body)
29
+ unless remaining.empty?
30
+ raise ArgumentError, I18n.t("logstash.web_api.logging.unrecognized_option", :option => remaining.keys.first)
31
+ end
32
+ respond_with({"acknowledged" => true})
33
+ rescue ArgumentError => e
34
+ status 400
35
+ respond_with({"error" => e.message})
36
+ end
37
+ end
38
+
39
+ get "/" do
40
+ context = LogStash::Logging::Logger::get_logging_context
41
+ if context.nil?
42
+ status 500
43
+ respond_with({"error" => "Logstash loggers were not initialized properly"})
44
+ else
45
+ loggers = context.getLoggers.map { |lgr| [lgr.getName, lgr.getLevel.name] }.sort
46
+ respond_with({"loggers" => Hash[loggers]})
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  require "logstash/api/modules/base"
3
+ require "logstash/api/errors"
3
4
 
4
5
  module LogStash
5
6
  module Api
@@ -12,20 +13,23 @@ module LogStash
12
13
  get "/hot_threads" do
13
14
  ignore_idle_threads = params["ignore_idle_threads"] || true
14
15
 
15
- options = {
16
- :ignore_idle_threads => as_boolean(ignore_idle_threads),
17
- :human => human?
18
- }
16
+ options = { :ignore_idle_threads => as_boolean(ignore_idle_threads) }
19
17
  options[:threads] = params["threads"].to_i if params.has_key?("threads")
20
18
 
21
- as = options[:human] ? :string : :json
19
+ as = human? ? :string : :json
22
20
  respond_with(node.hot_threads(options), {:as => as})
23
21
  end
24
22
 
25
- get "/?:filter?" do
26
- selected_fields = extract_fields(params["filter"].to_s.strip)
27
- respond_with node.all(selected_fields)
28
- end
23
+ get "/?:filter?" do
24
+ selected_fields = extract_fields(params["filter"].to_s.strip)
25
+ values = node.all(selected_fields)
26
+
27
+ if values.size == 0
28
+ raise NotFoundError
29
+ else
30
+ respond_with(values)
31
+ end
32
+ end
29
33
  end
30
34
  end
31
35
  end
@@ -3,12 +3,10 @@ module LogStash
3
3
  module Api
4
4
  module Modules
5
5
  class Root < ::LogStash::Api::Modules::Base
6
-
7
6
  get "/" do
8
7
  command = factory.build(:system_basic_info)
9
8
  respond_with command.run
10
9
  end
11
-
12
10
  end
13
11
  end
14
12
  end
@@ -3,7 +3,6 @@ module LogStash
3
3
  module Api
4
4
  module Modules
5
5
  class Stats < ::LogStash::Api::Modules::Base
6
-
7
6
  def stats_command
8
7
  factory.build(:stats)
9
8
  end
@@ -36,7 +35,6 @@ module LogStash
36
35
  }
37
36
  respond_with(payload, {:filter => params["filter"]})
38
37
  end
39
-
40
38
  end
41
39
  end
42
40
  end
@@ -5,6 +5,7 @@ require "logstash/api/modules/node"
5
5
  require "logstash/api/modules/node_stats"
6
6
  require "logstash/api/modules/plugins"
7
7
  require "logstash/api/modules/root"
8
+ require "logstash/api/modules/logging"
8
9
  require "logstash/api/modules/stats"
9
10
 
10
11
  module LogStash
@@ -31,9 +32,9 @@ module LogStash
31
32
  status, headers, body = res
32
33
 
33
34
  if fatal_error?(status)
34
- @logger.warn? && @logger.warn(LOG_MESSAGE, RackApp.log_metadata(status, env))
35
+ @logger.error? && @logger.error(LOG_MESSAGE, RackApp.log_metadata(status, env))
35
36
  else
36
- @logger.info? && @logger.info(LOG_MESSAGE, RackApp.log_metadata(status, env))
37
+ @logger.debug? && @logger.debug(LOG_MESSAGE, RackApp.log_metadata(status, env))
37
38
  end
38
39
 
39
40
  res
@@ -103,7 +104,8 @@ module LogStash
103
104
  "/_node" => LogStash::Api::Modules::Node,
104
105
  "/_stats" => LogStash::Api::Modules::Stats,
105
106
  "/_node/stats" => LogStash::Api::Modules::NodeStats,
106
- "/_node/plugins" => LogStash::Api::Modules::Plugins
107
+ "/_node/plugins" => LogStash::Api::Modules::Plugins,
108
+ "/_node/logging" => LogStash::Api::Modules::Logging
107
109
  }
108
110
  end
109
111
  end