logstash-core 5.0.0.alpha5.snapshot1-java → 5.0.0.alpha6.snapshot1-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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core/version.rb +1 -1
  3. data/lib/logstash/agent.rb +1 -1
  4. data/lib/logstash/api/commands/default_metadata.rb +1 -1
  5. data/lib/logstash/api/commands/hot_threads_reporter.rb +4 -7
  6. data/lib/logstash/api/commands/node.rb +5 -4
  7. data/lib/logstash/api/commands/stats.rb +8 -3
  8. data/lib/logstash/api/modules/base.rb +5 -0
  9. data/lib/logstash/api/modules/node.rb +1 -2
  10. data/lib/logstash/api/modules/node_stats.rb +1 -2
  11. data/lib/logstash/codecs/base.rb +29 -1
  12. data/lib/logstash/config/mixin.rb +1 -1
  13. data/lib/logstash/environment.rb +5 -5
  14. data/lib/logstash/filter_delegator.rb +4 -5
  15. data/lib/logstash/instrument/periodic_poller/jvm.rb +43 -10
  16. data/lib/logstash/output_delegator.rb +33 -168
  17. data/lib/logstash/output_delegator_strategies/legacy.rb +29 -0
  18. data/lib/logstash/output_delegator_strategies/shared.rb +20 -0
  19. data/lib/logstash/output_delegator_strategies/single.rb +23 -0
  20. data/lib/logstash/output_delegator_strategy_registry.rb +36 -0
  21. data/lib/logstash/outputs/base.rb +39 -26
  22. data/lib/logstash/patches/clamp.rb +6 -0
  23. data/lib/logstash/pipeline.rb +42 -14
  24. data/lib/logstash/pipeline_reporter.rb +2 -8
  25. data/lib/logstash/plugin.rb +6 -10
  26. data/lib/logstash/runner.rb +12 -9
  27. data/lib/logstash/settings.rb +124 -21
  28. data/lib/logstash/util/wrapped_synchronous_queue.rb +17 -1
  29. data/lib/logstash/version.rb +1 -1
  30. data/lib/logstash/webserver.rb +44 -33
  31. data/locales/en.yml +5 -1
  32. data/logstash-core.gemspec +2 -2
  33. data/spec/api/lib/api/node_spec.rb +62 -10
  34. data/spec/api/lib/api/node_stats_spec.rb +16 -3
  35. data/spec/api/lib/api/support/resource_dsl_methods.rb +11 -1
  36. data/spec/api/spec_helper.rb +1 -1
  37. data/spec/conditionals_spec.rb +12 -1
  38. data/spec/logstash/agent_spec.rb +3 -0
  39. data/spec/logstash/codecs/base_spec.rb +74 -0
  40. data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +37 -10
  41. data/spec/logstash/output_delegator_spec.rb +64 -89
  42. data/spec/logstash/outputs/base_spec.rb +91 -15
  43. data/spec/logstash/pipeline_reporter_spec.rb +1 -6
  44. data/spec/logstash/pipeline_spec.rb +20 -22
  45. data/spec/logstash/plugin_spec.rb +3 -3
  46. data/spec/logstash/runner_spec.rb +86 -3
  47. data/spec/logstash/settings/integer_spec.rb +20 -0
  48. data/spec/logstash/settings/numeric_spec.rb +28 -0
  49. data/spec/logstash/settings/port_range_spec.rb +93 -0
  50. data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +6 -0
  51. data/spec/logstash/webserver_spec.rb +95 -0
  52. metadata +20 -6
@@ -16,6 +16,18 @@ describe LogStash::Api::Modules::NodeStats do
16
16
  "count"=>Numeric,
17
17
  "peak_count"=>Numeric
18
18
  },
19
+ "gc" => {
20
+ "collectors" => {
21
+ "young" => {
22
+ "collection_count" => Numeric,
23
+ "collection_time_in_millis" => Numeric
24
+ },
25
+ "old" => {
26
+ "collection_count" => Numeric,
27
+ "collection_time_in_millis" => Numeric
28
+ }
29
+ }
30
+ },
19
31
  "mem" => {
20
32
  "heap_used_in_bytes" => Numeric,
21
33
  "heap_used_percent" => Numeric,
@@ -59,12 +71,13 @@ describe LogStash::Api::Modules::NodeStats do
59
71
  },
