logstash-core 5.0.0.alpha4.snapshot1-java → 5.0.0.alpha4.snapshot2-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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core/version.rb +1 -1
  3. data/lib/logstash/agent.rb +31 -36
  4. data/lib/logstash/api/command_factory.rb +3 -1
  5. data/lib/logstash/api/commands/base.rb +4 -0
  6. data/lib/logstash/api/commands/node.rb +116 -0
  7. data/lib/logstash/api/commands/stats.rb +28 -77
  8. data/lib/logstash/api/modules/base.rb +2 -2
  9. data/lib/logstash/api/modules/node.rb +23 -6
  10. data/lib/logstash/api/modules/node_stats.rb +15 -1
  11. data/lib/logstash/api/rack_app.rb +9 -6
  12. data/lib/logstash/api/service.rb +8 -47
  13. data/lib/logstash/config/config_ast.rb +11 -3
  14. data/lib/logstash/config/mixin.rb +60 -22
  15. data/lib/logstash/inputs/metrics.rb +2 -2
  16. data/lib/logstash/instrument/collector.rb +5 -6
  17. data/lib/logstash/instrument/metric.rb +1 -1
  18. data/lib/logstash/instrument/metric_store.rb +54 -0
  19. data/lib/logstash/pipeline.rb +10 -4
  20. data/lib/logstash/runner.rb +2 -2
  21. data/lib/logstash/util/safe_uri.rb +48 -0
  22. data/lib/logstash/version.rb +1 -1
  23. data/lib/logstash/webserver.rb +8 -7
  24. data/logstash-core.gemspec +1 -1
  25. data/spec/api/lib/api/node_plugins_spec.rb +32 -0
  26. data/spec/api/lib/api/node_spec.rb +41 -7
  27. data/spec/api/lib/api/node_stats_spec.rb +31 -6
  28. data/spec/api/lib/api/plugins_spec.rb +1 -7
  29. data/spec/api/lib/api/root_spec.rb +2 -7
  30. data/spec/api/lib/api/support/resource_dsl_methods.rb +14 -7
  31. data/spec/api/spec_helper.rb +24 -50
  32. data/spec/logstash/agent_spec.rb +36 -13
  33. data/spec/logstash/config/config_ast_spec.rb +43 -0
  34. data/spec/logstash/config/mixin_spec.rb +138 -0
  35. data/spec/logstash/inputs/metrics_spec.rb +10 -11
  36. data/spec/logstash/instrument/collector_spec.rb +1 -1
  37. data/spec/logstash/instrument/metric_store_spec.rb +61 -0
  38. data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +6 -3
  39. data/spec/logstash/pipeline_spec.rb +9 -9
  40. data/spec/support/mocks_classes.rb +2 -1
  41. metadata +39 -35
@@ -32,8 +32,8 @@ module LogStash; class Pipeline
32
32
  :started_at,
33
33
  :thread,
34
34
  :config_str,
35
- :settings
36
- attr_accessor :metric
35
+ :settings,
36
+ :metric
37
37
 
38
38
  MAX_INFLIGHT_WARN_THRESHOLD = 10_000
39
39
 
@@ -41,7 +41,7 @@ module LogStash; class Pipeline
41
41
  "LogStash::Inputs::Stdin"
42
42
  ]
43
43
 
44
- def initialize(config_str, settings = LogStash::SETTINGS)
44
+ def initialize(config_str, settings = LogStash::SETTINGS, namespaced_metric = nil)
45
45
  @config_str = config_str
46
46
  @logger = Cabin::Channel.get(LogStash)
47
47
  @settings = settings
@@ -56,7 +56,7 @@ module LogStash; class Pipeline
56
56
 
57
57
  # This needs to be configured before we evaluate the code to make
58
58
  # sure the metric instance is correctly send to the plugins to make the namespace scoping work
59
- @metric = settings.get_value("metric.collect") ? Instrument::Metric.new : Instrument::NullMetric.new
59
+ @metric = namespaced_metric.nil? ? LogStash::Instrument::NullMetric.new : namespaced_metric
60
60
 
61
61
  grammar = LogStashConfigParser.new
62
62
  @config = grammar.parse(config_str)
@@ -188,6 +188,12 @@ module LogStash; class Pipeline
188
188
  batch_size = @settings.get("pipeline.batch.size")
189
189
  batch_delay = @settings.get("pipeline.batch.delay")
190
190
  max_inflight = batch_size * pipeline_workers
