logstash-core 5.0.0.alpha3.snapshot5-java → 5.0.0.alpha3.snapshot6-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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core/version.rb +1 -1
  3. data/lib/logstash/api/{lib/helpers/app_helpers.rb → app_helpers.rb} +0 -0
  4. data/lib/logstash/api/command_factory.rb +34 -0
  5. data/lib/logstash/api/commands/base.rb +25 -0
  6. data/lib/logstash/api/commands/stats.rb +105 -0
  7. data/lib/logstash/api/commands/system/basicinfo_command.rb +23 -0
  8. data/lib/logstash/api/commands/system/plugins_command.rb +35 -0
  9. data/lib/logstash/api/modules/base.rb +41 -0
  10. data/lib/logstash/api/modules/node.rb +24 -0
  11. data/lib/logstash/api/modules/node_stats.rb +59 -0
  12. data/lib/logstash/api/modules/plugins.rb +15 -0
  13. data/lib/logstash/api/modules/root.rb +15 -0
  14. data/lib/logstash/api/modules/stats.rb +63 -0
  15. data/lib/logstash/api/rack_app.rb +33 -0
  16. data/lib/logstash/api/service.rb +73 -0
  17. data/lib/logstash/instrument/metric_store.rb +11 -1
  18. data/lib/logstash/instrument/periodic_poller/base.rb +2 -0
  19. data/lib/logstash/instrument/periodic_poller/jvm.rb +47 -2
  20. data/lib/logstash/util/thread_dump.rb +55 -0
  21. data/lib/logstash/version.rb +1 -1
  22. data/lib/logstash/webserver.rb +15 -49
  23. data/locales/en.yml +5 -5
  24. data/logstash-core.gemspec +3 -3
  25. data/spec/api/lib/api/node_spec.rb +2 -2
  26. data/spec/api/lib/api/node_stats_spec.rb +32 -57
  27. data/spec/api/lib/api/plugins_spec.rb +2 -2
  28. data/spec/api/lib/api/root_spec.rb +2 -2
  29. data/spec/api/lib/api/support/resource_dsl_methods.rb +47 -0
  30. data/spec/api/lib/commands/stats.rb +47 -0
  31. data/spec/api/spec_helper.rb +2 -5
  32. data/spec/logstash/agent_spec.rb +1 -1
  33. data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +45 -0
  34. metadata +30 -38
  35. data/lib/logstash/api/init.ru +0 -31
  36. data/lib/logstash/api/lib/app.rb +0 -40
  37. data/lib/logstash/api/lib/app/command.rb +0 -29
  38. data/lib/logstash/api/lib/app/command_factory.rb +0 -29
  39. data/lib/logstash/api/lib/app/commands/stats/events_command.rb +0 -13
  40. data/lib/logstash/api/lib/app/commands/stats/hotthreads_command.rb +0 -120
  41. data/lib/logstash/api/lib/app/commands/stats/memory_command.rb +0 -25
  42. data/lib/logstash/api/lib/app/commands/system/basicinfo_command.rb +0 -15
  43. data/lib/logstash/api/lib/app/commands/system/plugins_command.rb +0 -28
  44. data/lib/logstash/api/lib/app/modules/node.rb +0 -25
  45. data/lib/logstash/api/lib/app/modules/node_stats.rb +0 -51
  46. data/lib/logstash/api/lib/app/modules/plugins.rb +0 -15
  47. data/lib/logstash/api/lib/app/modules/stats.rb +0 -21
  48. data/lib/logstash/api/lib/app/root.rb +0 -13
  49. data/lib/logstash/api/lib/app/service.rb +0 -61
  50. data/lib/logstash/api/lib/app/stats.rb +0 -56
  51. data/spec/api/lib/api/stats_spec.rb +0 -19
  52. data/spec/api/lib/commands/events_spec.rb +0 -17
  53. data/spec/api/lib/commands/jvm_spec.rb +0 -45