60
72
  "pipeline" => {
61
73
  "events" => {
74
+ "duration_in_millis" => Numeric,
62
75
  "in" => Numeric,
63
76
  "filtered" => Numeric,
64
77
  "out" => Numeric
65
- }
66
- }
78
+ }
79
+ }
67
80
  }
68
-
81
+
69
82
  test_api_and_resources(root_structure)
70
83
  end
@@ -1,3 +1,13 @@
1
+ # Ruby doesn't have common class for boolean,
2
+ # And to simplify the ResourceDSLMethods check it make sense to have it.
3
+ module Boolean; end
4
+ class TrueClass
5
+ include Boolean
6
+ end
7
+ class FalseClass
8
+ include Boolean
9
+ end
10
+
1
11
  module ResourceDSLMethods
2
12
  # Convert a nested hash to a mapping of key paths to expected classes
3
13
  def hash_to_mapping(h, path=[], mapping={})
@@ -35,7 +45,7 @@ module ResourceDSLMethods
35
45
  end
36
46
 
37
47
  it "should include the http address" do
38
- expect(payload["http_address"]).to eql("#{Socket.gethostname}:#{::LogStash::WebServer::DEFAULT_PORT}")
48
+ expect(payload["http_address"]).to eql("#{Socket.gethostname}:#{::LogStash::WebServer::DEFAULT_PORTS.first}")
39
49
  end
40
50
  end
41
51
 
@@ -19,7 +19,7 @@ end
19
19
  module LogStash
20
20
  class DummyAgent < Agent
21
21
  def start_webserver
22
- @webserver = Struct.new(:address).new("#{Socket.gethostname}:#{::LogStash::WebServer::DEFAULT_PORT}")
22
+ @webserver = Struct.new(:address).new("#{Socket.gethostname}:#{::LogStash::WebServer::DEFAULT_PORTS.first}")
23
23
  end
24
24
  def stop_webserver; end
25
25
  end
@@ -25,6 +25,17 @@ end
25
25
  describe "conditionals in output" do
26
26
  extend ConditionalFanciness
27
27
 
28
+ class DummyNullOutput < LogStash::Outputs::Base
29
+ def register
30
+ end
31
+ def multi_receive(events)
32
+ end
33
+ end
34
+
35
+ before do
36
+ LogStash::Registry.instance.register("logstash/outputs/dummynull", DummyNullOutput)
37
+ end
38
+
28
39
  describe "simple" do
29
40
  config <<-CONFIG
30
41
  input {
@@ -35,7 +46,7 @@ describe "conditionals in output" do
35
46
  }
36
47
  output {
37
48
  if [foo] == "bar" {
38
- stdout { }
49
+ dummynull { }
39
50
  }
40
51
  }
41
52
  CONFIG
@@ -392,7 +392,10 @@ describe LogStash::Agent do
392
392
 
393
393
  it "resets the metric collector" do
394
394
  # We know that the store has more events coming in.
395
+ i = 0
395
396
  while dummy_output.events.size <= new_config_generator_counter
397
+ i += 1
398
+ raise "Waiting too long!" if i > 20
396
399
  sleep(0.1)
397
400
  end