191
+
192
+ config_metric = metric.namespace([:stats, :pipelines, pipeline_id.to_s.to_sym, :config])
193
+ config_metric.gauge(:workers, pipeline_workers)
194
+ config_metric.gauge(:batch_size, batch_size)
195
+ config_metric.gauge(:batch_delay, batch_delay)
196
+
191
197
  @logger.info("Starting pipeline",
192
198
  "id" => self.pipeline_id,
193
199
  "pipeline.workers" => pipeline_workers,
@@ -18,10 +18,10 @@ require "logstash/patches/clamp"
18
18
  require "logstash/settings"
19
19
 
20
20
  class LogStash::Runner < Clamp::StrictCommand
21
- # The `path.settings` need to be defined in the runner instead of the `logstash-core/lib/logstash/environment.r`
21
+ # The `path.settings` need to be defined in the runner instead of the `logstash-core/lib/logstash/environment.rb`
22
22
  # because the `Environment::LOGSTASH_HOME` doesn't exist in the context of the `logstash-core` gem.
23
23
  #
24
- # See issues https://github.com/elastic/logstash/issues/5361
24
+ # See issue https://github.com/elastic/logstash/issues/5361
25
25
  LogStash::SETTINGS.register(LogStash::Setting::String.new("path.settings", ::File.join(LogStash::Environment::LOGSTASH_HOME, "config")))
26
26
 
27
27
  # Node Settings
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ require "logstash/namespace"
3
+ require "logstash/util"
4
+
5
+ # This class exists to quietly wrap a password string so that, when printed or
6
+ # logged, you don't accidentally print the password itself.
7
+ class LogStash::Util::SafeURI
8
+ PASS_PLACEHOLDER = "xxxxxx".freeze
9
+
10
+ extend Forwardable
11
+
12
+ def_delegators :@uri, :coerce, :query=, :route_from, :port=, :default_port, :select, :normalize!, :absolute?, :registry=, :path, :password, :hostname, :merge, :normalize, :host, :component_ary, :userinfo=, :query, :set_opaque, :+, :merge!, :-, :password=, :parser, :port, :set_host, :set_path, :opaque=, :scheme, :fragment=, :set_query, :set_fragment, :userinfo, :hostname=, :set_port, :path=, :registry, :opaque, :route_to, :set_password, :hierarchical?, :set_user, :set_registry, :set_userinfo, :fragment, :component, :user=, :set_scheme, :absolute, :host=, :relative?, :scheme=, :user
13
+
14
+ attr_reader :uri
15
+
16
+ public
17
+ def initialize(arg)
18
+ @uri = case arg
19
+ when String
20
+ URI.parse(arg)
21
+ when URI
22
+ arg
23
+ else
24
+ raise ArgumentError, "Expected a string or URI, got a #{arg.class} creating a URL"
25
+ end
26
+ end
27
+
28
+ def to_s
29
+ sanitized.to_s
30
+ end
31
+
32
+ def inspect
33
+ sanitized.to_s
34
+ end
35
+
36
+ def sanitized
37
+ return uri unless uri.password # nothing to sanitize here!
38
+
39
+ safe = uri.clone
40
+ safe.password = PASS_PLACEHOLDER
41
+ safe
42
+ end
43
+
44
+ def ==(other)
45
+ other.is_a?(::LogStash::Util::SafeURI) ? @uri == other.uri : false
46
+ end
47
+ end
48
+
@@ -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-alpha4.snapshot1"
14
+ LOGSTASH_VERSION = "5.0.0-alpha4.snapshot2"
@@ -7,7 +7,7 @@ module LogStash
7
7
  class WebServer
8
8
  extend Forwardable
9
9
 
10
- attr_reader :logger, :status, :config, :options, :cli_options, :runner, :binder, :events, :http_host, :http_port, :http_environment
10
+ attr_reader :logger, :status, :config, :options, :cli_options, :runner, :binder, :events, :http_host, :http_port, :http_environment, :agent
11
11
 
12
12
  def_delegator :@runner, :stats
13
13
 
@@ -15,12 +15,13 @@ module LogStash
15
15
  DEFAULT_PORT = 9600.freeze
16
16
  DEFAULT_ENVIRONMENT = 'production'.freeze
17
17
 
18
- def initialize(logger, options={})
19
- @logger = logger
20
- @http_host = options[:http_host] || DEFAULT_HOST
21
- @http_port = options[:http_port] || DEFAULT_PORT
18
+ def initialize(logger, agent, options={})
19
+ @logger = logger
20
+ @agent = agent
21
+ @http_host = options[:http_host] || DEFAULT_HOST
22
+ @http_port = options[:http_port] || DEFAULT_PORT
22
23
  @http_environment = options[:http_environment] || DEFAULT_ENVIRONMENT
23
- @options = {}
24
+ @options = {}
24
25
  @cli_options = options.merge({ :rackup => ::File.join(::File.dirname(__FILE__), "api", "init.ru"),
25
26
  :binds => ["tcp://#{http_host}:#{http_port}"],
26
27
  :debug => logger.debug?,
@@ -37,7 +38,7 @@ module LogStash
37
38
 
38
39
  stop # Just in case
39
40
 
40
- app = LogStash::Api::RackApp.app(logger, http_environment)
41
+ app = LogStash::Api::RackApp.app(logger, agent, http_environment)
41
42
  @server = ::Puma::Server.new(app)
42
43
  @server.add_tcp_listener(http_host, http_port)
43
44
 
@@ -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.alpha4.snapshot1"
20
+ gem.add_runtime_dependency "logstash-core-event-java", "5.0.0.alpha4.snapshot2"
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)
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+ require_relative "../../spec_helper"
3
+ require "sinatra"
4
+ require "logstash/api/modules/plugins"
5
+ require "logstash/json"
6
+
7
+ describe LogStash::Api::Modules::Plugins do
8
+ include_context "api setup"
9
+
10
+ extend ResourceDSLMethods
11
+
12
+ before(:all) do
13
+ do_request { get "/" }
14
+ end
15
+
16
+ let(:payload) { LogStash::Json.load(last_response.body) }
17
+
18
+ describe "retrieving plugins" do
19
+ it "should return OK" do
20
+ expect(last_response).to be_ok
21
+ end
22
+
23
+ it "should return a list of plugins" do
24
+ expect(payload["plugins"]).to be_a(Array)
25
+ end
26
+
27
+ it "should return the total number of plugins" do
28
+ expect(payload["total"]).to be_a(Numeric)
29
+ end
30
+
31
+ end
32
+ end
@@ -5,12 +5,7 @@ require "logstash/api/modules/node"
5
5
  require "logstash/json"
6
6
 
7
7
  describe LogStash::Api::Modules::Node do
8
-
9
- include Rack::Test::Methods
10
-
11
- def app()
12
- described_class
13
- end
8
+ include_context "api setup"
14
9
 
15
10
  describe "#hot threads" do
16
11
 
@@ -39,7 +34,7 @@ describe LogStash::Api::Modules::Node do
39
34
  end
40
35
 
41
36
  it "should return information for <= # requested threads" do
42
- expect(payload["threads"].count).to be <= 5
37
+ expect(payload["hot_threads"]["threads"].count).to be <= 5
43
38
  end
44
39
  end
45
40
 
@@ -60,5 +55,44 @@ describe LogStash::Api::Modules::Node do
60
55
  end
61
56
  end
62
57
 
58
+ describe "Generic JSON testing" do
59
+ extend ResourceDSLMethods
60
+
61
+ root_structure = {
62
+ "pipeline" => {
63
+ "workers" => Numeric,
64
+ "batch_size" => Numeric,
65
+ "batch_delay" => Numeric
66
+ },
67
+ "os" => {
68
+ "name" => String,
69
+ "arch" => String,
70
+ "version" => String,
71
+ "available_processors" => Numeric
72
+ },
73
+ "jvm" => {
74
+ "pid" => Numeric,
75
+ "version" => String,
76
+ "vm_name" => String,
77
+ "vm_version" => String,
78
+ "vm_vendor" => String,
79
+ "start_time_in_millis" => Numeric,
80
+ "mem" => {
81
+ "heap_init_in_bytes" => Numeric,
82
+ "heap_max_in_bytes" => Numeric,
83
+ "non_heap_init_in_bytes" => Numeric,
84
+ "non_heap_max_in_bytes" => Numeric
85
+ }
86
+ },
87
+ "hot_threads"=> {
88
+ "hostname" => String,
89
+ "time" => String,
90
+ "busiest_threads" => Numeric,
91
+ "threads" => Array
92
+ }
93
+ }
94
+
95
+ test_api_and_resources(root_structure, :exclude_from_root => ["hot_threads"])
96
+ end
63
97
  end
64
98
  end
@@ -5,12 +5,9 @@ require "logstash/api/modules/node_stats"
5
5
  require "logstash/json"
6
6
 
7
7
  describe LogStash::Api::Modules::NodeStats do
8
- include Rack::Test::Methods
9
- extend ResourceDSLMethods
8
+ include_context "api setup"
10
9
 
11
- def app() # Used by Rack::Test::Methods
12
- described_class
13
- end
10
+ extend ResourceDSLMethods
14
11
 
15
12
  # DSL describing response structure
16
13
  root_structure = {
@@ -36,8 +33,36 @@ describe LogStash::Api::Modules::NodeStats do
36
33
  "total_in_millis"=>Numeric,
37
34
  "percent"=>Numeric
38
35
  }
36
+ },
37
+ "mem" => {
38
+ "heap_used_in_bytes" => Numeric,
39
+ "heap_used_percent" => Numeric,
40
+ "heap_committed_in_bytes" => Numeric,
41
+ "heap_max_in_bytes" => Numeric,
42
+ "non_heap_used_in_bytes" => Numeric,
43
+ "non_heap_committed_in_bytes" => Numeric,
44
+ "pools" => {
45
+ "survivor" => {
46
+ "peak_used_in_bytes" => Numeric,
47
+ "used_in_bytes" => Numeric,
48
+ "peak_max_in_bytes" => Numeric,
49
+ "max_in_bytes" => Numeric
50
+ },
51
+ "old" => {
52
+ "peak_used_in_bytes" => Numeric,
53
+ "used_in_bytes" => Numeric,
54
+ "peak_max_in_bytes" => Numeric,
55
+ "max_in_bytes" => Numeric
56
+ },
57
+ "young" => {
58
+ "peak_used_in_bytes" => Numeric,
59
+ "used_in_bytes" => Numeric,
60
+ "peak_max_in_bytes" => Numeric,
61
+ "max_in_bytes" => Numeric
62
+ }
63
+ }
39
64
  }
40
65
  }
