logstash-core 5.0.2-java → 5.1.1.1-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.
- checksums.yaml +4 -4
- data/gemspec_jars.rb +9 -0
- data/lib/logstash-core/logstash-core.jar +0 -0
- data/lib/logstash-core/logstash-core.rb +22 -0
- data/lib/logstash-core/version.rb +1 -1
- data/lib/logstash-core_jars.rb +20 -0
- data/lib/logstash/agent.rb +65 -14
- data/lib/logstash/api/commands/default_metadata.rb +2 -1
- data/lib/logstash/api/commands/stats.rb +3 -2
- data/lib/logstash/config/file.rb +0 -1
- data/lib/logstash/config/loader.rb +1 -0
- data/lib/logstash/config/mixin.rb +2 -6
- data/lib/logstash/environment.rb +25 -2
- data/lib/logstash/event_dispatcher.rb +40 -0
- data/lib/logstash/filter_delegator.rb +1 -1
- data/lib/logstash/filters/base.rb +10 -2
- data/lib/logstash/instrument/metric_store.rb +0 -1
- data/lib/logstash/instrument/metric_type/base.rb +0 -1
- data/lib/logstash/instrument/namespaced_null_metric.rb +54 -0
- data/lib/logstash/instrument/null_metric.rb +55 -46
- data/lib/logstash/instrument/periodic_poller/jvm.rb +26 -3
- data/lib/logstash/instrument/periodic_poller/load_average.rb +47 -0
- data/lib/logstash/instrument/snapshot.rb +0 -1
- data/lib/logstash/java_integration.rb +0 -1
- data/lib/logstash/logging/logger.rb +37 -4
- data/lib/logstash/outputs/base.rb +1 -1
- data/lib/logstash/patches.rb +1 -0
- data/lib/logstash/patches/exception_to_json.rb +5 -0
- data/lib/logstash/pipeline.rb +50 -17
- data/lib/logstash/plugin.rb +14 -48
- data/lib/logstash/plugins/hooks_registry.rb +57 -0
- data/lib/logstash/plugins/registry.rb +208 -45
- data/lib/logstash/runner.rb +10 -5
- data/lib/logstash/settings.rb +101 -9
- data/lib/logstash/universal_plugin.rb +13 -0
- data/lib/logstash/util/byte_value.rb +60 -0
- data/lib/logstash/util/loggable.rb +14 -2
- data/lib/logstash/util/safe_uri.rb +1 -0
- data/lib/logstash/util/time_value.rb +70 -0
- data/lib/logstash/util/wrapped_acked_queue.rb +347 -0
- data/lib/logstash/util/wrapped_synchronous_queue.rb +17 -33
- data/lib/logstash/version.rb +1 -1
- data/locales/en.yml +1 -1
- data/logstash-core.gemspec +13 -18
- data/spec/api/lib/api/node_stats_spec.rb +3 -1
- data/spec/api/lib/api/support/resource_dsl_methods.rb +14 -6
- data/spec/api/spec_helper.rb +1 -0
- data/spec/conditionals_spec.rb +3 -2
- data/spec/logstash/agent_spec.rb +142 -62
- data/spec/logstash/environment_spec.rb +38 -0
- data/spec/logstash/event_dispatcher_spec.rb +76 -0
- data/spec/logstash/filter_delegator_spec.rb +2 -1
- data/spec/logstash/instrument/namespaced_null_metric_spec.rb +33 -0
- data/spec/logstash/instrument/null_metric_spec.rb +9 -5
- data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +40 -0
- data/spec/logstash/instrument/periodic_poller/load_average_spec.rb +91 -0
- data/spec/logstash/output_delegator_spec.rb +2 -1
- data/spec/logstash/patches_spec.rb +15 -4
- data/spec/logstash/pipeline_pq_file_spec.rb +131 -0
- data/spec/logstash/pipeline_spec.rb +21 -17
- data/spec/logstash/plugin_spec.rb +4 -16
- data/spec/logstash/plugins/hooks_registry_spec.rb +60 -0
- data/spec/logstash/plugins/registry_spec.rb +22 -14
- data/spec/logstash/settings/bytes_spec.rb +53 -0
- data/spec/logstash/settings/time_value_spec.rb +31 -0
- data/spec/logstash/settings/writable_directory_spec.rb +125 -0
- data/spec/logstash/settings_spec.rb +39 -0
- data/spec/logstash/util/byte_value_spec.rb +33 -0
- data/spec/logstash/util/time_value_spec.rb +59 -0
- data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +2 -2
- data/spec/logstash/webserver_spec.rb +4 -7
- data/spec/support/helpers.rb +8 -0
- data/spec/support/mocks_classes.rb +61 -31
- metadata +73 -20
- data/lib/jars.rb +0 -7
- data/lib/logstash/config/registry.rb +0 -13
- data/lib/logstash/inputs/metrics.rb +0 -47
- data/spec/logstash/inputs/metrics_spec.rb +0 -51
- data/vendor/jars/com/fasterxml/jackson/core/jackson-core/2.7.4/jackson-core-2.7.4.jar +0 -0
- data/vendor/jars/com/fasterxml/jackson/core/jackson-databind/2.7.4/jackson-databind-2.7.4.jar +0 -0
- data/vendor/jars/org/apache/logging/log4j/log4j-1.2-api/2.6.2/log4j-1.2-api-2.6.2.jar +0 -0
- data/vendor/jars/org/apache/logging/log4j/log4j-api/2.6.2/log4j-api-2.6.2.jar +0 -0
- data/vendor/jars/org/apache/logging/log4j/log4j-core/2.6.2/log4j-core-2.6.2.jar +0 -0
- data/vendor/jars/org/logstash/logstash-core/5.0.2/logstash-core-5.0.2.jar +0 -0
|
@@ -53,4 +53,42 @@ describe LogStash::Environment do
|
|
|
53
53
|
expect($LOAD_PATH).to include(path)
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
describe "OS detection" do
|
|
59
|
+
windows_host_os = %w(bccwin cygwin mingw mswin wince)
|
|
60
|
+
linux_host_os = %w(linux)
|
|
61
|
+
|
|
62
|
+
context "windows" do
|
|
63
|
+
windows_host_os.each do |host|
|
|
64
|
+
it "#{host} returns true" do
|
|
65
|
+
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return(host)
|
|
66
|
+
expect(LogStash::Environment.windows?).to be_truthy
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
linux_host_os.each do |host|
|
|
71
|
+
it "#{host} returns false" do
|
|
72
|
+
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return(host)
|
|
73
|
+
expect(LogStash::Environment.windows?).to be_falsey
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "Linux" do
|
|
79
|
+
windows_host_os.each do |host|
|
|
80
|
+
it "#{host} returns true" do
|
|
81
|
+
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return(host)
|
|
82
|
+
expect(LogStash::Environment.linux?).to be_falsey
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
linux_host_os.each do |host|
|
|
87
|
+
it "#{host} returns false" do
|
|
88
|
+
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return(host)
|
|
89
|
+
expect(LogStash::Environment.linux?).to be_truthy
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
56
94
|
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
require "logstash/event_dispatcher"
|
|
4
|
+
|
|
5
|
+
describe LogStash::EventDispatcher do
|
|
6
|
+
class DummyEmitter
|
|
7
|
+
attr_reader :dispatcher
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@dispatcher = LogStash::EventDispatcher.new(self)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def method_exists
|
|
14
|
+
dispatcher.fire(:method_exists)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def method_exists_with_arguments(argument1, argument2, argument3)
|
|
18
|
+
dispatcher.fire(:method_exists_with_arguments, argument1, argument2, argument3)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def method_do_not_exist
|
|
22
|
+
dispatcher.fire(:method_do_not_exist)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class CustomSpy
|
|
27
|
+
def method_exists
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def method_exists_with_arguments(argument1, argument2, argument3)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
let(:listener) { CustomSpy }
|
|
35
|
+
subject(:emitter) { DummyEmitter.new }
|
|
36
|
+
|
|
37
|
+
describe "Emits events" do
|
|
38
|
+
before do
|
|
39
|
+
emitter.dispatcher.add_listener(listener)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "when the method exist" do
|
|
43
|
+
it "calls the method without arguments" do
|
|
44
|
+
expect(listener).to receive(:method_exists).with(emitter)
|
|
45
|
+
emitter.method_exists
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "calls the method with arguments" do
|
|
49
|
+
expect(listener).to receive(:method_exists_with_arguments).with(emitter, 1, 2, 3)
|
|
50
|
+
emitter.method_exists_with_arguments(1, 2, 3)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context "when the method doesn't exist on the listener" do
|
|
55
|
+
it "should not raise an exception" do
|
|
56
|
+
expect { emitter.method_do_not_exist }.not_to raise_error
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "Configuring listeners" do
|
|
62
|
+
it "adds a listener to an emitter" do
|
|
63
|
+
expect(listener).to receive(:method_exists).with(emitter)
|
|
64
|
+
emitter.dispatcher.add_listener(listener)
|
|
65
|
+
emitter.method_exists
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "allows to remove a listner to an emitter" do
|
|
69
|
+
expect(listener).to receive(:method_exists).with(emitter).once
|
|
70
|
+
emitter.dispatcher.add_listener(listener)
|
|
71
|
+
emitter.method_exists
|
|
72
|
+
emitter.dispatcher.remove_listener(listener)
|
|
73
|
+
emitter.method_exists
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -10,7 +10,8 @@ describe LogStash::FilterDelegator do
|
|
|
10
10
|
let(:config) do
|
|
11
11
|
{ "host" => "127.0.0.1", "id" => filter_id }
|
|
12
12
|
end
|
|
13
|
-
let(:
|
|
13
|
+
let(:collector) { [] }
|
|
14
|
+
let(:metric) { LogStash::Instrument::NamespacedNullMetric.new(collector, :null) }
|
|
14
15
|
let(:events) { [LogStash::Event.new, LogStash::Event.new] }
|
|
15
16
|
|
|
16
17
|
before :each do
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require "logstash/instrument/namespaced_null_metric"
|
|
3
|
+
require "logstash/instrument/null_metric"
|
|
4
|
+
require_relative "../../support/matchers"
|
|
5
|
+
require "spec_helper"
|
|
6
|
+
|
|
7
|
+
describe LogStash::Instrument::NamespacedNullMetric do
|
|
8
|
+
let(:namespace) { :root }
|
|
9
|
+
let(:collector) { [] }
|
|
10
|
+
let(:metric) { LogStash::Instrument::NullMetric.new(collector) }
|
|
11
|
+
|
|
12
|
+
subject { described_class.new(metric, namespace) }
|
|
13
|
+
|
|
14
|
+
it "defines the same interface as `Metric`" do
|
|
15
|
+
expect(described_class).to implement_interface_of(LogStash::Instrument::NamespacedMetric)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "returns a TimedException when we call without a block" do
|
|
19
|
+
expect(subject.time(:duration_ms)).to be(LogStash::Instrument::NullMetric::NullTimedExecution)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "returns the value of the block" do
|
|
23
|
+
expect(subject.time(:duration_ms) { "hello" }).to eq("hello")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "its doesnt change the original `namespace` when creating a subnamespace" do
|
|
27
|
+
new_namespace = subject.namespace(:wally)
|
|
28
|
+
|
|
29
|
+
expect(subject.namespace_name).to eq([namespace])
|
|
30
|
+
expect(new_namespace.namespace_name).to eq([:root, :wally])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -2,18 +2,22 @@
|
|
|
2
2
|
require "logstash/instrument/null_metric"
|
|
3
3
|
require "logstash/instrument/namespaced_metric"
|
|
4
4
|
require_relative "../../support/shared_examples"
|
|
5
|
+
require_relative "../../support/matchers"
|
|
6
|
+
require "spec_helper"
|
|
5
7
|
|
|
6
8
|
describe LogStash::Instrument::NullMetric do
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
let(:key) { "test" }
|
|
11
|
+
let(:collector) { [] }
|
|
12
|
+
subject { LogStash::Instrument::NullMetric.new(collector) }
|
|
9
13
|
|
|
10
14
|
it "defines the same interface as `Metric`" do
|
|
11
|
-
expect(described_class).to implement_interface_of(LogStash::Instrument::
|
|
15
|
+
expect(described_class).to implement_interface_of(LogStash::Instrument::Metric)
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
describe "#namespace" do
|
|
15
|
-
it "return a
|
|
16
|
-
expect(subject.namespace(key)).to be_kind_of LogStash::Instrument::
|
|
19
|
+
it "return a NamespacedNullMetric" do
|
|
20
|
+
expect(subject.namespace(key)).to be_kind_of LogStash::Instrument::NamespacedNullMetric
|
|
17
21
|
end
|
|
18
22
|
end
|
|
19
23
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
require "spec_helper"
|
|
3
3
|
require "logstash/instrument/periodic_poller/jvm"
|
|
4
4
|
require "logstash/instrument/collector"
|
|
5
|
+
require "logstash/environment"
|
|
5
6
|
|
|
6
7
|
describe LogStash::Instrument::PeriodicPoller::JVM::GarbageCollectorName do
|
|
7
8
|
subject { LogStash::Instrument::PeriodicPoller::JVM::GarbageCollectorName }
|
|
@@ -27,6 +28,7 @@ describe LogStash::Instrument::PeriodicPoller::JVM::GarbageCollectorName do
|
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|
|
31
|
+
|
|
30
32
|
describe LogStash::Instrument::PeriodicPoller::JVM do
|
|
31
33
|
let(:metric) { LogStash::Instrument::Metric.new(LogStash::Instrument::Collector.new) }
|
|
32
34
|
let(:options) { {} }
|
|
@@ -36,6 +38,22 @@ describe LogStash::Instrument::PeriodicPoller::JVM do
|
|
|
36
38
|
expect { jvm }.not_to raise_error
|
|
37
39
|
end
|
|
38
40
|
|
|
41
|
+
describe "load average" do
|
|
42
|
+
context "on linux" do
|
|
43
|
+
context "when an exception occur reading the file" do
|
|
44
|
+
before do
|
|
45
|
+
expect(LogStash::Environment).to receive(:windows?).and_return(false)
|
|
46
|
+
expect(LogStash::Environment).to receive(:linux?).and_return(true)
|
|
47
|
+
expect(::File).to receive(:read).with("/proc/loadavg").and_raise("Didnt work out so well")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "doesn't raise an exception" do
|
|
51
|
+
expect { subject.collect }.not_to raise_error
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
39
57
|
describe "collections" do
|
|
40
58
|
subject(:collection) { jvm.collect }
|
|
41
59
|
it "should run cleanly" do
|
|
@@ -70,6 +88,28 @@ describe LogStash::Instrument::PeriodicPoller::JVM do
|
|
|
70
88
|
expect(mval(*path)).to be_a(Numeric)
|
|
71
89
|
end
|
|
72
90
|
end
|
|
91
|
+
|
|
92
|
+
context "real system" do
|
|
93
|
+
if LogStash::Environment.linux?
|
|
94
|
+
context "Linux" do
|
|
95
|
+
it "returns the load avg" do
|
|
96
|
+
expect(subject[:process][:cpu][:load_average].value).to include(:"1m" => a_kind_of(Numeric), :"5m" => a_kind_of(Numeric), :"15m" => a_kind_of(Numeric))
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
elsif LogStash::Environment.windows?
|
|
100
|
+
context "Window" do
|
|
101
|
+
it "returns nothing" do
|
|
102
|
+
expect(subject[:process][:cpu].has_key?(:load_average)).to be_falsey
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
else
|
|
106
|
+
context "Other" do
|
|
107
|
+
it "returns 1m only" do
|
|
108
|
+
expect(subject[:process][:cpu][:load_average].value).to include(:"1m" => a_kind_of(Numeric))
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
73
113
|
end
|
|
74
114
|
end
|
|
75
115
|
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require "logstash/instrument/periodic_poller/load_average"
|
|
3
|
+
describe LogStash::Instrument::PeriodicPoller::LoadAverage do
|
|
4
|
+
subject { described_class.create }
|
|
5
|
+
|
|
6
|
+
context "on mocked system" do
|
|
7
|
+
context "on Linux" do
|
|
8
|
+
before do
|
|
9
|
+
expect(LogStash::Environment).to receive(:windows?).and_return(false)
|
|
10
|
+
expect(LogStash::Environment).to receive(:linux?).and_return(true)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "when it can read the file" do
|
|
14
|
+
let(:proc_loadavg) { "0.00 0.01 0.05 3/180 29727" }
|
|
15
|
+
|
|
16
|
+
before do
|
|
17
|
+
expect(::File).to receive(:read).with("/proc/loadavg").and_return(proc_loadavg)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "return the 3 load average from `/proc/loadavg`" do
|
|
21
|
+
avg_1m, avg_5m, avg_15m = proc_loadavg.chomp.split(" ")
|
|
22
|
+
|
|
23
|
+
expect(subject.get).to include(:"1m" => avg_1m.to_f, :"5m" => avg_5m.to_f, :"15m" => avg_15m.to_f)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "on windows" do
|
|
29
|
+
before do
|
|
30
|
+
expect(LogStash::Environment).to receive(:windows?).and_return(true)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "Xreturns nil" do
|
|
34
|
+
expect(subject.get).to be_nil
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "on other" do
|
|
39
|
+
before do
|
|
40
|
+
expect(LogStash::Environment).to receive(:windows?).and_return(false)
|
|
41
|
+
expect(LogStash::Environment).to receive(:linux?).and_return(false)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "when 'OperatingSystemMXBean.getSystemLoadAverage' return something" do
|
|
45
|
+
let(:load_avg) { 5 }
|
|
46
|
+
|
|
47
|
+
before do
|
|
48
|
+
expect(ManagementFactory).to receive(:getOperatingSystemMXBean).and_return(double("OperatingSystemMXBean", :getSystemLoadAverage => load_avg))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "returns the value" do
|
|
52
|
+
expect(subject.get).to include(:"1m" => 5)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "when 'OperatingSystemMXBean.getSystemLoadAverage' doesn't return anything" do
|
|
57
|
+
before do
|
|
58
|
+
expect(ManagementFactory).to receive(:getOperatingSystemMXBean).and_return(double("OperatingSystemMXBean", :getSystemLoadAverage => nil))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "returns nothing" do
|
|
62
|
+
expect(subject.get).to be_nil
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Since we are running this on macos and linux I think it make sense to have real test
|
|
69
|
+
# insteadof only mock
|
|
70
|
+
context "real system" do
|
|
71
|
+
if LogStash::Environment.linux?
|
|
72
|
+
context "Linux" do
|
|
73
|
+
it "returns the load avg" do
|
|
74
|
+
expect(subject.get).to include(:"1m" => a_kind_of(Numeric), :"5m" => a_kind_of(Numeric), :"15m" => a_kind_of(Numeric))
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
elsif LogStash::Environment.windows?
|
|
78
|
+
context "window" do
|
|
79
|
+
it "returns nothing" do
|
|
80
|
+
expect(subject.get).to be_nil
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
else
|
|
84
|
+
context "Other" do
|
|
85
|
+
it "returns 1m only" do
|
|
86
|
+
expect(subject.get).to include(:"1m" => a_kind_of(Numeric))
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -6,7 +6,8 @@ describe LogStash::OutputDelegator do
|
|
|
6
6
|
let(:logger) { double("logger") }
|
|
7
7
|
let(:events) { 7.times.map { LogStash::Event.new }}
|
|
8
8
|
let(:plugin_args) { {"id" => "foo", "arg1" => "val1"} }
|
|
9
|
-
let(:
|
|
9
|
+
let(:collector) { [] }
|
|
10
|
+
let(:metric) { LogStash::Instrument::NamespacedNullMetric.new(collector, :null) }
|
|
10
11
|
|
|
11
12
|
subject { described_class.new(logger, out_klass, metric, ::LogStash::OutputDelegatorStrategyRegistry.instance, plugin_args) }
|
|
12
13
|
|
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
require "socket"
|
|
3
3
|
require "logstash/patches"
|
|
4
4
|
require "flores/pki"
|
|
5
|
+
require "logstash/json"
|
|
5
6
|
|
|
6
7
|
describe "OpenSSL defaults" do
|
|
7
8
|
subject { OpenSSL::SSL::SSLContext.new }
|
|
8
9
|
|
|
9
|
-
# OpenSSL::SSL::SSLContext#ciphers returns an array of
|
|
10
|
+
# OpenSSL::SSL::SSLContext#ciphers returns an array of
|
|
10
11
|
# [ [ ciphername, version, bits, alg_bits ], [ ... ], ... ]
|
|
11
|
-
|
|
12
|
+
|
|
12
13
|
# List of cipher names
|
|
13
14
|
let(:ciphers) { subject.ciphers.map(&:first) }
|
|
14
15
|
|
|
15
|
-
# List of cipher encryption bit strength.
|
|
16
|
+
# List of cipher encryption bit strength.
|
|
16
17
|
let(:encryption_bits) { subject.ciphers.map { |_, _, _, a| a } }
|
|
17
18
|
|
|
18
19
|
it "should not include any export ciphers" do
|
|
@@ -35,7 +36,7 @@ describe "OpenSSL defaults" do
|
|
|
35
36
|
# https://github.com/jordansissel/ruby-flores/blob/master/spec/flores/pki_integration_spec.rb
|
|
36
37
|
# since these helpers were created to fix this particular issue
|
|
37
38
|
let(:csr) { Flores::PKI::CertificateSigningRequest.new }
|
|
38
|
-
# Here, I use a 1024-bit key for faster tests.
|
|
39
|
+
# Here, I use a 1024-bit key for faster tests.
|
|
39
40
|
# Please do not use such small keys in production.
|
|
40
41
|
let(:key_bits) { 1024 }
|
|
41
42
|
let(:key) { OpenSSL::PKey::RSA.generate(key_bits, 65537) }
|
|
@@ -88,3 +89,13 @@ describe "OpenSSL defaults" do
|
|
|
88
89
|
end
|
|
89
90
|
end
|
|
90
91
|
end
|
|
92
|
+
|
|
93
|
+
describe "exceptions used json logging hashes" do
|
|
94
|
+
let(:exception) { ArgumentError.new("so you want an argument, huh?") }
|
|
95
|
+
let(:result) { [] }
|
|
96
|
+
|
|
97
|
+
it "should not raise errors" do
|
|
98
|
+
expect { result << LogStash::Json.dump({"error" => exception}) }.not_to raise_error
|
|
99
|
+
expect(result[0]).to match(/ArgumentError.*so you want an argument/)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require "spec_helper"
|
|
3
|
+
require "logstash/inputs/generator"
|
|
4
|
+
require "logstash/filters/multiline"
|
|
5
|
+
|
|
6
|
+
class PipelinePqFileOutput < LogStash::Outputs::Base
|
|
7
|
+
config_name "pipelinepqfileoutput"
|
|
8
|
+
milestone 2
|
|
9
|
+
|
|
10
|
+
attr_reader :num_closes, :event_count
|
|
11
|
+
|
|
12
|
+
def self.make_shared
|
|
13
|
+
@concurrency = :shared
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(params={})
|
|
17
|
+
super
|
|
18
|
+
@num_closes = 0
|
|
19
|
+
@event_count = 0
|
|
20
|
+
@mutex = Mutex.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def register
|
|
24
|
+
self.class.make_shared
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def receive(event)
|
|
28
|
+
@mutex.synchronize do
|
|
29
|
+
@event_count = @event_count.succ
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def close
|
|
34
|
+
@num_closes = 1
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe LogStash::Pipeline do
|
|
39
|
+
let(:pipeline_settings_obj) { LogStash::SETTINGS }
|
|
40
|
+
let(:pipeline_id) { "main" }
|
|
41
|
+
|
|
42
|
+
let(:multiline_id) { "my-multiline" }
|
|
43
|
+
let(:output_id) { "my-pipelinepqfileoutput" }
|
|
44
|
+
let(:generator_id) { "my-generator" }
|
|
45
|
+
let(:config) do
|
|
46
|
+
<<-EOS
|
|
47
|
+
input {
|
|
48
|
+
generator {
|
|
49
|
+
count => #{number_of_events}
|
|
50
|
+
id => "#{generator_id}"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
filter {
|
|
54
|
+
multiline {
|
|
55
|
+
id => "#{multiline_id}"
|
|
56
|
+
pattern => "hello"
|
|
57
|
+
what => next
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
output {
|
|
61
|
+
pipelinepqfileoutput {
|
|
62
|
+
id => "#{output_id}"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
EOS
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
let(:pipeline_settings) { { "queue.type" => queue_type, "pipeline.workers" => worker_thread_count, "pipeline.id" => pipeline_id} }
|
|
69
|
+
|
|
70
|
+
subject { described_class.new(config, pipeline_settings_obj, metric) }
|
|
71
|
+
|
|
72
|
+
let(:counting_output) { PipelinePqFileOutput.new({ "id" => output_id }) }
|
|
73
|
+
let(:metric_store) { subject.metric.collector.snapshot_metric.metric_store }
|
|
74
|
+
let(:metric) { LogStash::Instrument::Metric.new(LogStash::Instrument::Collector.new) }
|
|
75
|
+
let(:base_queue_path) { pipeline_settings_obj.get("path.queue") }
|
|
76
|
+
let(:this_queue_folder) { File.join(base_queue_path, SecureRandom.hex(8)) }
|
|
77
|
+
|
|
78
|
+
let(:worker_thread_count) { 8 } # 1 4 8
|
|
79
|
+
let(:number_of_events) { 100_000 }
|
|
80
|
+
let(:page_capacity) { 1 * 1024 * 512 } # 1 128
|
|
81
|
+
let(:max_bytes) { 1024 * 1024 * 1024 } # 1 gb
|
|
82
|
+
let(:queue_type) { "persisted" } # "memory" "memory_acked"
|
|
83
|
+
let(:times) { [] }
|
|
84
|
+
|
|
85
|
+
before :each do
|
|
86
|
+
FileUtils.mkdir_p(this_queue_folder)
|
|
87
|
+
|
|
88
|
+
pipeline_settings_obj.set("path.queue", this_queue_folder)
|
|
89
|
+
allow(PipelinePqFileOutput).to receive(:new).with(any_args).and_return(counting_output)
|
|
90
|
+
allow(LogStash::Plugin).to receive(:lookup).with("input", "generator").and_return(LogStash::Inputs::Generator)
|
|
91
|
+
allow(LogStash::Plugin).to receive(:lookup).with("codec", "plain").and_return(LogStash::Codecs::Plain)
|
|
92
|
+
allow(LogStash::Plugin).to receive(:lookup).with("filter", "multiline").and_return(LogStash::Filters::Multiline)
|
|
93
|
+
allow(LogStash::Plugin).to receive(:lookup).with("output", "pipelinepqfileoutput").and_return(PipelinePqFileOutput)
|
|
94
|
+
|
|
95
|
+
pipeline_workers_setting = LogStash::SETTINGS.get_setting("pipeline.workers")
|
|
96
|
+
allow(pipeline_workers_setting).to receive(:default).and_return(worker_thread_count)
|
|
97
|
+
pipeline_settings.each {|k, v| pipeline_settings_obj.set(k, v) }
|
|
98
|
+
pipeline_settings_obj.set("queue.page_capacity", page_capacity)
|
|
99
|
+
pipeline_settings_obj.set("queue.max_bytes", max_bytes)
|
|
100
|
+
Thread.new do
|
|
101
|
+
# make sure we have received all the generated events
|
|
102
|
+
while counting_output.event_count < number_of_events do
|
|
103
|
+
sleep 1
|
|
104
|
+
end
|
|
105
|
+
subject.shutdown
|
|
106
|
+
end
|
|
107
|
+
times.push(Time.now.to_f)
|
|
108
|
+
subject.run
|
|
109
|
+
times.unshift(Time.now.to_f - times.first)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
after :each do
|
|
113
|
+
# Dir.rm_rf(this_queue_folder)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
let(:collected_metric) { metric_store.get_with_path("stats/pipelines/") }
|
|
117
|
+
|
|
118
|
+
it "populates the pipelines core metrics" do
|
|
119
|
+
_metric = collected_metric[:stats][:pipelines][:main][:events]
|
|
120
|
+
expect(_metric[:duration_in_millis].value).not_to be_nil
|
|
121
|
+
expect(_metric[:in].value).to eq(number_of_events)
|
|
122
|
+
expect(_metric[:filtered].value).to eq(number_of_events)
|
|
123
|
+
expect(_metric[:out].value).to eq(number_of_events)
|
|
124
|
+
STDOUT.puts " queue.type: #{pipeline_settings_obj.get("queue.type")}"
|
|
125
|
+
STDOUT.puts " queue.page_capacity: #{pipeline_settings_obj.get("queue.page_capacity") / 1024}KB"
|
|
126
|
+
STDOUT.puts " queue.max_bytes: #{pipeline_settings_obj.get("queue.max_bytes") / 1024}KB"
|
|
127
|
+
STDOUT.puts " workers: #{worker_thread_count}"
|
|
128
|
+
STDOUT.puts " events: #{number_of_events}"
|
|
129
|
+
STDOUT.puts " took: #{times.first}s"
|
|
130
|
+
end
|
|
131
|
+
end
|