logstash-core 2.2.4.snapshot1

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 (83) hide show
  1. checksums.yaml +7 -0
  2. data/lib/logstash-core.rb +1 -0
  3. data/lib/logstash-core/logstash-core.rb +3 -0
  4. data/lib/logstash-core/version.rb +8 -0
  5. data/lib/logstash/agent.rb +391 -0
  6. data/lib/logstash/codecs/base.rb +50 -0
  7. data/lib/logstash/config/config_ast.rb +550 -0
  8. data/lib/logstash/config/cpu_core_strategy.rb +32 -0
  9. data/lib/logstash/config/defaults.rb +12 -0
  10. data/lib/logstash/config/file.rb +39 -0
  11. data/lib/logstash/config/grammar.rb +3503 -0
  12. data/lib/logstash/config/mixin.rb +518 -0
  13. data/lib/logstash/config/registry.rb +13 -0
  14. data/lib/logstash/environment.rb +98 -0
  15. data/lib/logstash/errors.rb +12 -0
  16. data/lib/logstash/filters/base.rb +205 -0
  17. data/lib/logstash/inputs/base.rb +116 -0
  18. data/lib/logstash/inputs/threadable.rb +18 -0
  19. data/lib/logstash/java_integration.rb +116 -0
  20. data/lib/logstash/json.rb +61 -0
  21. data/lib/logstash/logging.rb +91 -0
  22. data/lib/logstash/namespace.rb +13 -0
  23. data/lib/logstash/output_delegator.rb +172 -0
  24. data/lib/logstash/outputs/base.rb +91 -0
  25. data/lib/logstash/patches.rb +5 -0
  26. data/lib/logstash/patches/bugfix_jruby_2558.rb +51 -0
  27. data/lib/logstash/patches/cabin.rb +35 -0
  28. data/lib/logstash/patches/profile_require_calls.rb +47 -0
  29. data/lib/logstash/patches/rubygems.rb +38 -0
  30. data/lib/logstash/patches/stronger_openssl_defaults.rb +68 -0
  31. data/lib/logstash/pipeline.rb +499 -0
  32. data/lib/logstash/pipeline_reporter.rb +114 -0
  33. data/lib/logstash/plugin.rb +120 -0
  34. data/lib/logstash/program.rb +14 -0
  35. data/lib/logstash/runner.rb +124 -0
  36. data/lib/logstash/shutdown_watcher.rb +100 -0
  37. data/lib/logstash/util.rb +203 -0
  38. data/lib/logstash/util/buftok.rb +139 -0
  39. data/lib/logstash/util/charset.rb +35 -0
  40. data/lib/logstash/util/decorators.rb +52 -0
  41. data/lib/logstash/util/defaults_printer.rb +31 -0
  42. data/lib/logstash/util/filetools.rb +186 -0
  43. data/lib/logstash/util/java_version.rb +66 -0
  44. data/lib/logstash/util/password.rb +25 -0
  45. data/lib/logstash/util/plugin_version.rb +56 -0
  46. data/lib/logstash/util/prctl.rb +10 -0
  47. data/lib/logstash/util/retryable.rb +40 -0
  48. data/lib/logstash/util/socket_peer.rb +7 -0
  49. data/lib/logstash/util/unicode_trimmer.rb +81 -0
  50. data/lib/logstash/util/worker_threads_default_printer.rb +29 -0
  51. data/lib/logstash/util/wrapped_synchronous_queue.rb +41 -0
  52. data/lib/logstash/version.rb +14 -0
  53. data/locales/en.yml +204 -0
  54. data/logstash-core.gemspec +58 -0
  55. data/spec/conditionals_spec.rb +429 -0
  56. data/spec/logstash/agent_spec.rb +85 -0
  57. data/spec/logstash/config/config_ast_spec.rb +146 -0
  58. data/spec/logstash/config/cpu_core_strategy_spec.rb +123 -0
  59. data/spec/logstash/config/defaults_spec.rb +10 -0
  60. data/spec/logstash/config/mixin_spec.rb +158 -0
  61. data/spec/logstash/environment_spec.rb +56 -0
  62. data/spec/logstash/filters/base_spec.rb +251 -0
  63. data/spec/logstash/inputs/base_spec.rb +74 -0
  64. data/spec/logstash/java_integration_spec.rb +304 -0
  65. data/spec/logstash/json_spec.rb +96 -0
  66. data/spec/logstash/output_delegator_spec.rb +144 -0
  67. data/spec/logstash/outputs/base_spec.rb +40 -0
  68. data/spec/logstash/patches_spec.rb +90 -0
  69. data/spec/logstash/pipeline_reporter_spec.rb +85 -0
  70. data/spec/logstash/pipeline_spec.rb +455 -0
  71. data/spec/logstash/plugin_spec.rb +169 -0
  72. data/spec/logstash/runner_spec.rb +68 -0
  73. data/spec/logstash/shutdown_watcher_spec.rb +113 -0
  74. data/spec/logstash/util/buftok_spec.rb +31 -0
  75. data/spec/logstash/util/charset_spec.rb +74 -0
  76. data/spec/logstash/util/defaults_printer_spec.rb +50 -0
  77. data/spec/logstash/util/java_version_spec.rb +79 -0
  78. data/spec/logstash/util/plugin_version_spec.rb +64 -0
  79. data/spec/logstash/util/unicode_trimmer_spec.rb +55 -0
  80. data/spec/logstash/util/worker_threads_default_printer_spec.rb +45 -0
  81. data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +28 -0
  82. data/spec/logstash/util_spec.rb +35 -0
  83. metadata +364 -0