41
-
66
+
42
67
  test_api_and_resources(root_structure)
43
68
  end
@@ -5,12 +5,7 @@ require "logstash/api/modules/plugins"
5
5
  require "logstash/json"
6
6
 
7
7
  describe LogStash::Api::Modules::Plugins do
8
-
9
- include Rack::Test::Methods
10
-
11
- def app()
12
- described_class
13
- end
8
+ include_context "api setup"
14
9
 
15
10
  before(:all) do
16
11
  get "/"
@@ -52,6 +47,5 @@ describe LogStash::Api::Modules::Plugins do
52
47
  expect(plugin["version"]).not_to be_empty
53
48
  end
54
49
  end
55
-
56
50
  end
57
51
  end
@@ -5,16 +5,11 @@ require "logstash/api/modules/root"
5
5
  require "logstash/json"
6
6
 
7
7
  describe LogStash::Api::Modules::Root do
8
-
9
- include Rack::Test::Methods
10
-
11
- def app()
12
- described_class
13
- end
8
+ include_context "api setup"
14
9
 
15
10
  it "should respond to root resource" do
16
11
  do_request { get "/" }
17
12
  expect(last_response).to be_ok
18
13
  end
19
-
20
14
  end
15
+
@@ -24,12 +24,16 @@ module ResourceDSLMethods
24
24
  expect(last_response).to be_ok
