rack-profiler 0.0.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +48 -9
- data/lib/rack/profiler.rb +21 -11
- data/lib/rack/profiler/version.rb +1 -1
- data/public/rack-profiler.html +1 -1
- data/spec/rack/profiler_spec.rb +41 -19
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ada3784e0444ea4df49d755fac6dc82e3ae30ee2
|
4
|
+
data.tar.gz: 7611769984c985b48d7a49cfb36750a92c000da3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3d87464a4fdf2c46f2f236ff9633b042535ffdf5184fe03453d11706e77b2b2b27a9de0dfc76dfcf87308458a5d1e5aa9f11be2fc1e4ef19adf21fe721eda89
|
7
|
+
data.tar.gz: 62c9a482614f8be5ddde9917ac96c0f36eb278b5d7e62d479682f574b5c677a90c4f704c4ca5414e4eec802574951f3ccd2d5bfe589fd28fb03016ede66e9b61
|
data/README.md
CHANGED
@@ -55,27 +55,33 @@ require 'rack/profiler'
|
|
55
55
|
use Rack::Profiler
|
56
56
|
```
|
57
57
|
|
58
|
+
NOTE: you should not expose the profiler publicly in the production environment,
|
59
|
+
as it may contain sensitive information. Refer to the [`authorization
|
60
|
+
section`](#authorization) on how to protect it.
|
61
|
+
|
58
62
|
### Rails
|
59
63
|
|
60
64
|
You can add the `Rack::Profiler` middleware at the beginning of your `config.ru`
|
61
65
|
like in the Rack/Sinatra installation or insert it in the middlewares stack configuration
|
62
|
-
in
|
66
|
+
in your `config/environments/<env>.rb` files:
|
63
67
|
|
64
68
|
```ruby
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# ...
|
69
|
-
|
70
|
-
config.middleware.insert_before Rack::Runtime, Rack::Profiler
|
69
|
+
YourApp.configure do |config|
|
70
|
+
# ...
|
71
71
|
|
72
|
-
|
72
|
+
config.middleware.insert 0, Rack::Profiler
|
73
73
|
end
|
74
74
|
```
|
75
75
|
|
76
|
+
NOTE: you should not expose the profiler publicly in the production environment,
|
77
|
+
as it may contain sensitive information. Refer to the [`authorization
|
78
|
+
section`](#authorization) for on to protect it.
|
79
|
+
|
76
80
|
## Configuration
|
77
81
|
|
78
|
-
You can configure `Rack::Profiler` passing a block to `use
|
82
|
+
You can configure `Rack::Profiler` passing a block to `use` (or
|
83
|
+
`middleware.insert` in Rails configuration). In the block you can subscribe to
|
84
|
+
more notifications and change some defaults:
|
79
85
|
|
80
86
|
```ruby
|
81
87
|
use Rack::Profiler do |profiler|
|
@@ -88,6 +94,39 @@ use Rack::Profiler do |profiler|
|
|
88
94
|
end
|
89
95
|
```
|
90
96
|
|
97
|
+
## Authorization
|
98
|
+
|
99
|
+
You typically *do not want to expose profiling publicly*, as it may contain
|
100
|
+
sensible information about your data and app. To protect your data, the easiest
|
101
|
+
option is to only enable the profiler in the development environment:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
if ENV['RACK_ENV'] == 'development'
|
105
|
+
require 'rack/profiler'
|
106
|
+
use Rack::Profiler
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
Sometimes though, you might want to run the profiler in the production
|
111
|
+
environment, in order to get results in a real setting (including caching and
|
112
|
+
optimizations). In this case, you can configure your custom authorization logic,
|
113
|
+
which can rely on the Rack env:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
use Rack::Profiler do |profiler|
|
117
|
+
profiler.authorize do |env|
|
118
|
+
# env is the Rack environment of the request. This block should return a
|
119
|
+
# truthy value when the request is allowed to be profiled, falsy otherwise.
|
120
|
+
env['rack-profiler-enabled'] == true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# ...then in your app:
|
125
|
+
before do
|
126
|
+
env['rack-profiler-enabled'] = true if current_user.admin?
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
91
130
|
## Usage
|
92
131
|
|
93
132
|
### Custom steps
|
data/lib/rack/profiler.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require "rack"
|
2
2
|
require "rack/request"
|
3
|
+
require "rack/auth/basic"
|
3
4
|
require "rack/profiler/version"
|
4
5
|
require "active_support/notifications"
|
5
6
|
|
6
7
|
module Rack
|
7
8
|
class Profiler
|
8
9
|
|
9
|
-
attr_reader :events, :backtrace_filter, :subscriptions
|
10
|
+
attr_reader :events, :backtrace_filter, :subscriptions, :authorizator
|
10
11
|
attr_accessor :dashboard_path
|
11
12
|
|
12
13
|
DEFAULT_SUBSCRIPTIONS = ['sql.active_record',
|
@@ -36,6 +37,7 @@ module Rack
|
|
36
37
|
def call(env)
|
37
38
|
@events = []
|
38
39
|
req = Rack::Request.new(env)
|
40
|
+
env['rack-profiler'] = self
|
39
41
|
|
40
42
|
if req.path == dashboard_path
|
41
43
|
render_dashboard
|
@@ -69,6 +71,10 @@ module Rack
|
|
69
71
|
@backtrace_filter = block
|
70
72
|
end
|
71
73
|
|
74
|
+
def authorize(&block)
|
75
|
+
@authorizator = block
|
76
|
+
end
|
77
|
+
|
72
78
|
private
|
73
79
|
|
74
80
|
def render_profiler_results(env)
|
@@ -76,16 +82,16 @@ module Rack
|
|
76
82
|
ActiveSupport::Notifications.instrument('rack-profiler.total_time') do
|
77
83
|
status, headers, body = @app.call(env)
|
78
84
|
end
|
79
|
-
[
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
]
|
85
|
+
return [status, headers, body] unless authorized?(env)
|
86
|
+
results = {
|
87
|
+
events: events.sort_by { |event| event[:start] },
|
88
|
+
response: {
|
89
|
+
status: status,
|
90
|
+
headers: headers,
|
91
|
+
body: stringify_body(body)
|
92
|
+
}
|
93
|
+
}
|
94
|
+
[200, { 'Content-Type' => 'application/json' }, [results.to_json]]
|
89
95
|
end
|
90
96
|
|
91
97
|
def render_dashboard
|
@@ -115,5 +121,9 @@ module Rack
|
|
115
121
|
body.each { |part| str << part }
|
116
122
|
str
|
117
123
|
end
|
124
|
+
|
125
|
+
def authorized?(env)
|
126
|
+
@authorizator.nil? || @authorizator.call(env)
|
127
|
+
end
|
118
128
|
end
|
119
129
|
end
|
data/public/rack-profiler.html
CHANGED
data/spec/rack/profiler_spec.rb
CHANGED
@@ -34,6 +34,7 @@ describe Rack::Profiler do
|
|
34
34
|
it "sets the correct defaults" do
|
35
35
|
expect(profiler.dashboard_path).to eq('/rack-profiler')
|
36
36
|
expect(profiler.backtrace_filter).to be_nil
|
37
|
+
expect(profiler.authorizator).to be_nil
|
37
38
|
expect(profiler.subscriptions).to include(
|
38
39
|
*Rack::Profiler::DEFAULT_SUBSCRIPTIONS
|
39
40
|
)
|
@@ -118,25 +119,25 @@ describe Rack::Profiler do
|
|
118
119
|
|
119
120
|
let(:env) do
|
120
121
|
{
|
121
|
-
"PATH_INFO"
|
122
|
-
"QUERY_STRING"
|
123
|
-
"REMOTE_HOST"
|
124
|
-
"REQUEST_METHOD"
|
125
|
-
"REQUEST_URI"
|
126
|
-
"SCRIPT_NAME"
|
127
|
-
"SERVER_NAME"
|
128
|
-
"SERVER_PORT"
|
129
|
-
"SERVER_PROTOCOL"
|
130
|
-
"HTTP_HOST"
|
131
|
-
"rack.version"
|
132
|
-
"rack.input"
|
133
|
-
"rack.errors"
|
134
|
-
"rack.multithread"
|
122
|
+
"PATH_INFO" => "/",
|
123
|
+
"QUERY_STRING" => "",
|
124
|
+
"REMOTE_HOST" => "localhost",
|
125
|
+
"REQUEST_METHOD" => "GET",
|
126
|
+
"REQUEST_URI" => "http://localhost:3000/",
|
127
|
+
"SCRIPT_NAME" => "",
|
128
|
+
"SERVER_NAME" => "localhost",
|
129
|
+
"SERVER_PORT" => "3000",
|
130
|
+
"SERVER_PROTOCOL" => "HTTP/1.1",
|
131
|
+
"HTTP_HOST" => "localhost:3000",
|
132
|
+
"rack.version" => [1, 2],
|
133
|
+
"rack.input" => StringIO.new,
|
134
|
+
"rack.errors" => StringIO.new,
|
135
|
+
"rack.multithread" => true,
|
135
136
|
"rack.multiprocess" => false,
|
136
|
-
"rack.run_once"
|
137
|
-
"rack.url_scheme"
|
138
|
-
"HTTP_VERSION"
|
139
|
-
"REQUEST_PATH"
|
137
|
+
"rack.run_once" => false,
|
138
|
+
"rack.url_scheme" => "http",
|
139
|
+
"HTTP_VERSION" => "HTTP/1.1",
|
140
|
+
"REQUEST_PATH" => "/"
|
140
141
|
}
|
141
142
|
end
|
142
143
|
|
@@ -146,7 +147,7 @@ describe Rack::Profiler do
|
|
146
147
|
expect(profiler.events).not_to include('xxx')
|
147
148
|
end
|
148
149
|
|
149
|
-
context "when the path is
|
150
|
+
context "when the path is dashboard_path" do
|
150
151
|
it "renders dashboard" do
|
151
152
|
path = ::File.expand_path('../../public/rack-profiler.html',
|
152
153
|
::File.dirname( __FILE__ ) )
|
@@ -193,6 +194,27 @@ describe Rack::Profiler do
|
|
193
194
|
parsed_body['events'].map { |e| e['name'] }
|
194
195
|
).to include('rack-profiler.total_time', 'rack-profiler.step')
|
195
196
|
end
|
197
|
+
|
198
|
+
context "when authorization is configured" do
|
199
|
+
before do
|
200
|
+
profiler.authorize { |env| env['rack-profiler-allowed'] }
|
201
|
+
end
|
202
|
+
|
203
|
+
it "returns the original response if the request is not authorized" do
|
204
|
+
response = profiler.call(env_with_param)
|
205
|
+
expect(response).to eq(
|
206
|
+
[200, { 'X-My-Header' => 'foo' }, ['hello hello']]
|
207
|
+
)
|
208
|
+
end
|
209
|
+
|
210
|
+
it "returns the profiler results if the request is authorized" do
|
211
|
+
status, headers, body = profiler.call(
|
212
|
+
env_with_param.merge('rack-profiler-allowed' => true)
|
213
|
+
)
|
214
|
+
parsed_body = JSON.parse(body.join)
|
215
|
+
expect(parsed_body).to have_key('events')
|
216
|
+
end
|
217
|
+
end
|
196
218
|
end
|
197
219
|
end
|
198
220
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-profiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Ongaro
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-01-
|
12
|
+
date: 2015-01-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|