@@ -0,0 +1,169 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/plugin"
4
+
5
+ describe LogStash::Plugin do
6
+ it "should fail lookup on inexisting type" do
7
+ expect_any_instance_of(Cabin::Channel).to receive(:debug).once
8
+ expect { LogStash::Plugin.lookup("badbadtype", "badname") }.to raise_error(LogStash::PluginLoadingError)
9
+ end
10
+
11
+ it "should fail lookup on inexisting name" do
12
+ expect_any_instance_of(Cabin::Channel).to receive(:debug).once
13
+ expect { LogStash::Plugin.lookup("filter", "badname") }.to raise_error(LogStash::PluginLoadingError)
14
+ end
15
+
16
+ it "should fail on bad plugin class" do
17
+ LogStash::Filters::BadSuperClass = Class.new
18
+ expect { LogStash::Plugin.lookup("filter", "bad_super_class") }.to raise_error(LogStash::PluginLoadingError)
19
+ end
20
+
21
+ it "should fail on missing config_name method" do
22
+ LogStash::Filters::MissingConfigName = Class.new(LogStash::Filters::Base)
23
+ expect { LogStash::Plugin.lookup("filter", "missing_config_name") }.to raise_error(LogStash::PluginLoadingError)
24
+ end
25
+
26
+ it "should lookup an already defined plugin class" do
27
+ class LogStash::Filters::LadyGaga < LogStash::Filters::Base
28
+ config_name "lady_gaga"
29
+ end
30
+ expect(LogStash::Plugin.lookup("filter", "lady_gaga")).to eq(LogStash::Filters::LadyGaga)
31
+ end
32
+
33
+ describe "#inspect" do
34
+ class LogStash::Filters::MyTestFilter < LogStash::Filters::Base
35
+ config_name "param1"
36
+ config :num, :validate => :number, :default => 20
37
+ config :str, :validate => :string, :default => "test"
38
+ end
39
+ subject { LogStash::Filters::MyTestFilter.new("num" => 1, "str" => "hello") }
40
+
41
+ it "should print the class of the filter" do
42
+ expect(subject.inspect).to match(/^<LogStash::Filters::MyTestFilter/)
43
+ end
44
+ it "should list config options and values" do
45
+ expect(subject.inspect).to match(/num=>1, str=>"hello"/)
46
+ end
47
+ end
48
+
49
+ context "when validating the plugin version" do
50
+ let(:plugin_name) { 'logstash-filter-stromae' }
51
+ subject do
52
+ Class.new(LogStash::Filters::Base) do
53
+ config_name 'stromae'
54
+ end
55
+ end
56
+
57
+ it "doesn't warn the user if the version is superior or equal to 1.0.0" do
58
+ allow(Gem::Specification).to receive(:find_by_name)
59
+ .with(plugin_name)
60
+ .and_return(double(:version => Gem::Version.new('1.0.0')))
61
+
62
+ expect_any_instance_of(Cabin::Channel).not_to receive(:info)
63
+ subject.validate({})
64
+ end
65
+
66
+ it 'warns the user if the plugin version is between 0.9.x and 1.0.0' do
67
+ allow(Gem::Specification).to receive(:find_by_name)
68
+ .with(plugin_name)
69
+ .and_return(double(:version => Gem::Version.new('0.9.1')))
70
+
71
+ expect_any_instance_of(Cabin::Channel).to receive(:info)
72
+ .with(/Using version 0.9.x/)
73
+
74
+ subject.validate({})
75
+ end
76
+
77
+ it 'warns the user if the plugin version is inferior to 0.9.x' do
78
+ allow(Gem::Specification).to receive(:find_by_name)
79
+ .with(plugin_name)
80
+ .and_return(double(:version => Gem::Version.new('0.1.1')))
81
+
82
+ expect_any_instance_of(Cabin::Channel).to receive(:info)
83
+ .with(/Using version 0.1.x/)
84
+ subject.validate({})
85
+ end
86
+
87
+ it "doesnt show the version notice more than once" do
88
+ one_notice = Class.new(LogStash::Filters::Base) do
89
+ config_name "stromae"
90
+ end
91
+
92
+ allow(Gem::Specification).to receive(:find_by_name)
93
+ .with(plugin_name)
94
+ .and_return(double(:version => Gem::Version.new('0.1.1')))
95
+
96
+ expect_any_instance_of(Cabin::Channel).to receive(:info)
97
+ .once
98
+ .with(/Using version 0.1.x/)
99
+
100
+ one_notice.validate({})
101
+ one_notice.validate({})
102
+ end
103
+
104
+ it "warns the user if we can't find a defined version" do
105
+ expect_any_instance_of(Cabin::Channel).to receive(:warn)
106
+ .once
107
+ .with(/plugin doesn't have a version/)
108
+
109
+ subject.validate({})
110
+ end
111
+
112
+
113
+ it 'logs a warning if the plugin use the milestone option' do
114
+ expect_any_instance_of(Cabin::Channel).to receive(:warn)
115
+ .with(/stromae plugin is using the 'milestone' method/)
116
+
117
+ class LogStash::Filters::Stromae < LogStash::Filters::Base
118
+ config_name "stromae"
119
+ milestone 2
120
+ end
121
+ end
122
+ end
123
+
124
+ describe "subclass initialize" do
125
+ let(:args) { Hash.new }
126
+
127
+ [
128
+ StromaeCodec = Class.new(LogStash::Codecs::Base) do
129
+ config_name "stromae"
130
+ config :foo_tag, :validate => :string, :default => "bar"
131
+ end,
132
+ StromaeFilter = Class.new(LogStash::Filters::Base) do
133
+ config_name "stromae"
134
+ config :foo_tag, :validate => :string, :default => "bar"
135
+ end,
136
+ StromaeInput = Class.new(LogStash::Inputs::Base) do
137
+ config_name "stromae"
138
+ config :foo_tag, :validate => :string, :default => "bar"
139
+ end,
140
+ StromaeOutput = Class.new(LogStash::Outputs::Base) do
141
+ config_name "stromae"
142
+ config :foo_tag, :validate => :string, :default => "bar"
143
+ end
144
+ ].each do |klass|
145
+
146
+ it "subclass #{klass.name} does not modify params" do
147
+ klass.new(args)
148
+ expect(args).to be_empty
149
+ end
150
+ end
151
+
152
+ context "codec initialization" do
153
+
154
+ class LogStash::Codecs::Noop < LogStash::Codecs::Base
155
+ config_name "noop"
156
+
157
+ config :format, :validate => :string
158
+ def register; end
159
+ end
160
+
161
+ it "should only register once" do
162
+ args = { "codec" => LogStash::Codecs::Noop.new("format" => ".") }
163
+ expect_any_instance_of(LogStash::Codecs::Noop).to receive(:register).once
164
+ LogStash::Plugin.new(args)
165
+ end
166
+
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/runner"
4
+ require "stud/task"
5
+ require "stud/trap"
6
+
7
+ class NullRunner
8
+ def run(args); end
9
+ end
10
+
11
+ describe LogStash::Runner do
12
+
13
+ context "argument parsing" do
14
+ it "should run agent" do
15
+ expect(Stud::Task).to receive(:new).once.and_return(nil)
16
+ args = ["agent", "-e", ""]
17
+ expect(subject.run(args)).to eq(nil)
18
+ end
19
+
20
+ it "should run agent help" do
21
+ expect(subject).to receive(:show_help).once.and_return(nil)
22
+ args = ["agent", "-h"]
23
+ expect(subject.run(args).wait).to eq(0)
24
+ end
25
+
26
+ it "should show help with no arguments" do
27
+ expect($stderr).to receive(:puts).once.and_return("No command given")
28
+ expect($stderr).to receive(:puts).once
29
+ args = []
30
+ expect(subject.run(args).wait).to eq(1)
31
+ end
32
+
33
+ it "should show help for unknown commands" do
34
+ expect($stderr).to receive(:puts).once.and_return("No such command welp")
35
+ expect($stderr).to receive(:puts).once
36
+ args = ["welp"]
37
+ expect(subject.run(args).wait).to eq(1)
38
+ end
39
+ end
40
+
41
+ describe "pipeline settings" do
42
+ let(:pipeline_string) { "input { stdin {} } output { stdout {} }" }
43
+ let(:base_pipeline_settings) { { :pipeline_id => "base", :debug_config => false } }
44
+ let(:pipeline) { double("pipeline") }
45
+
46
+ before(:each) do
47
+ task = Stud::Task.new { 1 }
48
+ allow(pipeline).to receive(:run).and_return(task)
49
+ end
50
+
51
+ context "when pipeline workers is not defined by the user" do
52
+ it "should not pass the value to the pipeline" do
53
+ expect(LogStash::Pipeline).to receive(:new).with(pipeline_string, base_pipeline_settings).and_return(pipeline)
54
+ args = ["agent", "-e", pipeline_string]
55
+ subject.run(args).wait
56
+ end
57
+ end
58
+
59
+ context "when pipeline workers is defined by the user" do
60
+ it "should pass the value to the pipeline" do
61
+ base_pipeline_settings[:pipeline_workers] = 2
62
+ expect(LogStash::Pipeline).to receive(:new).with(pipeline_string, base_pipeline_settings).and_return(pipeline)
63
+ args = ["agent", "-w", "2", "-e", pipeline_string]
64
+ subject.run(args).wait
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,113 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/shutdown_watcher"
4
+
5
+ describe LogStash::ShutdownWatcher do
6
+
7
+ let(:check_every) { 0.01 }
8
+ let(:check_threshold) { 100 }
9
+ subject { LogStash::ShutdownWatcher.new(pipeline, check_every) }
10
+ let(:pipeline) { double("pipeline") }
11
+ let(:reporter) { double("reporter") }
12
+ let(:reporter_snapshot) { double("reporter snapshot") }
13
+ report_count = 0
14
+
15
+ before :each do
16
+ allow(pipeline).to receive(:reporter).and_return(reporter)
17
+ allow(reporter).to receive(:snapshot).and_return(reporter_snapshot)
18
+ allow(reporter_snapshot).to receive(:o_simple_hash).and_return({})
19
+
20
+ allow(subject).to receive(:pipeline_report_snapshot).and_wrap_original do |m, *args|
21
+ report_count += 1
22
+ m.call(*args)
23
+ end
24
+ end
25
+
26
+ after :each do
27
+ report_count = 0
28
+ end
29
+
30
+ context "when pipeline is stalled" do
31
+ let(:increasing_count) { (1..5000).to_a }
32
+ before :each do
33
+ allow(reporter_snapshot).to receive(:inflight_count).and_return(*increasing_count)
34
+ allow(reporter_snapshot).to receive(:stalling_threads) { { } }
35
+ end
36
+
37
+ describe ".unsafe_shutdown = true" do
38
+ let(:abort_threshold) { subject.abort_threshold }
39
+ let(:report_every) { subject.report_every }
40
+
41
+ before :each do
42
+ subject.class.unsafe_shutdown = true
43
+ end
44
+
45
+ it "should force the shutdown" do
46
+ expect(subject).to receive(:force_exit).once
47
+ subject.start
48
+ end
49
+
50
+ it "should do exactly \"abort_threshold\" stall checks" do
51
+ allow(subject).to receive(:force_exit)
52
+ expect(subject).to receive(:shutdown_stalled?).exactly(abort_threshold).times.and_call_original
53
+ subject.start
54
+ end
55
+
56
+ it "should do exactly \"abort_threshold\"*\"report_every\" stall checks" do
57
+ allow(subject).to receive(:force_exit)
58
+ expect(subject).to receive(:pipeline_report_snapshot).exactly(abort_threshold*report_every).times.and_call_original
59
+ subject.start
60
+ end
61
+ end
62
+
63
+ describe ".unsafe_shutdown = false" do
64
+
65
+ before :each do
66
+ subject.class.unsafe_shutdown = false
67
+ end
68
+
69
+ it "shouldn't force the shutdown" do
70
+ expect(subject).to_not receive(:force_exit)
71
+ thread = Thread.new(subject) {|subject| subject.start }
72
+ sleep 0.1 until report_count > check_threshold
73
+ thread.kill
74
+ end
75
+ end
76
+ end
77
+
78
+ context "when pipeline is not stalled" do
79
+ let(:decreasing_count) { (1..5000).to_a.reverse }
80
+ before :each do
81
+ allow(reporter_snapshot).to receive(:inflight_count).and_return(*decreasing_count)
82
+ allow(reporter_snapshot).to receive(:stalling_threads) { { } }
83
+ end
84
+
85
+ describe ".unsafe_shutdown = true" do
86
+
87
+ before :each do
88
+ subject.class.unsafe_shutdown = true
89
+ end
90
+
91
+ it "should force the shutdown" do
92
+ expect(subject).to_not receive(:force_exit)
93
+ thread = Thread.new(subject) {|subject| subject.start }
94
+ sleep 0.1 until report_count > check_threshold
95
+ thread.kill
96
+ end
97
+ end
98
+
99
+ describe ".unsafe_shutdown = false" do
100
+
101
+ before :each do
102
+ subject.class.unsafe_shutdown = false
103
+ end
104
+
105
+ it "shouldn't force the shutdown" do
106
+ expect(subject).to_not receive(:force_exit)
107
+ thread = Thread.new(subject) {|subject| subject.start }
108
+ sleep 0.1 until report_count > check_threshold
109
+ thread.kill
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/util/buftok"
4
+
5
+ describe FileWatch::BufferedTokenizer do
6
+
7
+ subject { FileWatch::BufferedTokenizer.new }
8
+
9
+ it "should tokenize a single token" do
10
+ expect(subject.extract("foo\n")).to eq(["foo"])
11
+ end
12
+
13
+ it "should merge multiple token" do
14
+ expect(subject.extract("foo")).to eq([])
15
+ expect(subject.extract("bar\n")).to eq(["foobar"])
16
+ end
17
+
18
+ it "should tokenize multiple token" do
19
+ expect(subject.extract("foo\nbar\n")).to eq(["foo", "bar"])
20
+ end
21
+
22
+ it "should ignore empty payload" do
23
+ expect(subject.extract("")).to eq([])
24
+ expect(subject.extract("foo\nbar")).to eq(["foo"])
25
+ end
26
+
27
+ it "should tokenize empty payload with newline" do
28
+ expect(subject.extract("\n")).to eq([""])
29
+ expect(subject.extract("\n\n\n")).to eq(["", "", ""])
30
+ end
31
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/util/charset"
4
+
5
+ describe LogStash::Util::Charset do
6
+ let(:logger) { double("logger") }
7
+
8
+ context "with valid UTF-8 source encoding" do
9
+ subject {LogStash::Util::Charset.new("UTF-8")}
10
+
11
+ it "should return untouched data" do
12
+ ["foobar", "κόσμε"].each do |data|
13
+ expect(data.encoding.name).to eq("UTF-8")
14
+ expect(subject.convert(data)).to eq(data)
15
+ expect(subject.convert(data).encoding.name).to eq("UTF-8")
16
+ end
17
+ end
18
+ end
19
+
20
+ context "with invalid UTF-8 source encoding" do
21
+ subject do
22
+ LogStash::Util::Charset.new("UTF-8").tap do |charset|
23
+ charset.logger = logger
24
+ end
25
+ end
26
+
27
+ it "should escape invalid sequences" do
28
+ ["foo \xED\xB9\x81\xC3", "bar \xAD"].each do |data|
29
+ expect(data.encoding.name).to eq("UTF-8")
30
+ expect(data.valid_encoding?).to eq(false)
31
+ expect(logger).to receive(:warn).exactly(2).times
32
+ #logger.should_receive(:warn).twice
33
+ expect(subject.convert(data)).to eq(data.inspect[1..-2])
34
+ expect(subject.convert(data).encoding.name).to eq("UTF-8")
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ context "with valid non UTF-8 source encoding" do
41
+ subject {LogStash::Util::Charset.new("ISO-8859-1")}
42
+
43
+ it "should encode to UTF-8" do
44
+ samples = [
45
+ ["foobar", "foobar"],
46
+ ["\xE0 Montr\xE9al", "à Montréal"],
47
+ ]
48
+ samples.map{|(a, b)| [a.force_encoding("ISO-8859-1"), b]}.each do |(a, b)|
49
+ expect(a.encoding.name).to eq("ISO-8859-1")
50
+ expect(b.encoding.name).to eq("UTF-8")
51
+ expect(a.valid_encoding?).to eq(true)
52
+ expect(subject.convert(a).encoding.name).to eq("UTF-8")
53
+ expect(subject.convert(a)).to eq(b)
54
+ end
55
+ end
56
+ end
57
+
58
+ context "with invalid non UTF-8 source encoding" do
59
+ subject {LogStash::Util::Charset.new("ASCII-8BIT")}
60
+
61
+ it "should encode to UTF-8 and replace invalid chars" do
62
+ samples = [
63
+ ["\xE0 Montr\xE9al", "� Montr�al"],
64
+ ["\xCE\xBA\xCF\x8C\xCF\x83\xCE\xBC\xCE\xB5", "����������"],
65
+ ]
66
+ samples.map{|(a, b)| [a.force_encoding("ASCII-8BIT"), b]}.each do |(a, b)|
67
+ expect(a.encoding.name).to eq("ASCII-8BIT")
68
+ expect(b.encoding.name).to eq("UTF-8")
69
+ expect(subject.convert(a).encoding.name).to eq("UTF-8")
70
+ expect(subject.convert(a)).to eq(b)
71
+ end
72
+ end
73
+ end
74
+ end