logstash-core 2.4.1-java → 5.0.0.alpha1-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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core/version.rb +1 -1
  3. data/lib/logstash/agent.rb +124 -411
  4. data/lib/logstash/api/init.ru +31 -0
  5. data/lib/logstash/api/lib/app.rb +40 -0
  6. data/lib/logstash/api/lib/app/command.rb +29 -0
  7. data/lib/logstash/api/lib/app/command_factory.rb +29 -0
  8. data/lib/logstash/api/lib/app/commands/stats/events_command.rb +13 -0
  9. data/lib/logstash/api/lib/app/commands/stats/hotthreads_command.rb +120 -0
  10. data/lib/logstash/api/lib/app/commands/stats/memory_command.rb +25 -0
  11. data/lib/logstash/api/lib/app/commands/system/basicinfo_command.rb +15 -0
  12. data/lib/logstash/api/lib/app/commands/system/plugins_command.rb +28 -0
  13. data/lib/logstash/api/lib/app/modules/node.rb +25 -0
  14. data/lib/logstash/api/lib/app/modules/node_stats.rb +51 -0
  15. data/lib/logstash/api/lib/app/modules/plugins.rb +15 -0
  16. data/lib/logstash/api/lib/app/modules/stats.rb +21 -0
  17. data/lib/logstash/api/lib/app/root.rb +13 -0
  18. data/lib/logstash/api/lib/app/service.rb +61 -0
  19. data/lib/logstash/api/lib/app/stats.rb +56 -0
  20. data/lib/logstash/api/lib/helpers/app_helpers.rb +23 -0
  21. data/lib/logstash/codecs/base.rb +1 -29
  22. data/lib/logstash/config/config_ast.rb +18 -31
  23. data/lib/logstash/config/loader.rb +3 -5
  24. data/lib/logstash/config/mixin.rb +25 -64
  25. data/lib/logstash/filter_delegator.rb +65 -0
  26. data/lib/logstash/inputs/base.rb +1 -1
  27. data/lib/logstash/inputs/metrics.rb +47 -0
  28. data/lib/logstash/instrument/collector.rb +109 -0
  29. data/lib/logstash/instrument/metric.rb +102 -0
  30. data/lib/logstash/instrument/metric_store.rb +228 -0
  31. data/lib/logstash/instrument/metric_type.rb +24 -0
  32. data/lib/logstash/instrument/metric_type/base.rb +35 -0
  33. data/lib/logstash/instrument/metric_type/counter.rb +29 -0
  34. data/lib/logstash/instrument/metric_type/gauge.rb +22 -0
  35. data/lib/logstash/instrument/metric_type/mean.rb +33 -0
  36. data/lib/logstash/instrument/namespaced_metric.rb +54 -0
  37. data/lib/logstash/instrument/null_metric.rb +4 -3
  38. data/lib/logstash/instrument/periodic_poller/base.rb +57 -0
  39. data/lib/logstash/instrument/periodic_poller/jvm.rb +92 -0
  40. data/lib/logstash/instrument/periodic_poller/os.rb +13 -0
  41. data/lib/logstash/instrument/periodic_poller/periodic_poller_observer.rb +19 -0
  42. data/lib/logstash/instrument/periodic_pollers.rb +26 -0
  43. data/lib/logstash/instrument/snapshot.rb +16 -0
  44. data/lib/logstash/json.rb +2 -3
  45. data/lib/logstash/namespace.rb +1 -0
  46. data/lib/logstash/output_delegator.rb +16 -3
  47. data/lib/logstash/outputs/base.rb +1 -32
  48. data/lib/logstash/pipeline.rb +67 -8
  49. data/lib/logstash/plugin.rb +57 -19
  50. data/lib/logstash/runner.rb +348 -84
  51. data/lib/logstash/util.rb +9 -0
  52. data/lib/logstash/util/duration_formatter.rb +15 -0
  53. data/lib/logstash/util/java_version.rb +2 -4
  54. data/lib/logstash/util/loggable.rb +29 -0
  55. data/lib/logstash/version.rb +1 -1
  56. data/lib/logstash/webserver.rb +98 -0
  57. data/locales/en.yml +42 -24
  58. data/logstash-core.gemspec +9 -6
  59. data/spec/api/lib/api/node_spec.rb +64 -0
  60. data/spec/api/lib/api/node_stats_spec.rb +68 -0
  61. data/spec/api/lib/api/plugins_spec.rb +57 -0
  62. data/spec/api/lib/api/root_spec.rb +20 -0
  63. data/spec/api/lib/api/stats_spec.rb +19 -0
  64. data/spec/api/lib/commands/events_spec.rb +17 -0
  65. data/spec/api/lib/commands/jvm_spec.rb +45 -0
  66. data/spec/api/spec_helper.rb +128 -0
  67. data/spec/logstash/agent_spec.rb +62 -169
  68. data/spec/logstash/config/config_ast_spec.rb +2 -47
  69. data/spec/logstash/config/mixin_spec.rb +0 -157
  70. data/spec/logstash/filter_delegator_spec.rb +143 -0
  71. data/spec/logstash/inputs/metrics_spec.rb +52 -0
  72. data/spec/logstash/instrument/collector_spec.rb +49 -0
  73. data/spec/logstash/instrument/metric_spec.rb +110 -0
  74. data/spec/logstash/instrument/metric_store_spec.rb +163 -0
  75. data/spec/logstash/instrument/metric_type/counter_spec.rb +40 -0
  76. data/spec/logstash/instrument/metric_type/gauge_spec.rb +40 -0
  77. data/spec/logstash/instrument/namespaced_metric_spec.rb +25 -0
  78. data/spec/logstash/instrument/null_metric_spec.rb +9 -51
  79. data/spec/logstash/json_spec.rb +14 -0
  80. data/spec/logstash/output_delegator_spec.rb +6 -3
  81. data/spec/logstash/outputs/base_spec.rb +0 -107
  82. data/spec/logstash/pipeline_spec.rb +204 -33
  83. data/spec/logstash/plugin_spec.rb +80 -15
  84. data/spec/logstash/runner_spec.rb +134 -38
  85. data/spec/logstash/shutdown_watcher_spec.rb +0 -1
  86. data/spec/logstash/util/duration_formatter_spec.rb +11 -0
  87. data/spec/logstash/util/java_version_spec.rb +10 -2
  88. data/spec/logstash/util_spec.rb +28 -0
  89. data/spec/support/matchers.rb +30 -0
  90. metadata +154 -20
  91. data/lib/logstash/logging/json.rb +0 -21
  92. data/lib/logstash/special_agent.rb +0 -8
  93. data/lib/logstash/util/safe_uri.rb +0 -50
  94. data/spec/logstash/codecs/base_spec.rb +0 -74
  95. data/spec/static/i18n_spec.rb +0 -25
