peastash 0.0.8
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 +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +129 -0
- data/README.md +183 -0
- data/Rakefile +17 -0
- data/lib/peastash/middleware.rb +37 -0
- data/lib/peastash/outputs/io.rb +21 -0
- data/lib/peastash/rails_ext/railtie.rb +30 -0
- data/lib/peastash/rails_ext/watch.rb +15 -0
- data/lib/peastash/rails_ext.rb +2 -0
- data/lib/peastash/version.rb +3 -0
- data/lib/peastash.rb +120 -0
- data/peastash.gemspec +31 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/controllers/welcome_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +28 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +34 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +40 -0
- data/spec/dummy/config/environments/test_with_specific_position.rb +41 -0
- data/spec/dummy/config/environments/test_without_buchestache.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +9 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/peastash/middleware_spec.rb +144 -0
- data/spec/peastash/rails_ext/railtie_spec.rb +92 -0
- data/spec/peastash/rails_ext/watch_spec.rb +24 -0
- data/spec/peastash_spec.rb +213 -0
- data/spec/spec_helper.rb +31 -0
- metadata +289 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
background-color: #EFEFEF;
|
|
9
|
+
color: #2E2F30;
|
|
10
|
+
text-align: center;
|
|
11
|
+
font-family: arial, sans-serif;
|
|
12
|
+
margin: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
div.dialog {
|
|
16
|
+
width: 95%;
|
|
17
|
+
max-width: 33em;
|
|
18
|
+
margin: 4em auto 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
div.dialog > div {
|
|
22
|
+
border: 1px solid #CCC;
|
|
23
|
+
border-right-color: #999;
|
|
24
|
+
border-left-color: #999;
|
|
25
|
+
border-bottom-color: #BBB;
|
|
26
|
+
border-top: #B00100 solid 4px;
|
|
27
|
+
border-top-left-radius: 9px;
|
|
28
|
+
border-top-right-radius: 9px;
|
|
29
|
+
background-color: white;
|
|
30
|
+
padding: 7px 12% 0;
|
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
h1 {
|
|
35
|
+
font-size: 100%;
|
|
36
|
+
color: #730E15;
|
|
37
|
+
line-height: 1.5em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
div.dialog > p {
|
|
41
|
+
margin: 0 0 1em;
|
|
42
|
+
padding: 1em;
|
|
43
|
+
background-color: #F7F7F7;
|
|
44
|
+
border: 1px solid #CCC;
|
|
45
|
+
border-right-color: #999;
|
|
46
|
+
border-left-color: #999;
|
|
47
|
+
border-bottom-color: #999;
|
|
48
|
+
border-bottom-left-radius: 4px;
|
|
49
|
+
border-bottom-right-radius: 4px;
|
|
50
|
+
border-top-color: #DADADA;
|
|
51
|
+
color: #666;
|
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
|
|
57
|
+
<body>
|
|
58
|
+
<!-- This file lives in public/422.html -->
|
|
59
|
+
<div class="dialog">
|
|
60
|
+
<div>
|
|
61
|
+
<h1>The change you wanted was rejected.</h1>
|
|
62
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
|
63
|
+
</div>
|
|
64
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
65
|
+
</div>
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
background-color: #EFEFEF;
|
|
9
|
+
color: #2E2F30;
|
|
10
|
+
text-align: center;
|
|
11
|
+
font-family: arial, sans-serif;
|
|
12
|
+
margin: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
div.dialog {
|
|
16
|
+
width: 95%;
|
|
17
|
+
max-width: 33em;
|
|
18
|
+
margin: 4em auto 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
div.dialog > div {
|
|
22
|
+
border: 1px solid #CCC;
|
|
23
|
+
border-right-color: #999;
|
|
24
|
+
border-left-color: #999;
|
|
25
|
+
border-bottom-color: #BBB;
|
|
26
|
+
border-top: #B00100 solid 4px;
|
|
27
|
+
border-top-left-radius: 9px;
|
|
28
|
+
border-top-right-radius: 9px;
|
|
29
|
+
background-color: white;
|
|
30
|
+
padding: 7px 12% 0;
|
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
h1 {
|
|
35
|
+
font-size: 100%;
|
|
36
|
+
color: #730E15;
|
|
37
|
+
line-height: 1.5em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
div.dialog > p {
|
|
41
|
+
margin: 0 0 1em;
|
|
42
|
+
padding: 1em;
|
|
43
|
+
background-color: #F7F7F7;
|
|
44
|
+
border: 1px solid #CCC;
|
|
45
|
+
border-right-color: #999;
|
|
46
|
+
border-left-color: #999;
|
|
47
|
+
border-bottom-color: #999;
|
|
48
|
+
border-bottom-left-radius: 4px;
|
|
49
|
+
border-bottom-right-radius: 4px;
|
|
50
|
+
border-top-color: #DADADA;
|
|
51
|
+
color: #666;
|
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
|
|
57
|
+
<body>
|
|
58
|
+
<!-- This file lives in public/500.html -->
|
|
59
|
+
<div class="dialog">
|
|
60
|
+
<div>
|
|
61
|
+
<h1>We're sorry, but something went wrong.</h1>
|
|
62
|
+
</div>
|
|
63
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
64
|
+
</div>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
File without changes
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'peastash/middleware'
|
|
3
|
+
require 'pry'
|
|
4
|
+
|
|
5
|
+
describe Peastash::Middleware do
|
|
6
|
+
before do
|
|
7
|
+
Peastash.any_instance.stub(:enabled?) { true }
|
|
8
|
+
end
|
|
9
|
+
let(:app) { ->(env) { [200, {}, "app"] } }
|
|
10
|
+
let(:before_block) { ->(env, response) {} }
|
|
11
|
+
let(:after_block) { ->(env, response) {} }
|
|
12
|
+
|
|
13
|
+
let(:middleware) do
|
|
14
|
+
Peastash::Middleware.new(app, before_block, after_block)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "Rack middleware" do
|
|
18
|
+
it "wraps the call to the next middleware in a Peastash block" do
|
|
19
|
+
expect(Peastash.with_instance).to receive(:log)
|
|
20
|
+
middleware.call env_for('/')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "doesn't interrupt the middleware chain" do
|
|
24
|
+
expect(app).to receive(:call).and_call_original
|
|
25
|
+
middleware.call env_for('/')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "calls whatever block is given to the middleware" do
|
|
29
|
+
before_block = ->(env, response) { Peastash.with_instance.store[:before_block] = true }
|
|
30
|
+
after_block = ->(env, response) { Peastash.with_instance.store[:after_block] = true }
|
|
31
|
+
|
|
32
|
+
middleware = Peastash::Middleware.new(app, before_block, after_block)
|
|
33
|
+
code, env = middleware.call env_for('/')
|
|
34
|
+
expect(Peastash.with_instance.store[:before_block]).to be true
|
|
35
|
+
expect(Peastash.with_instance.store[:after_block]).to be true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context 'storing data in the custom block' do
|
|
39
|
+
before :each do
|
|
40
|
+
block = ->(env, response) {
|
|
41
|
+
request = Rack::Request.new(env)
|
|
42
|
+
Peastash.with_instance.store[:path] = request.path
|
|
43
|
+
}
|
|
44
|
+
@middleware = Peastash::Middleware.new(app, block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "can store arbitrary data in the Peastash store" do
|
|
48
|
+
@middleware.call env_for('/')
|
|
49
|
+
expect(Peastash.with_instance.store[:path]).to eq('/')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'uses the stored data to build the event' do
|
|
53
|
+
expect(LogStash::Event).to receive(:new).with({
|
|
54
|
+
'@source' => Peastash::STORE_NAME,
|
|
55
|
+
'@fields' => { path: '/', duration: 0, status: 200, ip: nil },
|
|
56
|
+
'@tags' => []
|
|
57
|
+
})
|
|
58
|
+
Timecop.freeze { @middleware.call env_for('/') }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context 'storing data in the rack app' do
|
|
63
|
+
before :each do
|
|
64
|
+
app = ->(env) do
|
|
65
|
+
request = Rack::Request.new(env)
|
|
66
|
+
Peastash.with_instance.store[:scheme] = request.scheme
|
|
67
|
+
[200, {}, "app"]
|
|
68
|
+
end
|
|
69
|
+
@middleware = Peastash::Middleware.new(app, before_block)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "can store arbitrary data in the Peastash store" do
|
|
73
|
+
@middleware.call env_for('/')
|
|
74
|
+
expect(Peastash.with_instance.store[:scheme]).to eq('http')
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'uses the stored data to build the event' do
|
|
78
|
+
expect(LogStash::Event).to receive(:new).with({
|
|
79
|
+
'@source' => Peastash::STORE_NAME,
|
|
80
|
+
'@fields' => { scheme: 'http', duration: 0, status: 200, ip: nil },
|
|
81
|
+
'@tags' => []
|
|
82
|
+
})
|
|
83
|
+
Timecop.freeze { @middleware.call env_for('/') }
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context 'without a custom block' do
|
|
88
|
+
it "doesn't try to call the block" do
|
|
89
|
+
@middleware = Peastash::Middleware.new(app)
|
|
90
|
+
expect {
|
|
91
|
+
@middleware.call env_for('/')
|
|
92
|
+
}.to_not raise_error
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context 'persistence between before/after block' do
|
|
97
|
+
it "saves instance variables between before/after block" do
|
|
98
|
+
before_block = ->(env, request) { @foo = 'foo' }
|
|
99
|
+
after_block = ->(env, request) { Peastash.with_instance.store[:foo] = @foo }
|
|
100
|
+
@middleware = Peastash::Middleware.new(app, before_block, after_block)
|
|
101
|
+
|
|
102
|
+
expect(LogStash::Event).to receive(:new).with({
|
|
103
|
+
'@source' => Peastash::STORE_NAME,
|
|
104
|
+
'@fields' => { duration: 0, status: 200, foo: 'foo', ip: nil },
|
|
105
|
+
'@tags' => [],
|
|
106
|
+
})
|
|
107
|
+
Timecop.freeze { @middleware.call env_for('/') }
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context "exception in before / after block" do
|
|
112
|
+
before :each do
|
|
113
|
+
Peastash.safe!
|
|
114
|
+
before_block = ->(env, request) { 1 / 0 }
|
|
115
|
+
after_block = ->(env, request) { unknown_method }
|
|
116
|
+
@middleware = Peastash::Middleware.new(app, before_block, after_block)
|
|
117
|
+
STDERR.stub(:puts)
|
|
118
|
+
end
|
|
119
|
+
after(:each) { STDERR.unstub(:puts) }
|
|
120
|
+
|
|
121
|
+
it "doesn't interrupt the middleware flow, logging should be transparent" do
|
|
122
|
+
expect {
|
|
123
|
+
@middleware.call env_for('/')
|
|
124
|
+
}.to_not raise_error
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "puts the error to STDERR for easy debugging" do
|
|
128
|
+
expect(STDERR).to receive(:puts).twice
|
|
129
|
+
@middleware.call env_for('/')
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "doesn't catch exception in the app" do
|
|
134
|
+
Peastash.safe!
|
|
135
|
+
app = ->(env) { raise }
|
|
136
|
+
@middleware = Peastash::Middleware.new(app)
|
|
137
|
+
expect {
|
|
138
|
+
@middleware.call env_for('/')
|
|
139
|
+
}.to raise_error
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rails'
|
|
3
|
+
require 'peastash/rails_ext'
|
|
4
|
+
require 'simplecov'
|
|
5
|
+
|
|
6
|
+
describe Peastash::Railtie do
|
|
7
|
+
context 'not configured' do
|
|
8
|
+
it "doesn't add the middleware by default" do
|
|
9
|
+
run_with_env 'test_without_peastash' do
|
|
10
|
+
expect(Rails.application.middleware).to_not include(Peastash::Middleware)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "doesn't add the subscriber" do
|
|
15
|
+
run_with_env 'test_without_peastash' do
|
|
16
|
+
Peastash.with_instance.store.clear
|
|
17
|
+
ActiveSupport::Notifications.instrument('process_action.action_controller', db_runtime: 1)
|
|
18
|
+
expect(Peastash.with_instance.store).to_not include(db: 1)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context 'correctly configured' do
|
|
24
|
+
context 'with specific conf' do
|
|
25
|
+
it 'places the middleware before the configured middleware if specified' do
|
|
26
|
+
run_with_env 'test_with_specific_position' do
|
|
27
|
+
cookies_index = -1
|
|
28
|
+
Rails.application.middleware.each_with_index { |middleware, index| cookies_index = index if middleware == ActionDispatch::Cookies }
|
|
29
|
+
expect(Rails.application.middleware[cookies_index - 1]).to eq(Peastash::Middleware)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context 'with regular conf' do
|
|
35
|
+
before :all do
|
|
36
|
+
ENV['RAILS_ENV'] = 'test'
|
|
37
|
+
require 'dummy/config/environment'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
before(:each) { Peastash.with_instance.store.clear }
|
|
41
|
+
|
|
42
|
+
context 'middleware' do
|
|
43
|
+
it "adds the middleware" do
|
|
44
|
+
expect(Rails.application.middleware).to include(Peastash::Middleware)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'adds the middleware before ActionDispatch::ShowExceptions by default' do
|
|
48
|
+
show_exceptions_index = -1
|
|
49
|
+
Rails.application.middleware.each_with_index { |middleware, index| show_exceptions_index = index if middleware == ActionDispatch::ShowExceptions }
|
|
50
|
+
expect(Rails.application.middleware[show_exceptions_index - 1]).to eq(Peastash::Middleware)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "adds a subscriber on 'process_action.action_controller' to gather metrics about the request" do
|
|
56
|
+
ActiveSupport::Notifications.instrument('process_action.action_controller', db_runtime: 1)
|
|
57
|
+
expect(Peastash.with_instance.store).to include(db: 1)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context "params logging" do
|
|
61
|
+
it "doesn't log the parameters if log_parameters isn't true" do
|
|
62
|
+
Peastash.with_instance.configuration[:log_parameters] = false
|
|
63
|
+
Rails.application.call env_for('/')
|
|
64
|
+
expect(Peastash.with_instance.store.keys).to_not include(:params)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "logs the parameters if log_parameters is true" do
|
|
68
|
+
Peastash.with_instance.configuration[:log_parameters] = true
|
|
69
|
+
Rails.application.call env_for('/')
|
|
70
|
+
expect(Peastash.with_instance.store.keys).to include(:params)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "doesn't log filtered parameters in clear text" do
|
|
74
|
+
Peastash.with_instance.configuration[:log_parameters] = true
|
|
75
|
+
Rails.application.call env_for('/?password=foo')
|
|
76
|
+
expect(Peastash.with_instance.store[:params]["password"]).to eq("[FILTERED]")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def run_with_env(env = 'test')
|
|
84
|
+
# Can't run those tests on jruby... yet
|
|
85
|
+
return if RUBY_PLATFORM == 'java'
|
|
86
|
+
fork do
|
|
87
|
+
SimpleCov.running = false
|
|
88
|
+
ENV['RAILS_ENV'] = env
|
|
89
|
+
require 'dummy/config/environment'
|
|
90
|
+
yield
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'peastash/rails_ext/watch'
|
|
3
|
+
|
|
4
|
+
describe "Peastash::Watch" do
|
|
5
|
+
it "adds the #watch method to Peastash" do
|
|
6
|
+
expect(Peastash.with_instance).to respond_to(:watch)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe "#watch" do
|
|
10
|
+
it "can subscribe to any notification" do
|
|
11
|
+
@dummy = Object.new.stub(:foo)
|
|
12
|
+
@subscriber = Peastash.with_instance.watch('foo.bar') { @dummy.foo }
|
|
13
|
+
expect(@dummy).to receive(:foo)
|
|
14
|
+
ActiveSupport::Notifications.instrument('foo.bar')
|
|
15
|
+
ActiveSupport::Notifications.unsubscribe(@subscriber)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "is provided with a handy named store" do
|
|
19
|
+
Peastash.with_instance.watch('foo.bar') { |*event, store| store[:foo] = 'bar' }
|
|
20
|
+
@subscriber = ActiveSupport::Notifications.instrument('foo.bar')
|
|
21
|
+
expect(Peastash.with_instance.store['foo.bar']).to eq(foo: 'bar')
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Peastash do
|
|
4
|
+
|
|
5
|
+
after(:each) { unconfigure_foostash! }
|
|
6
|
+
|
|
7
|
+
describe 'enabled' do
|
|
8
|
+
|
|
9
|
+
before :each do
|
|
10
|
+
Peastash.any_instance.stub(:enabled?) { true }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "scoped instances" do
|
|
14
|
+
it 'always return the same instance for the same name' do
|
|
15
|
+
expect(Peastash.with_instance(:foo)).to be(Peastash.with_instance(:foo))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'returns different instances for different names' do
|
|
19
|
+
expect(Peastash.with_instance(:bar)).to_not be(Peastash.with_instance(:foo))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'uses `global` as the default instance name' do
|
|
23
|
+
expect(Peastash.with_instance(:global)).to be(Peastash.with_instance)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'inherits its configuration for the `global` conf' do
|
|
27
|
+
Peastash.with_instance(:global).configure!({source: :foo})
|
|
28
|
+
expect(Peastash.with_instance(:bar).configuration[:source]).to be(:foo)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "#configure!" do
|
|
33
|
+
it 'allows setting tags to be added to every event' do
|
|
34
|
+
tags = ['foo', 'bar']
|
|
35
|
+
Peastash.with_instance.configure!(tags: tags)
|
|
36
|
+
expect(LogStash::Event).to receive(:new).with({
|
|
37
|
+
'@source' => Peastash::STORE_NAME,
|
|
38
|
+
'@fields' => {},
|
|
39
|
+
'@tags' => tags
|
|
40
|
+
})
|
|
41
|
+
Peastash.with_instance.log {}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "can customize the source" do
|
|
45
|
+
Peastash.with_instance.configure!(source: 'foo')
|
|
46
|
+
expect(LogStash::Event).to receive(:new).with({
|
|
47
|
+
'@source' => 'foo',
|
|
48
|
+
'@fields' => {},
|
|
49
|
+
'@tags' => []
|
|
50
|
+
})
|
|
51
|
+
Peastash.with_instance.log {}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "can customize the store name" do
|
|
55
|
+
Peastash.with_instance.configure!(store_name: :foo)
|
|
56
|
+
Peastash.with_instance.store[:bar] = 'bar'
|
|
57
|
+
expect(Thread.current[:global].keys).to include(:foo)
|
|
58
|
+
expect(Thread.current[:global][:foo]).to eq(bar: 'bar')
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "dump if empty?" do
|
|
62
|
+
it "can prevent logging if nothing is stored" do
|
|
63
|
+
Peastash.with_instance.configure!(dump_if_empty: false)
|
|
64
|
+
expect(Peastash.with_instance.instance_variable_get(:@output)).to_not receive(:dump)
|
|
65
|
+
Peastash.with_instance.log {}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "doesn't prevent logging if set to true" do
|
|
69
|
+
Peastash.with_instance.configure!(dump_if_empty: true)
|
|
70
|
+
expect(Peastash.with_instance.instance_variable_get(:@output)).to receive(:dump)
|
|
71
|
+
Peastash.with_instance.log {}
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "#log" do
|
|
77
|
+
context "Peastash not configured" do
|
|
78
|
+
it "calls #configure! beforehand" do
|
|
79
|
+
expect(Peastash.with_instance).to receive(:configure!).once.and_call_original
|
|
80
|
+
Peastash.with_instance.log {}
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context "Peastash already configured" do
|
|
85
|
+
before { Peastash.with_instance.configure! }
|
|
86
|
+
|
|
87
|
+
it "doesn't call #configure!" do
|
|
88
|
+
expect(Peastash).to_not receive(:configure!)
|
|
89
|
+
Peastash.with_instance.log {}
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "sends the event to the output" do
|
|
94
|
+
Peastash.with_instance.configure!
|
|
95
|
+
expect(Peastash.with_instance.instance_variable_get(:@output)).to receive(:dump)
|
|
96
|
+
Peastash.with_instance.log {}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "clears the store beforehand" do
|
|
100
|
+
Peastash.with_instance.configure!
|
|
101
|
+
Peastash.with_instance.store[:foo] = 'bar'
|
|
102
|
+
Peastash.with_instance.log {}
|
|
103
|
+
expect(Peastash.with_instance.store.keys).to_not include(:foo)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "aggregates everything in the store and dumps it" do
|
|
107
|
+
Peastash.with_instance.configure!
|
|
108
|
+
Peastash.with_instance.log do
|
|
109
|
+
Peastash.with_instance.store[:foo] = ['foo']
|
|
110
|
+
Peastash.with_instance.store[:foo] << 'bar'
|
|
111
|
+
end
|
|
112
|
+
expect(Peastash.with_instance.store[:foo]).to eq(['foo', 'bar'])
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "merges the tags from the parameters with the base tags" do
|
|
116
|
+
base_tags = %w(foo bar)
|
|
117
|
+
tags = %w(baz)
|
|
118
|
+
Peastash.with_instance.configure!(tags: base_tags)
|
|
119
|
+
expect(LogStash::Event).to receive(:new).with({
|
|
120
|
+
'@source' => Peastash::STORE_NAME,
|
|
121
|
+
'@fields' => {},
|
|
122
|
+
'@tags' => base_tags + tags
|
|
123
|
+
})
|
|
124
|
+
Peastash.with_instance.log(tags) {}
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
describe ".safely" do
|
|
129
|
+
context "when safe" do
|
|
130
|
+
before { Peastash.safe! }
|
|
131
|
+
|
|
132
|
+
it 'rescues errors silently' do
|
|
133
|
+
expect {
|
|
134
|
+
Peastash.safely { 1 / 0 }
|
|
135
|
+
}.not_to raise_error
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'returns value returned from the block' do
|
|
139
|
+
expect(Peastash.safely { "test" }).to eq("test")
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "puts the error to STDERR for easy debugging" do
|
|
143
|
+
expect(STDERR).to receive(:puts)
|
|
144
|
+
Peastash.safely { 1 / 0 }
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
context "when unsafe" do
|
|
149
|
+
before { Peastash.unsafe! }
|
|
150
|
+
|
|
151
|
+
it 'doesn\'t rescue errors silently' do
|
|
152
|
+
expect {
|
|
153
|
+
Peastash.safely { 1 / 0 }
|
|
154
|
+
}.to raise_error(ZeroDivisionError)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "puts the error to STDERR for easy debugging" do
|
|
158
|
+
expect(STDERR).to receive(:puts)
|
|
159
|
+
|
|
160
|
+
expect {
|
|
161
|
+
Peastash.safely { 1 / 0 }
|
|
162
|
+
}.to raise_error(ZeroDivisionError)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
describe "#tags" do
|
|
168
|
+
it "calls configure beforehand if instance isn't configured" do
|
|
169
|
+
expect(Peastash.with_instance).to receive(:configure!).and_call_original
|
|
170
|
+
Peastash.with_instance.tags << 'foo'
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it "makes it possible to add tags from within the #log block" do
|
|
174
|
+
base_tags = %w(foo bar)
|
|
175
|
+
tags = %w(baz)
|
|
176
|
+
additional_tags = %w(qux)
|
|
177
|
+
Peastash.with_instance.configure!(tags: base_tags)
|
|
178
|
+
expect(LogStash::Event).to receive(:new).with({
|
|
179
|
+
'@source' => Peastash::STORE_NAME,
|
|
180
|
+
'@fields' => {},
|
|
181
|
+
'@tags' => base_tags + tags + additional_tags
|
|
182
|
+
})
|
|
183
|
+
Peastash.with_instance.log(tags) { Peastash.with_instance.tags.concat(additional_tags) }
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
describe 'disabled' do
|
|
190
|
+
|
|
191
|
+
it "can process the called stuff in the #log block" do
|
|
192
|
+
expect {
|
|
193
|
+
Peastash.with_instance.log do
|
|
194
|
+
raise
|
|
195
|
+
end
|
|
196
|
+
}.to raise_error
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it "can process the called stuff in the #log block" do
|
|
200
|
+
expect { |b|
|
|
201
|
+
Peastash.with_instance.log(&b)
|
|
202
|
+
}.to yield_with_args(Peastash.with_instance)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "can process the called stuff for custom instance in the #log block" do
|
|
206
|
+
expect { |b|
|
|
207
|
+
Peastash.with_instance(:worker).log(&b)
|
|
208
|
+
}.to yield_with_args(Peastash.with_instance(:worker))
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
|
2
|
+
|
|
3
|
+
# ENV['RACK_ENV'] = 'test'
|
|
4
|
+
# ENV['RAILS_ENV'] = 'test'
|
|
5
|
+
|
|
6
|
+
require 'timecop'
|
|
7
|
+
require 'simplecov'
|
|
8
|
+
require 'rack/test'
|
|
9
|
+
|
|
10
|
+
require 'peastash'
|
|
11
|
+
|
|
12
|
+
RSpec.configure do |config|
|
|
13
|
+
config.include Rack::Test::Methods
|
|
14
|
+
config.before(:all) do
|
|
15
|
+
# Muting the output from the logger
|
|
16
|
+
Peastash::Outputs::IO.class_variable_set(:@@default_io, File.open(File::NULL, File::WRONLY))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
config.before(:each) do
|
|
20
|
+
# For the errors to be raised
|
|
21
|
+
Peastash.unsafe!
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def unconfigure_foostash!
|
|
26
|
+
Peastash.class_variable_set(:@@instance_cache, ThreadSafe::Cache.new)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def env_for(url, opts={})
|
|
30
|
+
Rack::MockRequest.env_for(url, opts)
|
|
31
|
+
end
|