398
401
 
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ DATA_DOUBLE = "data".freeze
5
+
6
+ # use a dummy NOOP output to test Outputs::Base
7
+ class LogStash::Codecs::NOOPAsync < LogStash::Codecs::Base
8
+ attr_reader :last_result
9
+ config_name "noop_async"
10
+
11
+ def encode(event)
12
+ @last_result = @on_event.call(event, DATA_DOUBLE)
13
+ end
14
+ end
15
+
16
+ class LogStash::Codecs::NOOPSync < LogStash::Codecs::Base
17
+ attr_reader :last_result
18
+ config_name "noop_sync"
19
+
20
+ def encode_sync(event)
21
+ DATA_DOUBLE
22
+ end
23
+ end
24
+
25
+ class LogStash::Codecs::NOOPMulti < LogStash::Codecs::Base
26
+ attr_reader :last_result
27
+ config_name "noop_multi"
28
+
29
+ def encode_sync(event)
30
+ DATA_DOUBLE
31
+ end
32
+ end
33
+
34
+ describe LogStash::Codecs::Base do
35
+ let(:params) { {} }
36
+ subject(:instance) { klass.new(params.dup) }
37
+ let(:event) { double("event") }
38
+ let(:encoded_data) { DATA_DOUBLE }
39
+ let(:encoded_tuple) { [event, encoded_data] }
40
+
41
+ describe "encoding" do
42
+ shared_examples "encoder types" do |codec_class|
43
+ let(:klass) { codec_class }
44
+
45
+ describe "#{codec_class}" do
46
+ describe "multi_encode" do
47
+ it "should return an array of [event,data] tuples" do
48
+ expect(instance.multi_encode([event,event])).to eq([encoded_tuple, encoded_tuple])
49
+ end
50
+ end
51
+
52
+ describe "#encode" do
53
+ before do
54
+ @result = nil
55
+ instance.on_event do |event, data|
56
+ @result = [event, data]
57
+ end
58
+ instance.encode(event)
59
+ end
60
+
61
+ it "should yield the correct result" do
62
+ expect(@result).to eq(encoded_tuple)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ include_examples("encoder types", LogStash::Codecs::NOOPAsync)
69
+ include_examples("encoder types", LogStash::Codecs::NOOPSync)
70
+ include_examples("encoder types", LogStash::Codecs::NOOPMulti)
71
+ end
72
+ end
73
+
74
+
@@ -3,18 +3,41 @@ require "spec_helper"
3
3
  require "logstash/instrument/periodic_poller/jvm"
4
4
  require "logstash/instrument/collector"
5
5
 
6
+ describe LogStash::Instrument::PeriodicPoller::JVM::GarbageCollectorName do
7
+ subject { LogStash::Instrument::PeriodicPoller::JVM::GarbageCollectorName }
8
+
9
+ context "when the gc is of young type" do
10
+ LogStash::Instrument::PeriodicPoller::JVM::GarbageCollectorName::YOUNG_GC_NAMES.each do |name|
11
+ it "returns young for #{name}" do
12
+ expect(subject.get(name)).to eq(:young)
13
+ end
14
+ end
15
+ end
16
+
17
+ context "when the gc is of old type" do
18
+ LogStash::Instrument::PeriodicPoller::JVM::GarbageCollectorName::OLD_GC_NAMES.each do |name|
19
+ it "returns old for #{name}" do
20
+ expect(subject.get(name)).to eq(:old)
21
+ end
22
+ end
23
+ end
24
+
25
+ it "returns `nil` when we dont know the gc name" do
26
+ expect(subject.get("UNKNOWN GC")).to be_nil
27
+ end
28
+ end
29
+
6
30
  describe LogStash::Instrument::PeriodicPoller::JVM do
7
31
  let(:metric) { LogStash::Instrument::Metric.new(LogStash::Instrument::Collector.new) }
8
32
  let(:options) { {} }
9
33
  subject(:jvm) { described_class.new(metric, options) }
10
-
34
+
11
35
  it "should initialize cleanly" do
12
36
  expect { jvm }.not_to raise_error
13
37
  end
14
38
 
15
39
  describe "collections" do
16
40
  subject(:collection) { jvm.collect }
17
-
18
41
  it "should run cleanly" do
19
42
  expect { collection }.not_to raise_error
20
43
  end
@@ -22,21 +45,25 @@ describe LogStash::Instrument::PeriodicPoller::JVM do
22
45
  describe "metrics" do
23
46
  before(:each) { jvm.collect }
24
47
  let(:snapshot_store) { metric.collector.snapshot_metric.metric_store }
25
- subject(:jvm_metrics) { snapshot_store.get_shallow(:jvm, :process) }
48
+ subject(:jvm_metrics) { snapshot_store.get_shallow(:jvm) }
26
49
 
27
50
  # Make looking up metric paths easy when given varargs of keys
28
51
  # e.g. mval(:parent, :child)
29
52
  def mval(*metric_path)
30
53
  metric_path.reduce(jvm_metrics) {|acc,k| acc[k]}.value
31
- end
54
+ end
32
55
 
