logstash-core 5.0.0.alpha6.snapshot5-java → 5.0.0-java

Sign up to get free protection for your applications and to get access to all the features.

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