Skip to content

Commit 5c51db2

Browse files
authored
Merge pull request #15 from yaauie/fix-recovery-from-webserver-crashes-etc
Improve malformed-input handling, restarting, and crash-recovery
2 parents 17c8a2e + 0b26beb commit 5c51db2

File tree

4 files changed

+64
-5
lines changed

4 files changed

+64
-5
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 3.0.6
2+
- Improve malformed-input handling by using updated FTW
3+
- Improve webserver crash recovery
4+
- Properly support plugin stopping & reloading
5+
16
## 3.0.5
27
- Update gemspec summary
38

lib/logstash/inputs/github.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ def run(output_queue)
4242
response.body = "Accepted!"
4343
end
4444
@server.run
45+
rescue Exception => original_exception
46+
# If our server crashes, it may not have cleaned up after itself;
47+
# since `FTW::WebServer#stop` is idempotent, make one last attempt
48+
# before propagating the original exception.
49+
@server && @server.stop rescue logger.error("Error while stopping FTW::WebServer", exception: $!.message, backtrace: $!.backtrace)
50+
51+
raise original_exception
4552
end # def run
4653

4754
def build_event_from_request(body, headers)
@@ -69,8 +76,8 @@ def verify_signature(event,body)
6976
return is_valid
7077
end
7178

72-
def close
73-
@server.stop
74-
end # def close
79+
def stop
80+
@server && @server.stop
81+
end # def stop
7582

7683
end # class LogStash::Inputs::Github

logstash-input-github.gemspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Gem::Specification.new do |s|
22

33
s.name = 'logstash-input-github'
4-
s.version = '3.0.5'
4+
s.version = '3.0.6'
55
s.licenses = ['Apache License (2.0)']
66
s.summary = "Reads events from a GitHub webhook"
77
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
2424

2525
s.add_runtime_dependency 'addressable'
2626
s.add_runtime_dependency 'logstash-codec-plain'
27-
s.add_runtime_dependency 'ftw', '~> 0.0.42'
27+
s.add_runtime_dependency 'ftw', '~> 0.0.48'
2828

2929
s.add_development_dependency 'logstash-devutils'
3030
end

spec/inputs/github_spec.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,51 @@
5555
end
5656

5757
end
58+
59+
describe 'graceful shutdown' do
60+
context 'when underlying webserver crashes' do
61+
62+
# Stubbing out our FTW::WebServer allows us to force it to raise an exception when we try to run it.
63+
let(:mock_webserver_class) { double('FTW::WebServer::class').as_null_object }
64+
let(:mock_webserver) { double('FTW::WebServer').as_null_object }
65+
before(:each) do
66+
stub_const('FTW::WebServer', mock_webserver_class)
67+
allow(mock_webserver_class).to receive(:new).and_return(mock_webserver)
68+
expect(mock_webserver).to receive(:run).and_raise('testing: intentional uncaught exception')
69+
end
70+
71+
it 'makes an attempt to stop the webserver' do
72+
expect(mock_webserver).to receive(:stop)
73+
74+
plugin.run([]) rescue nil
75+
end
76+
77+
it 'propagates the original exception' do
78+
expect do
79+
plugin.run([])
80+
end.to raise_exception('testing: intentional uncaught exception')
81+
end
82+
83+
context 'and an attempt to stop the webserver also crashes' do
84+
let(:mock_logger) { double('Logger').as_null_object }
85+
before(:each) do
86+
allow(plugin).to receive(:logger).and_return(mock_logger)
87+
allow(mock_webserver).to receive(:stop).and_raise('yo dawg')
88+
end
89+
90+
it 'logs helpfully' do
91+
expect(mock_logger).to receive(:error).with("Error while stopping FTW::WebServer",
92+
exception: 'yo dawg', backtrace: instance_of(Array))
93+
94+
plugin.run([]) rescue nil
95+
end
96+
97+
it 'propagates the original exception' do
98+
expect do
99+
plugin.run([])
100+
end.to raise_exception('testing: intentional uncaught exception')
101+
end
102+
end
103+
end
104+
end
58105
end

0 commit comments

Comments
 (0)