33
56
  [
34
- :max_file_descriptors,
35
- :open_file_descriptors,
36
- :peak_open_file_descriptors,
37
- [:mem, :total_virtual_in_bytes],
38
- [:cpu, :total_in_millis],
39
- [:cpu, :percent]
57
+ [:process, :max_file_descriptors],
58
+ [:process, :open_file_descriptors],
59
+ [:process, :peak_open_file_descriptors],
60
+ [:process, :mem, :total_virtual_in_bytes],
61
+ [:process, :cpu, :total_in_millis],
62
+ [:process, :cpu, :percent],
63
+ [:gc, :collectors, :young, :collection_count],
64
+ [:gc, :collectors, :young, :collection_time_in_millis],
65
+ [:gc, :collectors, :old, :collection_count],
66
+ [:gc, :collectors, :old, :collection_time_in_millis]
40
67
  ].each do |path|
41
68
  path = Array(path)
42
69
  it "should have a value for #{path} that is Numeric" do
@@ -5,26 +5,26 @@ require 'spec_helper'
5
5
  describe LogStash::OutputDelegator do
6
6
  let(:logger) { double("logger") }
7
7
  let(:events) { 7.times.map { LogStash::Event.new }}
8
- let(:default_worker_count) { 1 }
8
+ let(:plugin_args) { {"id" => "foo", "arg1" => "val1"} }
9
9
 
10
- subject { described_class.new(logger, out_klass, default_worker_count, LogStash::Instrument::NullMetric.new) }
10
+ subject { described_class.new(logger, out_klass, LogStash::Instrument::NullMetric.new, ::LogStash::OutputDelegatorStrategyRegistry.instance, plugin_args) }
11
11
 
12
12
  context "with a plain output plugin" do
13
13
  let(:out_klass) { double("output klass") }
14
14
  let(:out_inst) { double("output instance") }
15
-
15
+ let(:concurrency) { :single }
16
16
 
17
17
  before(:each) do
18
18
  allow(out_klass).to receive(:new).with(any_args).and_return(out_inst)
19
- allow(out_klass).to receive(:threadsafe?).and_return(false)
20
- allow(out_klass).to receive(:workers_not_supported?).and_return(false)
21
19
  allow(out_klass).to receive(:name).and_return("example")
20
+ allow(out_klass).to receive(:concurrency).with(any_args).and_return concurrency
22
21
  allow(out_klass).to receive(:config_name)
23
22
  allow(out_inst).to receive(:register)
24
23
  allow(out_inst).to receive(:multi_receive)
25
24
  allow(out_inst).to receive(:metric=).with(any_args)
26
25
  allow(out_inst).to receive(:id).and_return("a-simple-plugin")
27
- allow(out_inst).to receive(:plugin_unique_name).and_return("hello-123")
26
+
27
+ allow(subject.metric_events).to receive(:increment).with(any_args)
28
28
  allow(logger).to receive(:debug).with(any_args)
29
29
  end
30
30
 
@@ -43,109 +43,84 @@ describe LogStash::OutputDelegator do
43
43
  end
44
44
 
45
45
  it "should increment the number of events received" do
46
- expect(subject.events_received).to eql(events.length)
46
+ expect(subject.metric_events).to have_received(:increment).with(:in, events.length)
47
+ expect(subject.metric_events).to have_received(:increment).with(:out, events.length)
47
48
  end
48
49
  end
49
50
 
50
-
51
51
  describe "closing" do
52
52
  before do
53
53
  subject.register
54
54
  end
55
55
 
56
- it "should register all workers on register" do
56
+ it "should register the output plugin instance on register" do
57
57
  expect(out_inst).to have_received(:register)
58
58
  end
59
59
 
60
- it "should close all workers when closing" do
60
+ it "should close the output plugin instance when closing" do
61
61
  expect(out_inst).to receive(:do_close)
62
62
  subject.do_close
63
63
  end
64
64
  end
65
65
 
66
- describe "concurrency and worker support" do
67
- before do
68
- allow(out_inst).to receive(:id).and_return("a-simple-plugin")
69
- allow(out_inst).to receive(:metric=).with(any_args)
70
- allow(out_klass).to receive(:workers_not_supported?).and_return(false)
71
- end
72
-
73
- describe "non-threadsafe outputs that allow workers" do
74
- let(:default_worker_count) { 3 }
75
-
76
- before do
77
- allow(out_klass).to receive(:threadsafe?).and_return(false)
78
- subject.register
79
- end
80
-
81
- it "should instantiate multiple workers" do
82
- expect(subject.workers.length).to eql(default_worker_count)
83
- end
84
-
85
- it "should send received events to the worker" do
86
- expect(out_inst).to receive(:multi_receive).with(events)
87
- subject.multi_receive(events)
88
- end
66
+ describe "concurrency strategies" do
67
+ it "should have :single as the default" do
68
+ expect(subject.concurrency).to eq :single
89
69
  end
