deas 0.37.0 → 0.37.1
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.
- data/lib/deas/logging.rb +7 -5
- data/lib/deas/show_exceptions.rb +7 -12
- data/lib/deas/version.rb +1 -1
- data/test/support/fake_sinatra_call.rb +5 -1
- data/test/support/routes.rb +1 -1
- data/test/unit/logging_tests.rb +259 -11
- data/test/unit/show_exceptions_tests.rb +49 -16
- metadata +5 -5
data/lib/deas/logging.rb
CHANGED
@@ -41,7 +41,7 @@ module Deas
|
|
41
41
|
log_error(env['sinatra.error'])
|
42
42
|
env['deas.time_taken'] = RoundedTime.new(benchmark.real)
|
43
43
|
|
44
|
-
[
|
44
|
+
[status, headers, body]
|
45
45
|
end
|
46
46
|
|
47
47
|
def log(message)
|
@@ -81,11 +81,11 @@ module Deas
|
|
81
81
|
status, headers, body = super(env)
|
82
82
|
log " Redir: #{headers['Location']}" if headers.key?('Location')
|
83
83
|
log "===== Completed in #{env['deas.time_taken']}ms (#{response_display(status)}) ====="
|
84
|
-
[
|
84
|
+
[status, headers, body]
|
85
85
|
end
|
86
86
|
|
87
87
|
def response_display(status)
|
88
|
-
[
|
88
|
+
[status, RESPONSE_STATUS_NAMES[status.to_i]].compact.join(', ')
|
89
89
|
end
|
90
90
|
|
91
91
|
end
|
@@ -101,16 +101,18 @@ module Deas
|
|
101
101
|
line_attrs = {
|
102
102
|
'method' => request.request_method,
|
103
103
|
'path' => request.path,
|
104
|
-
'handler' => env['deas.handler_class'].name,
|
105
104
|
'params' => env['deas.params'],
|
106
105
|
'time' => env['deas.time_taken'],
|
107
106
|
'status' => status
|
108
107
|
}
|
108
|
+
if env['deas.handler_class']
|
109
|
+
line_attrs['handler'] = env['deas.handler_class'].name
|
110
|
+
end
|
109
111
|
if headers.key?('Location')
|
110
112
|
line_attrs['redir'] = headers['Location']
|
111
113
|
end
|
112
114
|
log SummaryLine.new(line_attrs)
|
113
|
-
[
|
115
|
+
[status, headers, body]
|
114
116
|
end
|
115
117
|
|
116
118
|
end
|
data/lib/deas/show_exceptions.rb
CHANGED
@@ -27,24 +27,19 @@ module Deas
|
|
27
27
|
error_body = Body.new(error)
|
28
28
|
|
29
29
|
headers['Content-Length'] = error_body.size.to_s
|
30
|
-
headers['Content-Type']
|
30
|
+
headers['Content-Type'] = error_body.mime_type.to_s
|
31
31
|
body = [error_body.content]
|
32
32
|
end
|
33
|
-
[
|
33
|
+
[status, headers, body]
|
34
34
|
end
|
35
35
|
|
36
36
|
class Body
|
37
|
-
attr_reader :content
|
38
|
-
def initialize(e)
|
39
|
-
@content ||= "#{e.class}: #{e.message}\n#{(e.backtrace || []).join("\n")}"
|
40
|
-
end
|
37
|
+
attr_reader :content, :size, :mime_type
|
41
38
|
|
42
|
-
def
|
43
|
-
@
|
44
|
-
|
45
|
-
|
46
|
-
def mime_type
|
47
|
-
@mime_type ||= "text/plain"
|
39
|
+
def initialize(e)
|
40
|
+
@content = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
|
41
|
+
@size = Rack::Utils.bytesize(@content)
|
42
|
+
@mime_type = "text/plain"
|
48
43
|
end
|
49
44
|
end
|
50
45
|
|
data/lib/deas/version.rb
CHANGED
@@ -10,7 +10,7 @@ class FakeSinatraCall
|
|
10
10
|
|
11
11
|
def initialize(settings = nil)
|
12
12
|
@request = FakeRequest.new('GET','/something', {}, OpenStruct.new)
|
13
|
-
@response = FakeResponse.new
|
13
|
+
@response = FakeResponse.new(Factory.integer, {}, [Factory.text])
|
14
14
|
@session = @request.session
|
15
15
|
@params = @request.params
|
16
16
|
@logger = Deas::NullLogger.new
|
@@ -26,6 +26,10 @@ class FakeSinatraCall
|
|
26
26
|
}.merge(settings || {}))
|
27
27
|
end
|
28
28
|
|
29
|
+
def call(env)
|
30
|
+
[@response.status, @response.headers, [@response.body]]
|
31
|
+
end
|
32
|
+
|
29
33
|
def halt(*args)
|
30
34
|
throw :halt, args
|
31
35
|
end
|
data/test/support/routes.rb
CHANGED
data/test/unit/logging_tests.rb
CHANGED
@@ -5,41 +5,277 @@ module Deas::Logging
|
|
5
5
|
|
6
6
|
class UnitTests < Assert::Context
|
7
7
|
desc "Deas::Logging"
|
8
|
-
setup do
|
9
|
-
@app = Factory.sinatra_call
|
10
|
-
end
|
11
8
|
subject{ Deas::Logging }
|
12
9
|
|
13
10
|
should have_imeths :middleware
|
14
11
|
|
12
|
+
should "return a middleware class given a verbose flag" do
|
13
|
+
assert_equal Deas::VerboseLogging, subject.middleware(true)
|
14
|
+
assert_equal Deas::SummaryLogging, subject.middleware(false)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class CallSetupTests < UnitTests
|
20
|
+
setup do
|
21
|
+
@logger = SpyLogger.new
|
22
|
+
@app = Factory.sinatra_call({
|
23
|
+
:deas_server_data => Factory.server_data(:logger => @logger)
|
24
|
+
})
|
25
|
+
|
26
|
+
@app_call_env = nil
|
27
|
+
@resp_status = Factory.integer
|
28
|
+
@resp_headers = { 'Location' => Factory.path }
|
29
|
+
@app_response = [@resp_status, @resp_headers, [Factory.text]]
|
30
|
+
Assert.stub(@app, :call) do |env|
|
31
|
+
# dup so we can see what keys were added before supering
|
32
|
+
@app_call_env = env.dup
|
33
|
+
@app_response
|
34
|
+
end
|
35
|
+
|
36
|
+
@env = {
|
37
|
+
'REQUEST_METHOD' => Factory.string(3).upcase,
|
38
|
+
'PATH_INFO' => Factory.path,
|
39
|
+
'rack.run_once' => true
|
40
|
+
}
|
41
|
+
end
|
42
|
+
subject{ @middleware_class }
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class BaseLoggingTests < CallSetupTests
|
47
|
+
desc "Deas::BaseLogging"
|
48
|
+
setup do
|
49
|
+
@middleware_class = Deas::BaseLogging
|
50
|
+
end
|
51
|
+
|
15
52
|
end
|
16
53
|
|
17
|
-
class
|
54
|
+
class BaseLoggingInitTests < BaseLoggingTests
|
55
|
+
desc "when init"
|
56
|
+
setup do
|
57
|
+
@benchmark = Benchmark.measure{}
|
58
|
+
Assert.stub(Benchmark, :measure) do |&block|
|
59
|
+
block.call
|
60
|
+
@benchmark
|
61
|
+
end
|
62
|
+
|
63
|
+
@middleware = @middleware_class.new(@app)
|
64
|
+
end
|
65
|
+
subject{ @middleware }
|
66
|
+
|
67
|
+
should have_imeths :call, :call!
|
68
|
+
|
69
|
+
should "call the app and return its response when called" do
|
70
|
+
response = subject.call(@env)
|
71
|
+
assert_not_nil @app_call_env
|
72
|
+
assert_equal @app_response, response
|
73
|
+
end
|
74
|
+
|
75
|
+
should "set the rack.logger env key before its app is called" do
|
76
|
+
subject.call(@env)
|
77
|
+
assert_equal @logger, @env['rack.logger']
|
78
|
+
assert_same @env['rack.logger'], @app_call_env['rack.logger']
|
79
|
+
end
|
80
|
+
|
81
|
+
should "benchmark calling its app and set the deas.time_taken env key" do
|
82
|
+
assert_nil @env['deas.time_taken']
|
83
|
+
subject.call(@env)
|
84
|
+
exp = Deas::RoundedTime.new(@benchmark.real)
|
85
|
+
assert_equal exp, @env['deas.time_taken']
|
86
|
+
end
|
87
|
+
|
88
|
+
should "log a sinatra.error env key if it exists" do
|
89
|
+
@env.delete('sinatra.error')
|
90
|
+
subject.call(@env)
|
91
|
+
assert_empty @logger.info_logged
|
92
|
+
|
93
|
+
@env['sinatra.error'] = Factory.exception(Sinatra::NotFound)
|
94
|
+
subject.call(@env)
|
95
|
+
assert_empty @logger.info_logged
|
96
|
+
|
97
|
+
@env['sinatra.error'] = error = Factory.exception
|
98
|
+
subject.call(@env)
|
99
|
+
exp = "[Deas] #{error.class}: #{error.message}\n#{error.backtrace.join("\n")}"
|
100
|
+
assert_includes exp, @logger.info_logged
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
class VerboseLoggingTests < CallSetupTests
|
18
106
|
desc "Deas::VerboseLogging"
|
19
107
|
setup do
|
108
|
+
@middleware_class = Deas::VerboseLogging
|
109
|
+
end
|
110
|
+
|
111
|
+
should "be a base logging middleware" do
|
112
|
+
assert subject < Deas::BaseLogging
|
113
|
+
end
|
114
|
+
|
115
|
+
should "know its response status names" do
|
116
|
+
exp = {
|
117
|
+
200 => 'OK',
|
118
|
+
302 => 'FOUND',
|
119
|
+
400 => 'BAD REQUEST',
|
120
|
+
401 => 'UNAUTHORIZED',
|
121
|
+
403 => 'FORBIDDEN',
|
122
|
+
404 => 'NOT FOUND',
|
123
|
+
408 => 'TIMEOUT',
|
124
|
+
500 => 'ERROR'
|
125
|
+
}
|
126
|
+
assert_equal exp, @middleware_class::RESPONSE_STATUS_NAMES
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
class VerboseLoggingInitTests < VerboseLoggingTests
|
132
|
+
desc "when init"
|
133
|
+
setup do
|
134
|
+
@resp_status = @middleware_class::RESPONSE_STATUS_NAMES.keys.choice
|
135
|
+
@app_response[0] = @resp_status
|
136
|
+
|
20
137
|
@middleware = Deas::VerboseLogging.new(@app)
|
21
138
|
end
|
22
139
|
subject{ @middleware }
|
23
140
|
|
24
|
-
should have_imeths :call
|
141
|
+
should have_imeths :call!
|
142
|
+
|
143
|
+
should "call the app and return its response when called" do
|
144
|
+
response = subject.call(@env)
|
145
|
+
assert_not_nil @app_call_env
|
146
|
+
assert_equal @app_response, response
|
147
|
+
end
|
148
|
+
|
149
|
+
should "set the deas.logging env key before calling its app" do
|
150
|
+
assert_nil @env['deas.logging']
|
151
|
+
subject.call(@env)
|
152
|
+
assert_instance_of Proc, @env['deas.logging']
|
153
|
+
|
154
|
+
message = Factory.text
|
155
|
+
@env['deas.logging'].call(message)
|
156
|
+
assert_includes "[Deas] #{message}", @logger.info_logged
|
157
|
+
|
158
|
+
assert_same @env['deas.logging'], @app_call_env['deas.logging']
|
159
|
+
end
|
25
160
|
|
26
|
-
should "
|
27
|
-
|
161
|
+
should "log the request when called" do
|
162
|
+
assert_empty @logger.info_logged
|
163
|
+
subject.call(@env)
|
164
|
+
status = "#{@resp_status}, " \
|
165
|
+
"#{@middleware_class::RESPONSE_STATUS_NAMES[@resp_status]}"
|
166
|
+
exp = [
|
167
|
+
"[Deas] ===== Received request =====",
|
168
|
+
"[Deas] Method: #{@env['REQUEST_METHOD'].inspect}",
|
169
|
+
"[Deas] Path: #{@env['PATH_INFO'].inspect}",
|
170
|
+
"[Deas] Redir: #{@resp_headers['Location']}",
|
171
|
+
"[Deas] ===== Completed in #{@env['deas.time_taken']}ms (#{status}) ====="
|
172
|
+
]
|
173
|
+
assert_equal exp, @logger.info_logged
|
174
|
+
end
|
175
|
+
|
176
|
+
should "not log a redir line if it doesn't have a Location header" do
|
177
|
+
@resp_headers.delete('Location')
|
178
|
+
subject.call(@env)
|
179
|
+
|
180
|
+
exp = "[Deas] Redir: #{@resp_headers['Location']}"
|
181
|
+
assert_not_includes exp, @logger.info_logged
|
182
|
+
end
|
183
|
+
|
184
|
+
should "not log a status name for unknown statuses" do
|
185
|
+
@resp_status = Factory.integer
|
186
|
+
@app_response[0] = @resp_status
|
187
|
+
subject.call(@env)
|
188
|
+
|
189
|
+
exp = "[Deas] ===== Completed in #{@env['deas.time_taken']}ms (#{@resp_status}) ====="
|
190
|
+
assert_includes exp, @logger.info_logged
|
28
191
|
end
|
29
192
|
|
30
193
|
end
|
31
194
|
|
32
|
-
class SummaryLoggingTests <
|
195
|
+
class SummaryLoggingTests < CallSetupTests
|
33
196
|
desc "Deas::SummaryLogging"
|
34
197
|
setup do
|
198
|
+
@middleware_class = Deas::SummaryLogging
|
199
|
+
end
|
200
|
+
|
201
|
+
should "be a base logging middleware" do
|
202
|
+
assert subject < Deas::BaseLogging
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
class SummaryLoggingInitTests < SummaryLoggingTests
|
208
|
+
desc "when init"
|
209
|
+
setup do
|
210
|
+
@params = { Factory.string => Factory.string }
|
211
|
+
@handler_class = TestHandler
|
212
|
+
@env.merge!({
|
213
|
+
'deas.params' => @params,
|
214
|
+
'deas.handler_class' => @handler_class
|
215
|
+
})
|
216
|
+
|
35
217
|
@middleware = Deas::SummaryLogging.new(@app)
|
36
218
|
end
|
37
219
|
subject{ @middleware }
|
38
220
|
|
39
|
-
should
|
221
|
+
should "call the app and return its response when called" do
|
222
|
+
response = subject.call(@env)
|
223
|
+
assert_not_nil @app_call_env
|
224
|
+
assert_equal @app_response, response
|
225
|
+
end
|
40
226
|
|
41
|
-
should "
|
42
|
-
|
227
|
+
should "set the deas.logging env key before calling its app" do
|
228
|
+
assert_nil @env['deas.logging']
|
229
|
+
subject.call(@env)
|
230
|
+
assert_instance_of Proc, @env['deas.logging']
|
231
|
+
assert_nil @env['deas.logging'].call(Factory.text)
|
232
|
+
assert_same @env['deas.logging'], @app_call_env['deas.logging']
|
233
|
+
end
|
234
|
+
|
235
|
+
should "log the request when called" do
|
236
|
+
assert_empty @logger.info_logged
|
237
|
+
subject.call(@env)
|
238
|
+
|
239
|
+
summary_line = Deas::SummaryLine.new({
|
240
|
+
'method' => @env['REQUEST_METHOD'],
|
241
|
+
'path' => @env['PATH_INFO'],
|
242
|
+
'params' => @env['deas.params'],
|
243
|
+
'time' => @env['deas.time_taken'],
|
244
|
+
'status' => @resp_status,
|
245
|
+
'handler' => @handler_class.name,
|
246
|
+
'redir' => @resp_headers['Location']
|
247
|
+
})
|
248
|
+
assert_includes "[Deas] #{summary_line}", @logger.info_logged
|
249
|
+
end
|
250
|
+
|
251
|
+
should "not log a handler when it doesn't have a handler class" do
|
252
|
+
@env.delete('deas.handler_class')
|
253
|
+
subject.call(@env)
|
254
|
+
|
255
|
+
summary_line = Deas::SummaryLine.new({
|
256
|
+
'method' => @env['REQUEST_METHOD'],
|
257
|
+
'path' => @env['PATH_INFO'],
|
258
|
+
'params' => @env['deas.params'],
|
259
|
+
'time' => @env['deas.time_taken'],
|
260
|
+
'status' => @resp_status,
|
261
|
+
'redir' => @resp_headers['Location']
|
262
|
+
})
|
263
|
+
assert_includes "[Deas] #{summary_line}", @logger.info_logged
|
264
|
+
end
|
265
|
+
|
266
|
+
should "not log a redir if it doesn't have a Location header" do
|
267
|
+
@resp_headers.delete('Location')
|
268
|
+
subject.call(@env)
|
269
|
+
|
270
|
+
summary_line = Deas::SummaryLine.new({
|
271
|
+
'method' => @env['REQUEST_METHOD'],
|
272
|
+
'path' => @env['PATH_INFO'],
|
273
|
+
'params' => @env['deas.params'],
|
274
|
+
'time' => @env['deas.time_taken'],
|
275
|
+
'status' => @resp_status,
|
276
|
+
'handler' => @handler_class.name,
|
277
|
+
})
|
278
|
+
assert_includes "[Deas] #{summary_line}", @logger.info_logged
|
43
279
|
end
|
44
280
|
|
45
281
|
end
|
@@ -88,4 +324,16 @@ module Deas::Logging
|
|
88
324
|
|
89
325
|
end
|
90
326
|
|
327
|
+
TestHandler = Class.new
|
328
|
+
|
329
|
+
class SpyLogger
|
330
|
+
attr_reader :info_logged
|
331
|
+
|
332
|
+
def initialize
|
333
|
+
@info_logged = []
|
334
|
+
end
|
335
|
+
|
336
|
+
def info(message); @info_logged << message; end
|
337
|
+
end
|
338
|
+
|
91
339
|
end
|
@@ -8,27 +8,60 @@ class Deas::ShowExceptions
|
|
8
8
|
class UnitTests < Assert::Context
|
9
9
|
desc "Deas::ShowExceptions"
|
10
10
|
setup do
|
11
|
-
|
12
|
-
@app = proc do |env|
|
13
|
-
env['sinatra.error'] = exception
|
14
|
-
[ 404, {}, [] ]
|
15
|
-
end
|
16
|
-
@exception = exception
|
17
|
-
@show_exceptions = Deas::ShowExceptions.new(@app)
|
11
|
+
@middleware_class = Deas::ShowExceptions
|
18
12
|
end
|
19
|
-
subject{ @
|
13
|
+
subject{ @middleware_class }
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class InitTests < UnitTests
|
18
|
+
desc "when init"
|
19
|
+
setup do
|
20
|
+
@app = Factory.sinatra_call
|
21
|
+
@env = { 'sinatra.error' => Factory.exception }
|
22
|
+
@middleware = @middleware_class.new(@app)
|
23
|
+
end
|
24
|
+
subject{ @middleware }
|
20
25
|
|
21
26
|
should have_imeths :call, :call!
|
22
27
|
|
23
|
-
should "return a
|
24
|
-
status, headers, body = subject.call(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
should "return a response for the exception when called" do
|
29
|
+
status, headers, body = subject.call(@env)
|
30
|
+
error_body = Body.new(@env['sinatra.error'])
|
31
|
+
|
32
|
+
assert_equal @app.response.status, status
|
33
|
+
assert_equal error_body.size.to_s, headers['Content-Length']
|
34
|
+
assert_equal error_body.mime_type, headers['Content-Type']
|
35
|
+
assert_equal [error_body.content], body
|
36
|
+
end
|
37
|
+
|
38
|
+
should "return the apps response if there isn't an exception" do
|
39
|
+
@env.delete('sinatra.error')
|
40
|
+
status, headers, body = subject.call(@env)
|
41
|
+
|
42
|
+
assert_equal @app.response.status, status
|
43
|
+
assert_equal @app.response.headers, headers
|
44
|
+
assert_equal [@app.response.body], body
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class BodyTests < UnitTests
|
50
|
+
desc "Body"
|
51
|
+
setup do
|
52
|
+
@exception = Factory.exception
|
53
|
+
@body = Body.new(@exception)
|
54
|
+
end
|
55
|
+
subject{ @body }
|
56
|
+
|
57
|
+
should have_readers :content, :size, :mime_type
|
28
58
|
|
29
|
-
|
30
|
-
|
31
|
-
|
59
|
+
should "know its attributes" do
|
60
|
+
exp_content = "#{@exception.class}: #{@exception.message}\n" \
|
61
|
+
"#{@exception.backtrace.join("\n")}"
|
62
|
+
assert_equal exp_content, subject.content
|
63
|
+
assert_equal Rack::Utils.bytesize(exp_content), subject.size
|
64
|
+
assert_equal "text/plain", subject.mime_type
|
32
65
|
end
|
33
66
|
|
34
67
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deas
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 137
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 37
|
9
|
-
-
|
10
|
-
version: 0.37.
|
9
|
+
- 1
|
10
|
+
version: 0.37.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kelly Redding
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2015-
|
19
|
+
date: 2015-10-07 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
@@ -206,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
206
206
|
requirements: []
|
207
207
|
|
208
208
|
rubyforge_project:
|
209
|
-
rubygems_version: 1.8.
|
209
|
+
rubygems_version: 1.8.25
|
210
210
|
signing_key:
|
211
211
|
specification_version: 3
|
212
212
|
summary: Handler-based web framework powered by Sinatra
|