25
25
  end
26
26
 
27
- hash_to_mapping(expected).each do |path,klass|
28
- dotted = path.join(".")
27
+ hash_to_mapping(expected).each do |resource_path,klass|
28
+ dotted = resource_path.join(".")
29
29
 
30
- it "should set '#{dotted}' to be a '#{klass}'" do
31
- path_value = path.reduce(payload) {|acc,v| acc[v]}
32
- expect(path_value).to be_a(klass), "could not find '#{dotted}' in #{payload}"
30
+ it "should set '#{dotted}' at '#{path}' to be a '#{klass}'" do
31
+ expect(last_response).to be_ok # fail early if need be
32
+ resource_path_value = resource_path.reduce(payload) do |acc,v|
33
+ expect(acc.has_key?(v)).to eql(true), "Expected to find value '#{v}' in structure '#{acc}', but could not. Payload was '#{payload}'"
34
+ acc[v]
35
+ end
36
+ expect(resource_path_value).to be_a(klass), "could not find '#{dotted}' in #{payload}"
33
37
  end
34
38
  end
35
39
  end
@@ -37,8 +41,11 @@ module ResourceDSLMethods
37
41
  yield if block_given? # Add custom expectations
38
42
  end
39
43
 
40
- def test_api_and_resources(expected)
41
- test_api(expected, "/")
44
+ def test_api_and_resources(expected, xopts={})
45
+ xopts[:exclude_from_root] ||= []
46
+ root_expectation = expected.clone
47
+ xopts[:exclude_from_root].each {|k| root_expectation.delete(k)}
48
+ test_api(root_expectation, "/")
42
49
 