@@ -144,49 +144,6 @@ describe LogStashConfigParser do
144
144
  end
145
145
  end
146
146
 
147
- context "when using two plugin sections of the same type" do
148
- let(:pipeline_klass) do
149
- Class.new do
150
- def initialize(config)
151
- grammar = LogStashConfigParser.new
152
- @config = grammar.parse(config)
153
- @code = @config.compile
154
- eval(@code)
155
- end
156
- def plugin(*args);end
157
- end
158
- end
159
- context "(filters)" do
160
- let(:config_string) {
161
- "input { generator { } }
162
- filter { filter1 { } }
163
- filter { filter1 { } }
164
- output { output1 { } }"
165
- }
166
-
167
-
168
- it "should create a pipeline with both sections" do
169
- generated_objects = pipeline_klass.new(config_string).instance_variable_get("@generated_objects")
170
- filters = generated_objects.keys.map(&:to_s).select {|obj_name| obj_name.match(/^filter.+?_\d+$/) }
171
- expect(filters.size).to eq(2)
172
- end
173
- end
174
-
175
- context "(filters)" do
176
- let(:config_string) {
177
- "input { generator { } }
178
- output { output1 { } }
179
- output { output1 { } }"
180
- }
181
-
182
-
183
- it "should create a pipeline with both sections" do
184
- generated_objects = pipeline_klass.new(config_string).instance_variable_get("@generated_objects")
185
- outputs = generated_objects.keys.map(&:to_s).select {|obj_name| obj_name.match(/^output.+?_\d+$/) }
186
- expect(outputs.size).to eq(2)
187
- end
188
- end
189
- end
190
147
  context "when creating two instances of the same configuration" do