@@ -0,0 +1,33 @@
1
+ require "logstash/api/modules/base"
2
+ require "logstash/api/modules/node"
3
+ require "logstash/api/modules/node_stats"
4
+ require "logstash/api/modules/plugins"
5
+ require "logstash/api/modules/root"
6
+ require "logstash/api/modules/stats"
7
+
8
+ module LogStash
9
+ module Api
10
+ module RackApp
11
+ def self.app
12
+ namespaces = rack_namespaces
13
+ Rack::Builder.new do
14
+ run LogStash::Api::Modules::Root
15
+ namespaces.each_pair do |namespace, app|
16
+ map(namespace) do
17
+ run app
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ def self.rack_namespaces
24
+ {
25
+ "/_node" => LogStash::Api::Modules::Node,
26
+ "/_stats" => LogStash::Api::Modules::Stats,
27
+ "/_node/stats" => LogStash::Api::Modules::NodeStats,
28
+ "/_plugins" => LogStash::Api::Modules::Plugins
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+ require "logstash/instrument/collector"
3
+ require "logstash/util/loggable"
4
+
5
+ module LogStash
6
+ module Api
7
+ class Service
8
+
9
+ include Singleton
10
+ include LogStash::Util::Loggable
11
+
12
+ def initialize
13
+ @snapshot_rotation_mutex = Mutex.new
14
+ @snapshot = nil
15
+ logger.debug("[api-service] start") if logger.debug?
16
+ LogStash::Instrument::Collector.instance.add_observer(self)
17
+ end
18
+
19
+ def stop
20
+ logger.debug("[api-service] stop") if logger.debug?
21
+ LogStash::Instrument::Collector.instance.delete_observer(self)
22
+ end
23
+
24
+ def agent
25
+ LogStash::Instrument::Collector.instance.agent
26
+ end
27
+
28
+ def started?
29
+ !@snapshot.nil? && has_counters?
30
+ end
31
+
32
+ def update(snapshot)
33
+ logger.debug("[api-service] snapshot received", :snapshot_time => snapshot.created_at) if logger.debug?
34
+
35
+ @snapshot_rotation_mutex.synchronize do
36
+ @snapshot = snapshot
37
+ end
38
+ end
39
+
40
+ def snapshot
41
+ @snapshot_rotation_mutex.synchronize { @snapshot }
42
+ end
43
+
44
+ def get_shallow(*path)
45
+ snapshot.metric_store.get_shallow(*path)
46
+ end
47
+
48
+ def get(key)
49
+ metric_store = @snapshot_rotation_mutex.synchronize { @snapshot.metric_store }
50
+ if key == :jvm_memory_stats
51
+ data = metric_store.get_shallow(:jvm, :memory)
52
+ else
53
+ data = metric_store.get_with_path("stats/events")
54
+ end
55
+ LogStash::Json.dump(data)
56
+ end
57
+
58
+ private
59
+
60
+ def has_counters?
61
+ (["LogStash::Instrument::MetricType::Counter", "LogStash::Instrument::MetricType::Gauge"] - metric_types).empty?
62
+ end
63
+
64
+ def metric_types
65
+ types = []
66
+ @snapshot_rotation_mutex.synchronize do
67
+ types = @snapshot.metric_store.all.map { |t| t.class.to_s }
68
+ end
69
+ return types
70
+ end
71
+ end
72
+ end
73
+ end
@@ -86,7 +86,7 @@ module LogStash module Instrument
86
86
 
87
87
  # Similar to `get_with_path` but use symbols instead of string
88
88
  #
89
- # @param [Array<Symbol>
89
+ # @param [Array<Symbol>]
90
90
  # @return [Hash]
91
91
  def get(*key_paths)
92
92
  # Normalize the symbols access
@@ -100,6 +100,16 @@ module LogStash module Instrument
100
100
  new_hash
101
101
  end
102
102
 
103
+ # Retrieve values like `get`, but don't return them fully nested.
104
+ # This means that if you call `get_shallow(:foo, :bar)` the result will not
105
+ # be nested inside of `{:foo {:bar => values}`.
106
+ #
107
+ # @param [Array<Symbol>]
108
+ # @return [Hash]
109
+ def get_shallow(*key_paths)
110
+ key_paths.reduce(get(*key_paths)) {|acc, p| acc[p]}
111
+ end
112
+
103
113
  # Return all the individuals Metric,
104
114
  # This call mimic a Enum's each if a block is provided
105
115
  #
@@ -37,6 +37,8 @@ module LogStash module Instrument module PeriodicPoller
37
37
  logger.debug("PeriodicPoller: Starting",
38
38
  :polling_interval => @options[:polling_interval],
39
39
  :polling_timeout => @options[:polling_timeout]) if logger.debug?
40
+
41
+ collect # Collect data right away if possible
40
42
  @task.execute
41
43
  end
42
44
 
@@ -1,6 +1,15 @@
1
+
1
2
  # encoding: utf-8
2
3
  require "logstash/instrument/periodic_poller/base"
3
- require 'monitoring'
4
+ require 'jrmonitor'
5
+
6
+ java_import 'java.lang.management.ManagementFactory'
7
+ java_import 'java.lang.management.OperatingSystemMXBean'
8
+ java_import 'com.sun.management.UnixOperatingSystemMXBean'
9
+ java_import 'javax.management.MBeanServer'
10
+ java_import 'javax.management.ObjectName'
11
+ java_import 'javax.management.AttributeList'
12
+ java_import 'javax.naming.directory.Attribute'
4
13
 
5
14
  module LogStash module Instrument module PeriodicPoller
6
15
  class JVM < Base
@@ -13,14 +22,50 @@ module LogStash module Instrument module PeriodicPoller
13
22
  end
14
23
 
15
24
  def collect
16
- raw = JRMonitor.memory.generate
25
+ raw = JRMonitor.memory.generate
17
26
  collect_heap_metrics(raw)
18
27
  collect_non_heap_metrics(raw)
19
28
  collect_pools_metrics(raw)
29
+ collect_threads_metrics
30
+ collect_process_metrics
20
31
  end
21
32
 
22
33
  private
23
34
 
35
+ def collect_threads_metrics
36
+ threads = JRMonitor.threads.generate
37
+
38
+ current = threads.count
39
+ if @peak_threads.nil? || @peak_threads < current
40
+ @peak_threads = current
41
+ end
42
+
43
+ metric.gauge([:jvm, :threads], :count, threads.count)
44
+ metric.gauge([:jvm, :threads], :peak_count, @peak_threads)
45
+ end
46
+
47
+ def collect_process_metrics
48
+ process_metrics = JRMonitor.process.generate
49
+
50
+ path = [:jvm, :process]
51
+
52
+
53
+ open_fds = process_metrics["open_file_descriptors"]
54
+ if @peak_open_fds.nil? || open_fds > @peak_open_fds
55
+ @peak_open_fds = open_fds
56
+ end
57
+ metric.gauge(path, :open_file_descriptors, open_fds)
58
+ metric.gauge(path, :peak_open_file_descriptors, @peak_open_fds)
59
+ metric.gauge(path, :max_file_descriptors, process_metrics["max_file_descriptors"])
60
+
61
+ cpu_path = path + [:cpu]
62
+ cpu_metrics = process_metrics["cpu"]
63
+ metric.gauge(cpu_path, :percent, cpu_metrics["process_percent"])
64
+ metric.gauge(cpu_path, :total_in_millis, cpu_metrics["total_in_millis"])
65
+
66
+ metric.gauge(path + [:mem], :total_virtual_in_bytes, process_metrics["mem"]["total_virtual_in_bytes"])
67
+ end
68
+
24
69
  def collect_heap_metrics(data)
25
70
  heap = aggregate_information_for(data["heap"].values)
26
71
  heap[:used_percent] = (heap[:used_in_bytes] / heap[:max_in_bytes].to_f)*100.0
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ module LogStash
3
+ module Util
4
+ class ThreadDump
5
+ SKIPPED_THREADS = [ "Finalizer", "Reference Handler", "Signal Dispatcher" ].freeze
6
+ THREADS_COUNT_DEFAULT = 3.freeze
7
+ IGNORE_IDLE_THREADS_DEFAULT = true.freeze
8
+
9
+ attr_reader :top_count, :ignore, :dump
10
+
11
+ def initialize(options={})
12
+ @options = options
13
+ @dump = options.fetch(:dump, JRMonitor.threads.generate({}))
14
+ @top_count = options.fetch(:threads, THREADS_COUNT_DEFAULT)
15
+ @ignore = options.fetch(:ignore_idle_threads, IGNORE_IDLE_THREADS_DEFAULT)
16
+ end
17
+
18
+ def each(&block)
19
+ i=0
20
+ dump.each_pair do |thread_name, _hash|
21
+ break if i >= top_count
22
+ if ignore
23
+ next if idle_thread?(thread_name, _hash)
24
+ end
25
+ block.call(thread_name, _hash)
26
+ i += 1
27
+ end
28
+ end
29
+
30
+ def idle_thread?(thread_name, data)
31
+ idle = false
32
+ if SKIPPED_THREADS.include?(thread_name)
33
+ # these are likely JVM dependent
34
+ idle = true
35
+ elsif thread_name.match(/Ruby-\d+-JIT-\d+/)
36
+ # This are internal JRuby JIT threads,
37
+ # see java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor for details.
38
+ idle = true
39
+ elsif thread_name.match(/pool-\d+-thread-\d+/)
40
+ # This are threads used by the internal JRuby implementation to dispatch
41
+ # calls and tasks, see prg.jruby.internal.runtime.methods.DynamicMethod.call
42
+ idle = true
43
+ else
44
+ data["thread.stacktrace"].each do |trace|
45
+ if trace.start_with?("java.util.concurrent.ThreadPoolExecutor.getTask")
46
+ idle = true
47
+ break
48
+ end
49
+ end
50
+ end
51
+ idle
52
+ end
53
+ end
54
+ end
55
+ end
@@ -11,4 +11,4 @@
11
11
  # eventually this file should be in the root logstash lib fir and dependencies in logstash-core should be
12
12
  # fixed.
13
13
 
14
- LOGSTASH_VERSION = "5.0.0-alpha3.snapshot5"
14
+ LOGSTASH_VERSION = "5.0.0-alpha3.snapshot6"
@@ -1,16 +1,15 @@
1
1
  # encoding: utf-8
2
2
  require "puma"
3
- require "puma/single"
4
- require "puma/binder"
5
- require "puma/configuration"
6
- require "puma/commonlogger"
3
+ require "puma/server"
4
+ require "sinatra"
5
+ require "rack"
6
+ require "logstash/api/rack_app"
7
7
 
8
8
  module LogStash
9
9
  class WebServer
10
-
11
10
  extend Forwardable
12
11
 
13
- attr_reader :logger, :status, :config, :options, :cli_options, :runner, :binder, :events
12
+ attr_reader :logger, :status, :config, :options, :cli_options, :runner, :binder, :events, :http_host, :http_port
14
13
 
15
14
  def_delegator :@runner, :stats
16
15
 
@@ -19,8 +18,8 @@ module LogStash
19
18
 
20
19
  def initialize(logger, options={})
21
20
  @logger = logger
22
- http_host = options[:http_host] || DEFAULT_HOST
23
- http_port = options[:http_port] || DEFAULT_PORT
21
+ @http_host = options[:http_host] || DEFAULT_HOST
22
+ @http_port = options[:http_port] || DEFAULT_PORT
24
23
  @options = {}
25
24
  @cli_options = options.merge({ :rackup => ::File.join(::File.dirname(__FILE__), "api", "init.ru"),
26
25
  :binds => ["tcp://#{http_host}:#{http_port}"],
@@ -31,24 +30,17 @@ module LogStash
31
30
  :queue_requests => false
32
31
  })
33
32
  @status = nil
34
-
35
- parse_options
36
-
37
- @runner = nil
38
- @events = ::Puma::Events.strings
39
- @binder = ::Puma::Binder.new(@events)
40
- @binder.import_from_env
41
-
42
- set_environment
43
33
  end
44
34
 
45
35
  def run
46
36
  log "=== puma start: #{Time.now} ==="
47
37
 
48
- @runner = Puma::Single.new(self)
49
- @status = :run
50
- @runner.run
51
- stop(:graceful => true)
38
+ stop # Just in case
39
+
40
+ @server = ::Puma::Server.new(LogStash::Api::RackApp.app)
41
+ @server.add_tcp_listener(http_host, http_port)
42
+
43
+ @server.run.join
52
44
  end
53
45
 
54
46
  def log(str)
@@ -58,7 +50,7 @@ module LogStash
58
50
  def error(str)
59
51
  logger.error(str)
60
52
  end
61
-
53
+
62
54
  # Empty method, this method is required because of the puma usage we make through
63
55
  # the Single interface, https://github.com/puma/puma/blob/master/lib/puma/single.rb#L82
64
56
  # for more details. This can always be implemented when we want to keep track of this
@@ -66,33 +58,7 @@ module LogStash
66
58
  def write_state; end
67
59
 
68
60
  def stop(options={})
69
- graceful = options.fetch(:graceful, true)
70
-
71
- if graceful
72
- @runner.stop_blocked
73
- else
74
- @runner.stop
75
- end rescue nil
76
-
77
- @status = :stop
78
- log "=== puma shutdown: #{Time.now} ==="
79
- end
80
-
81
- private
82
-
83
- def env
84
- @options[:debug] ? "development" : "production"
85
- end
86
-
87
- def set_environment
88
- @options[:environment] = env
89
- ENV['RACK_ENV'] = env
90
- end
91
-
92
- def parse_options
93
- @config = ::Puma::Configuration.new(cli_options)
94
- @config.load
95
- @options = @config.options
61
+ @server.stop(true) if @server
96
62
  end
97
63
  end
98
64
  end
@@ -1,6 +1,6 @@
1
1
  # YAML notes
2
2
  # |- means 'scalar block' useful for formatted text
3
- # > means 'scalar block' but it chomps all newlines. Useful
3
+ # > means 'scalar block' but it chomps all newlines. Useful
4
4
  # for unformatted text.
5
5
  en:
6
6
  oops: |-
@@ -76,7 +76,7 @@ en:
76
76
  hot_threads:
77
77
  title: |-
78
78
  ::: {%{hostname}}
79
- Hot threads at %{time}, busiestThreads=%{top_count}:
79
+ Hot threads at %{time}, busiestThreads=%{top_count}:
80
80
  thread_title: |-
81
81
  %{percent_of_cpu_time} % of cpu usage by %{thread_state} thread named '%{thread_name}'
82
82
  runner:
@@ -141,18 +141,18 @@ en:
141
141
  after %{after}
142
142
  invalid_plugin_register: >-
143
143
  Cannot register %{plugin} %{type} plugin.
144
- The error reported is:
144
+ The error reported is:
145
145
  %{error}
146
146
  plugin_path_missing: >-
147
147
  You specified a plugin path that does not exist: %{path}
148
148
  no_plugins_found: |-
149
149
  Could not find any plugins in "%{path}"
150
- I tried to find files matching the following, but found none:
150
+ I tried to find files matching the following, but found none:
151
151
  %{plugin_glob}
152
152
  log_file_failed: |-
153
153
  Failed to open %{path} for writing: %{error}
154
154
 
155
- This is often a permissions issue, or the wrong
155
+ This is often a permissions issue, or the wrong
156
156
  path was specified?
157
157
  flag:
158
158
  # Note: Wrap these at 55 chars so they display nicely when clamp emits
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.require_paths = ["lib"]
18
18
  gem.version = LOGSTASH_CORE_VERSION.gsub(/-/, '.')
19
19
 
20
- gem.add_runtime_dependency "logstash-core-event-java", "5.0.0.alpha3.snapshot5"
20
+ gem.add_runtime_dependency "logstash-core-event-java", "5.0.0.alpha3.snapshot6"
21
21
 
22
22
  gem.add_runtime_dependency "cabin", "~> 0.8.0" #(Apache 2.0 license)
23
23
  gem.add_runtime_dependency "pry", "~> 0.10.1" #(Ruby license)
@@ -27,10 +27,10 @@ Gem::Specification.new do |gem|
27
27
  gem.add_runtime_dependency "gems", "~> 0.8.3" #(MIT license)
28
28
  gem.add_runtime_dependency "concurrent-ruby", "1.0.0"
29
29
  gem.add_runtime_dependency "sinatra", '~> 1.4', '>= 1.4.6'
30
- gem.add_runtime_dependency 'puma', '~> 2.16', '>= 2.16.0'
30
+ gem.add_runtime_dependency 'puma', '~> 3.4.0'
31
31
  gem.add_runtime_dependency "jruby-openssl", "0.9.16" # >= 0.9.13 Required to support TLSv1.2
32
32
  gem.add_runtime_dependency "chronic_duration", "0.10.6"
33
- gem.add_runtime_dependency "jruby-monitoring", '~> 0.3.1'
33
+ gem.add_runtime_dependency "jrmonitor", '~> 0.4.2'
34
34
 
35
35
  # TODO(sissel): Treetop 1.5.x doesn't seem to work well, but I haven't
36
36
  # investigated what the cause might be. -Jordan
@@ -1,10 +1,10 @@
1
1
  # encoding: utf-8
2
2
  require_relative "../../spec_helper"
3
3
  require "sinatra"
4
- require "app/modules/node"
4
+ require "logstash/api/modules/node"
5
5
  require "logstash/json"
6
6
 
7
- describe LogStash::Api::Node do
7
+ describe LogStash::Api::Modules::Node do
8
8
 
9
9
  include Rack::Test::Methods
10
10