90
70
 
91
- describe "threadsafe outputs" do
92
- before do
93
- allow(out_klass).to receive(:threadsafe?).and_return(true)
94
- subject.register
95
- end
96
-
97
- it "should return true when threadsafe? is invoked" do
98
- expect(subject.threadsafe?).to eql(true)
99
- end
100
-
101
- it "should define a threadsafe_worker" do
102
- expect(subject.send(:threadsafe_worker)).to eql(out_inst)
103
- end
104
-
105
- it "should utilize threadsafe_multi_receive" do
106
- expect(subject.send(:threadsafe_worker)).to receive(:multi_receive).with(events)
107
- subject.multi_receive(events)
108
- end
109
-
110
- it "should not utilize the worker queue" do
111
- expect(subject.send(:worker_queue)).to be_nil
112
- end
113
-
114
- it "should send received events to the worker" do
115
- expect(out_inst).to receive(:multi_receive).with(events)
116
- subject.multi_receive(events)
117
- end
118
-
119
- it "should close all workers when closing" do
120
- expect(out_inst).to receive(:do_close)
121
- subject.do_close
71
+ [
72
+ [:shared, ::LogStash::OutputDelegatorStrategies::Shared],
73
+ [:single, ::LogStash::OutputDelegatorStrategies::Single],
74
+ [:legacy, ::LogStash::OutputDelegatorStrategies::Legacy],
75
+ ].each do |strategy_concurrency,klass|
76
+ context "with strategy #{strategy_concurrency}" do
77
+ let(:concurrency) { strategy_concurrency }
78
+
79
+ it "should find the correct concurrency type for the output" do
80
+ expect(subject.concurrency).to eq(strategy_concurrency)
81
+ end
82
+
83
+ it "should find the correct Strategy class for the worker" do
84
+ expect(subject.strategy).to be_a(klass)
85
+ end
86
+
87
+ it "should set the correct parameters on the instance" do
88
+ expect(out_klass).to have_received(:new).with(plugin_args)
89
+ end
90
+
91
+ [[:register], [:do_close], [:multi_receive, [[]] ] ].each do |method, args|
92
+ context "strategy objects" do
93
+ before do
94
+ allow(subject.strategy).to receive(method)
95
+ end
96
+
97
+ it "should delegate #{method} to the strategy" do
98
+ subject.send(method, *args)
99
+ if args
100
+ expect(subject.strategy).to have_received(method).with(*args)
101
+ else
102
+ expect(subject.strategy).to have_received(method).with(no_args)
103
+ end
104
+ end
105
+ end
106
+
107
+ context "strategy output instances" do
108
+ before do
109
+ allow(out_inst).to receive(method)
110
+ end
111
+
112
+ it "should delegate #{method} to the strategy" do
113
+ subject.send(method, *args)
114
+ if args
115
+ expect(out_inst).to have_received(method).with(*args)
116
+ else
117
+ expect(out_inst).to have_received(method).with(no_args)
118
+ end
119
+ end
120
+ end
121
+ end
122
122
  end
123
123
  end
124
124
  end
125
125
  end
126
-
127
- # This may seem suspiciously similar to the class in outputs/base_spec
128
- # but, in fact, we need a whole new class because using this even once
129
- # will immutably modify the base class
130
- class LogStash::Outputs::NOOPDelLegacyNoWorkers < ::LogStash::Outputs::Base
131
- LEGACY_WORKERS_NOT_SUPPORTED_REASON = "legacy reason"
132
-
133
- def register
134
- workers_not_supported(LEGACY_WORKERS_NOT_SUPPORTED_REASON)
135
- end
136
- end
137
-
138
- describe "legacy output workers_not_supported" do
139
- let(:default_worker_count) { 2 }
140
- let(:out_klass) { LogStash::Outputs::NOOPDelLegacyNoWorkers }
141
-
142
- before(:each) do
143
- allow(logger).to receive(:debug).with(any_args)
144
- end
145
-
146
- it "should only setup one worker" do
147
- subject.register
148
- expect(subject.worker_count).to eql(1)
149
- end
150
- end
151
126
  end