191
148
 
192
149
  let(:config_string) {
@@ -212,12 +169,10 @@ describe LogStashConfigParser do
212
169
  end
213
170
 
214
171
  describe "generated conditional functionals" do
215
- it "should be created per instance" do
172
+ it "should be defined at instance level" do
216
173
  instance_1 = pipeline_klass.new(config_string)
217
174
  instance_2 = pipeline_klass.new(config_string)
218
- generated_method_1 = instance_1.instance_variable_get("@generated_objects")[:cond_func_1]
219
- generated_method_2 = instance_2.instance_variable_get("@generated_objects")[:cond_func_1]
220
- expect(generated_method_1).to_not be(generated_method_2)
175
+ expect(instance_1.method(:cond_func_1).owner).to_not be(instance_2.method(:cond_func_1).owner)
221
176
  end
222
177
  end
223
178
  end
@@ -68,74 +68,6 @@ describe LogStash::Config::Mixin do
68
68
  end
69
69
  end
70
70
 
71
- context "when validating lists of items" do
72
- let(:klass) do
73
- Class.new(LogStash::Filters::Base) do
74
- config_name "multiuri"
75
- config :uris, :validate => :uri, :list => true
76
- config :strings, :validate => :string, :list => true
77
- config :required_strings, :validate => :string, :list => true, :required => true
78
- end
79
- end
80
-
81
- let(:uris) { ["http://example.net/1", "http://example.net/2"] }
82
- let(:safe_uris) { uris.map {|str| ::LogStash::Util::SafeURI.new(str) } }
83
- let(:strings) { ["I am a", "modern major general"] }
84
- let(:required_strings) { ["required", "strings"] }
85
-
86
- subject { klass.new("uris" => uris, "strings" => strings, "required_strings" => required_strings) }
87
-
88
- it "a URI list should return an array of URIs" do
89
- expect(subject.uris).to match_array(safe_uris)
90
- end
91
-
92
- it "a string list should return an array of strings" do
93
- expect(subject.strings).to match_array(strings)
94
- end
95
-
96
- context "with a scalar value" do
97
- let(:strings) { "foo" }
98
-
99
- it "should return the scalar value as a single element array" do
100
- expect(subject.strings).to match_array([strings])
101
- end
102
- end
103
-
104
- context "with an empty list" do
105
- let(:strings) { [] }
106
-
107
- it "should return nil" do
108
- expect(subject.strings).to be_nil
109
- end
110
- end
111
-
112
- describe "with required => true" do
113
- context "and a single element" do
114
- let(:required_strings) { ["foo"] }
115
-
116
- it "should return the single value" do
117
- expect(subject.required_strings).to eql(required_strings)
118
- end
119
- end
120
-
121
- context "with an empty list" do
122
- let (:required_strings) { [] }
123
-
124
- it "should raise a configuration error" do
125
- expect { subject.required_strings }.to raise_error(LogStash::ConfigurationError)
126
- end
127
- end
128
-
129
- context "with no value specified" do
130
- let (:required_strings) { nil }
131
-
132
- it "should raise a configuration error" do
133
- expect { subject.required_strings }.to raise_error(LogStash::ConfigurationError)
134
- end
135
- end
136
- end
137
- end
138
-
139
71
  context "when validating :password" do
140
72
  let(:klass) do
141
73
  Class.new(LogStash::Filters::Base) do
@@ -170,95 +102,6 @@ describe LogStash::Config::Mixin do
170
102
  end
171
103
  end
172
104
 
173
- context "when validating :uri" do
174
- let(:klass) do
175
- Class.new(LogStash::Filters::Base) do
176
- config_name "fakeuri"
177
- config :uri, :validate => :uri
178
- end
179
- end
180
-
181
- shared_examples("safe URI") do |options|
182
- options ||= {}
183
-
184
- subject { klass.new("uri" => uri_str) }
185
-
186
- it "should be a SafeURI object" do
187
- expect(subject.uri).to(be_a(LogStash::Util::SafeURI))
188
- end
189
-
190
- it "should correctly copy URI types" do
191
- clone = subject.class.new(subject.params)
192
- expect(clone.uri.to_s).to eql(uri_hidden)
193
- end
194
-
195
- it "should make the real URI object availale under #uri" do
196
- expect(subject.uri.uri).to be_a(::URI)
197
- end
198
-
199
- it "should obfuscate original_params" do
200
- expect(subject.original_params['uri']).to(be_a(LogStash::Util::SafeURI))
201
- end
202
-
203
- if !options[:exclude_password_specs]
204
- describe "passwords" do
205
- it "should make password values hidden with #to_s" do
206
- expect(subject.uri.to_s).to eql(uri_hidden)
207
- end
208
-
209
- it "should make password values hidden with #inspect" do
210
- expect(subject.uri.inspect).to eql(uri_hidden)
211
- end
212
- end
213
- end
214
-
215
- context "attributes" do
216
- [:scheme, :user, :password, :hostname, :path].each do |attr|
217
- it "should make #{attr} available" do
218
- expect(subject.uri.send(attr)).to eql(self.send(attr))
219
- end
220
- end
221
- end
222
- end
223
-
224
- context "with a host:port combination" do
225
- let(:scheme) { nil }
226
- let(:user) { nil }
227
- let(:password) { nil }
228
- let(:hostname) { "myhostname" }
229
- let(:port) { 1234 }
230
- let(:path) { "" }
231
- let(:uri_str) { "#{hostname}:#{port}" }
232
- let(:uri_hidden) { "//#{hostname}:#{port}" }
233
-
234
- include_examples("safe URI", :exclude_password_specs => true)
235
- end
236
-
237
- context "with a username / password" do
238
- let(:scheme) { "myscheme" }
239
- let(:user) { "myuser" }
240
- let(:password) { "fancypants" }
241
- let(:hostname) { "myhostname" }
242
- let(:path) { "/my/path" }
243
- let(:uri_str) { "#{scheme}://#{user}:#{password}@#{hostname}#{path}" }
244
- let(:uri_hidden) { "#{scheme}://#{user}:#{LogStash::Util::SafeURI::PASS_PLACEHOLDER}@#{hostname}#{path}" }
245
-
246
- include_examples("safe URI")
247
- end
248
-
249
- context "without a username / password" do
250
- let(:scheme) { "myscheme" }
251
- let(:user) { nil }
252
- let(:password) { nil }
253
- let(:hostname) { "myhostname" }
254
- let(:path) { "/my/path" }
255
- let(:uri_str) { "#{scheme}://#{hostname}#{path}" }
256
- let(:uri_hidden) { "#{scheme}://#{hostname}#{path}" }
257
-
258
- include_examples("safe URI")
259
- end
260
- end
261
-
262
105
  describe "obsolete settings" do
263
106
  let(:plugin_class) do
264
107
  Class.new(LogStash::Inputs::Base) do
@@ -0,0 +1,143 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/filter_delegator"
4
+ require "logstash/instrument/null_metric"
5
+ require "logstash/event"
6
+
7
+ describe LogStash::FilterDelegator do
8
+ let(:logger) { double(:logger) }
9
+ let(:filter_id) { "my-filter" }
10
+ let(:config) do
11
+ { "host" => "127.0.0.1", "id" => filter_id }
12
+ end
13
+ let(:metric) { LogStash::Instrument::NullMetric.new }
14
+ let(:events) { [LogStash::Event.new, LogStash::Event.new] }
15
+
16
+ before :each do
17
+ allow(metric).to receive(:namespace).with(anything).and_return(metric)
18
+ end
19
+
20
+ let(:plugin_klass) do
21
+ Class.new(LogStash::Filters::Base) do
22
+ config_name "super_plugin"
23
+ config :host, :validate => :string
24
+ def register; end
25
+ end
26
+ end
27
+
28
+ subject { described_class.new(logger, plugin_klass, metric, config) }
29
+
30
+ it "create a plugin with the passed options" do
31
+ expect(plugin_klass).to receive(:new).with(config).and_return(plugin_klass.new(config))
32
+ described_class.new(logger, plugin_klass, metric, config)
33
+ end
34
+
35
+ context "when the plugin support flush" do
36
+ let(:plugin_klass) do
37
+ Class.new(LogStash::Filters::Base) do
38
+ config_name "super_plugin"
39
+ config :host, :validate => :string
40
+ def register; end
41
+ def flush(options = {}); @events ; end
42
+ def filter(event)
43
+ @events ||= []
44
+ @events << event
45
+ event.cancel
46
+ end
47
+ end
48
+ end
49
+
50
+ it "defines a flush method" do
51
+ expect(subject.respond_to?(:flush)).to be_truthy
52
+ end
53
+
54
+ context "when the flush return events" do
55
+ it "increments the out" do
56
+ subject.multi_filter([LogStash::Event.new])
57
+ expect(metric).to receive(:increment).with(:out, 1)
58
+ subject.flush({})
59
+ end
60
+ end
61
+
62
+ context "when the flush doesn't return anything" do
63
+ it "doesnt increment the out" do
64
+ expect(metric).not_to receive(:increment)
65
+ subject.flush({})
66
+ end
67
+ end
68
+
69
+ context "when the filter buffer events" do
70
+ it "doesn't increment out" do
71
+ expect(metric).to receive(:increment).with(:in, events.size)
72
+ expect(metric).not_to receive(:increment)
73
+
74
+ subject.multi_filter(events)
75
+ end
76
+ end
77
+
78
+ context "when the fitler create more events" do
79
+ let(:plugin_klass) do
80
+ Class.new(LogStash::Filters::Base) do
81
+ config_name "super_plugin"
82
+ config :host, :validate => :string
83
+ def register; end
84
+ def flush(options = {}); @events ; end
85
+
86
+ # naive split filter implementation
87
+ def filter(event)
88
+ event.cancel
89
+ 2.times { yield LogStash::Event.new }
90
+ end
91
+ end
92
+ end
93
+
94
+ it "increments the in/out of the metric" do
95
+ expect(metric).to receive(:increment).with(:in, events.size)
96
+ expect(metric).to receive(:increment).with(:out, events.size * 2)
97
+
98
+ subject.multi_filter(events)
99
+ end
100
+ end
101
+ end
102
+
103
+ context "when the plugin doesnt support flush" do
104
+ let(:plugin_klass) do
105
+ Class.new(LogStash::Filters::Base) do
106
+ config_name "super_plugin"
107
+ config :host, :validate => :string
108
+ def register; end
109
+ def filter(event)
110
+ event
111
+ end
112
+ end
113
+ end
114
+
115
+ it "doesnt define a flush method" do
116
+ expect(subject.respond_to?(:flush)).to be_falsey
117
+ end
118
+
119
+ it "increments the in/out of the metric" do
120
+ expect(metric).to receive(:increment).with(:in, events.size)
121
+ expect(metric).to receive(:increment).with(:out, events.size)
122
+
123
+ subject.multi_filter(events)
124
+ end
125
+ end
126
+
127
+ context "#config_name" do
128
+ it "proxy the config_name to the class method" do
129
+ expect(subject.config_name).to eq("super_plugin")
130
+ end
131
+ end
132
+
133
+ context "delegate methods to the original plugin" do
134
+ # I am not testing the behavior of these methods
135
+ # this is done in the plugin tests. I just want to make sure
136
+ # the proxy delegates the methods.
137
+ LogStash::FilterDelegator::DELEGATED_METHODS.each do |method|
138
+ it "delegate method: `#{method}` to the filter" do
139
+ expect(subject.respond_to?(method))
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/metrics"
3
+ require "spec_helper"
4
+
5
+ describe LogStash::Inputs::Metrics do
6
+ before :each do
7
+ LogStash::Instrument::Collector.instance.clear
8
+ end
9
+
10
+ let(:queue) { [] }
11
+
12
+ describe "#run" do
13
+ it "should register itself to the collector observer" do
14
+ expect(LogStash::Instrument::Collector.instance).to receive(:add_observer).with(subject)
15
+ t = Thread.new { subject.run(queue) }
16
+ sleep(0.1) # give a bit of time to the thread to start
17
+ subject.stop
18
+ end
19
+ end
20
+
21
+ describe "#update" do
22
+ let(:namespaces) { [:root, :base] }
23
+ let(:key) { :foo }
24
+ let(:metric_store) { LogStash::Instrument::MetricStore.new }
25
+
26
+ it "should fill up the queue with received events" do
27
+ Thread.new { subject.run(queue) }
28
+ sleep(0.1)
29
+ subject.stop
30
+
31
+ metric_store.fetch_or_store(namespaces, key, LogStash::Instrument::MetricType::Counter.new(namespaces, key))
32
+ subject.update(LogStash::Instrument::Snapshot.new(metric_store))
33
+ expect(queue.count).to eq(1)
34
+ end
35
+ end
36
+
37
+ describe "#stop" do
38
+ it "should remove itself from the the collector observer" do
39
+ expect(LogStash::Instrument::Collector.instance).to receive(:delete_observer).with(subject)
40
+ t = Thread.new { subject.run(queue) }
41
+ sleep(0.1) # give a bit of time to the thread to start
42
+ subject.stop
43
+ end
44
+
45
+ it "should unblock the input" do
46
+ t = Thread.new { subject.run(queue) }
47
+ sleep(0.1) # give a bit of time to the thread to start
48
+ subject.do_stop
49
+ wait_for { t.status }.to be_falsey
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ require "logstash/instrument/collector"
3
+ require "spec_helper"
4
+
5
+ describe LogStash::Instrument::Collector do
6
+ subject { LogStash::Instrument::Collector.instance }
7
+ describe "#push" do
8
+ let(:namespaces_path) { [:root, :pipelines, :pipelines01] }
9
+ let(:key) { :my_key }
10
+
11
+ context "when the `MetricType` exist" do
12
+ it "store the metric of type `counter`" do
13
+ subject.push(namespaces_path, key, :counter, :increment)
14
+ end
15
+ end
16
+
17
+ context "when the `MetricType` doesn't exist" do
18
+ let(:wrong_type) { :donotexist }
19
+
20
+ it "logs an error but dont crash" do
21
+ expect(subject.logger).to receive(:error)
22
+ .with("Collector: Cannot create concrete class for this metric type",
23
+ hash_including({ :type => wrong_type, :namespaces_path => namespaces_path }))
24
+
25
+ subject.push(namespaces_path, key, wrong_type, :increment)
26
+ end
27
+ end
28
+
29
+ context "when there is a conflict with the metric key" do
30
+ let(:conflicting_namespaces) { [namespaces_path, key].flatten }
31
+
32
+ it "logs an error but dont crash" do
33
+ subject.push(namespaces_path, key, :counter, :increment)
34
+
35
+ expect(subject.logger).to receive(:error)
36
+ .with("Collector: Cannot record metric",
37
+ hash_including({ :exception => instance_of(LogStash::Instrument::MetricStore::NamespacesExpectedError) }))
38
+
39
+ subject.push(conflicting_namespaces, :random_key, :counter, :increment)
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "#snapshot_metric" do
45
+ it "return a `LogStash::Instrument::MetricStore`" do
46
+ expect(subject.snapshot_metric).to be_kind_of(LogStash::Instrument::Snapshot)
47
+ end
48
+ end
49
+ end