43
50
  expected.keys.each do |key|
44
51
  test_api({key => expected[key]}, "/#{key}")
@@ -1,13 +1,10 @@
1
1
  # encoding: utf-8
2
2
  API_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "logstash", "api"))
3
3
 
4
-
5
-
6
4
  require "logstash/devutils/rspec/spec_helper"
7
-
8
5
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
9
6
  require "lib/api/support/resource_dsl_methods"
10
-
7
+ require 'rspec/expectations'
11
8
  require "logstash/settings"
12
9
  require 'rack/test'
13
10
  require 'rspec'
@@ -20,10 +17,6 @@ end
20
17
 
21
18
  module LogStash
22
19
  class DummyAgent < Agent
23
- def fetch_config(settings)
24
- "input { generator {count => 0} } output { }"
25
- end
26
-
27
20
  def start_webserver; end
28
21
  def stop_webserver; end
29
22
  end
@@ -39,7 +32,8 @@ class LogStashRunner
39
32
  attr_reader :config_str, :agent, :pipeline_settings
40
33
 
41
34
  def initialize
42
- @config_str = "input { generator {count => 0} } output { }"
35
+ @config_str = "input { generator {count => 100 } } output { dummyoutput {} }"
36
+
43
37
  args = {
44
38
  "config.reload.automatic" => false,
45
39
  "metric.collect" => true,
@@ -57,31 +51,18 @@ class LogStashRunner
57
51
  end
58
52
 
59
53
  def start
54
+ # We start a pipeline that will generate a finite number of events
55
+ # before starting the expectations
60
56
  agent.register_pipeline("main", @settings)
61
- @runner = Thread.new(agent) do |_agent|
62
- _agent.execute
63
- end
64
-
65
- wait_until_ready
57
+ @agent_task = Stud::Task.new { agent.execute }
58
+ @agent_task.wait
66
59
  end
67
60
 
68
61
  def stop
69
62
  agent.shutdown
70
- Thread.kill(@runner)
71
- sleep 0.1 while !@runner.stop?
72
- end
73
-
74
- private
75
-
76
- def wait_until_ready
77
- # Wait until the service and pipeline have started
78
- while !(LogStash::Api::Service.instance.started? && agent.pipelines["main"].running?) do
79
- sleep 0.5
80
- end
81
63
  end
82
64
  end
83
65
 
84
-
85
66
  ##
86
67
  # Method used to wrap up a request in between of a running
87
68
  # pipeline, this makes the whole execution model easier and
@@ -95,30 +76,6 @@ def do_request(&block)
95
76
  ret_val
96
77
  end
97
78
 
98
- ##
99
- # Helper module that setups necessary mocks when doing the requests,
100
- # this could be just included in the test and the runner will be
101
- # started managed for all tests.
102
- ##
103
- module LogStash; module RSpec; module RunnerConfig
104
- def self.included(klass)
105
- klass.before(:all) do
106
- LogStashRunner.instance.start
107
- end
108
-
109
- klass.before(:each) do
110
- runner = LogStashRunner.instance
111
- allow(LogStash::Instrument::Collector.instance).to receive(:agent).and_return(runner.agent)
112
- end
113
-
114
- klass.after(:all) do
115
- LogStashRunner.instance.stop
116
- end
117
- end
118
- end; end; end
119
-
120
- require 'rspec/expectations'
121
-
122
79
  RSpec::Matchers.define :be_available? do
123
80
  match do |plugin|
124
81
  begin
@@ -129,3 +86,20 @@ RSpec::Matchers.define :be_available? do
129
86
  end
130
87
  end
131
88
  end
89
+
90
+ shared_context "api setup" do
91
+ before :all do
92
+ @runner = LogStashRunner.new
93
+ @runner.start
94
+ end
95
+
96
+ after :all do
97
+ @runner.stop
98
+ end
99
+
100
+ include Rack::Test::Methods
101
+
102
+ def app()
103
+ described_class.new(nil, @runner.agent)
104
+ end
105
+ end