logstash-core 2.2.4.snapshot1

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.

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