rack-webprofiler 0.1.0.pre.beta2 → 0.1.0

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.
Files changed (38) hide show
  1. checksums.yaml +5 -13
  2. data/CHANGELOG.md +36 -12
  3. data/README.md +16 -12
  4. data/docs/DSL.md +152 -0
  5. data/docs/GettingStarted.md +51 -0
  6. data/docs/README.md +6 -0
  7. data/lib/rack/templates/assets/css/profiler.css +1 -1
  8. data/lib/rack/templates/assets/css/rwpt.css +1 -1
  9. data/lib/rack/templates/assets/sass/_variables.scss +21 -2
  10. data/lib/rack/templates/assets/sass/profiler.scss +73 -61
  11. data/lib/rack/templates/assets/sass/rwpt.scss +2 -2
  12. data/lib/rack/templates/panel/show.erb +4 -4
  13. data/lib/rack/templates/profiler.erb +4 -0
  14. data/lib/rack/web_profiler/collector.rb +197 -125
  15. data/lib/rack/web_profiler/collectors/rack_collector.rb +74 -0
  16. data/lib/rack/web_profiler/{collector/rack → collectors}/request_collector.rb +43 -60
  17. data/lib/rack/web_profiler/{collector → collectors}/ruby_collector.rb +4 -3
  18. data/lib/rack/web_profiler/{collector → collectors}/time_collector.rb +12 -6
  19. data/lib/rack/web_profiler/collectors.rb +21 -27
  20. data/lib/rack/web_profiler/config.rb +4 -9
  21. data/lib/rack/web_profiler/controller.rb +131 -126
  22. data/lib/rack/web_profiler/engine.rb +10 -14
  23. data/lib/rack/web_profiler/model.rb +74 -23
  24. data/lib/rack/web_profiler/request.rb +22 -7
  25. data/lib/rack/web_profiler/response.rb +27 -0
  26. data/lib/rack/web_profiler/rouge/html_formatter.rb +25 -0
  27. data/lib/rack/web_profiler/router.rb +11 -6
  28. data/lib/rack/web_profiler/version.rb +1 -1
  29. data/lib/rack/web_profiler/view.rb +255 -139
  30. data/lib/rack/web_profiler.rb +47 -4
  31. data/rack-webprofiler.gemspec +1 -3
  32. metadata +32 -32
  33. data/lib/rack/web_profiler/collector/debug_collector.rb +0 -31
  34. data/lib/rack/web_profiler/collector/erb_collector.rb +0 -0
  35. data/lib/rack/web_profiler/collector/performance_collector.rb +0 -1
  36. data/lib/rack/web_profiler/collector/rack/rack_collector.rb +0 -23
  37. data/lib/rack/web_profiler/collector/view.rb +0 -44
  38. data/lib/rack/web_profiler/model/collection_record.rb +0 -46
@@ -0,0 +1,25 @@
1
+ module Rack
2
+ #
3
+ class WebProfiler::Rouge::HTMLFormatter < ::Rouge::Formatter
4
+
5
+ # Initialize the Formatter.
6
+ #
7
+ # @param request [Hash]
8
+ def initialize(opts = {})
9
+ @formatter = opts[:inline_theme] \
10
+ ? ::Rouge::Formatters::HTMLInline.new(opts[:inline_theme])
11
+ : ::Rouge::Formatters::HTML.new
12
+
13
+ if opts[:line_numbers]
14
+ @formatter = ::Rouge::Formatters::HTMLTable.new(@formatter, opts)
15
+ else
16
+ @formatter = ::Rouge::Formatters::HTMLPygments.new(@formatter)
17
+ end
18
+ end
19
+
20
+ # @yield the html output.
21
+ def stream(tokens, &b)
22
+ @formatter.stream(tokens, &b)
23
+ end
24
+ end
25
+ end
@@ -28,6 +28,7 @@ module Rack
28
28
  # Route the request.
29
29
  #
30
30
  # @param request [Rack::WebProfiler::Request]
31
+ # @param path [String]
31
32
  #
32
33
  # @return [Rack::Reponse, false]
33
34
  def route(request, path)
@@ -58,8 +59,6 @@ module Rack
58
59
  request = @request.dup
59
60
  request.env[PATH_INFO] = "/#{path}"
60
61
 
61
- path_info = Utils.unescape(request.env[PATH_INFO])
62
- clean_path_info = Utils.clean_path_info(path_info)
63
62
 
64
63
  status, headers, body = rf.call(request.env)
65
64
  Rack::Response.new(body, status, headers)
@@ -71,7 +70,7 @@ module Rack
71
70
  #
72
71
  # @return [String]
73
72
  def url_for_asset(path)
74
- "#{@request.script_name}#{BASE_PATH}/assets/#{path}"
73
+ "#{get_base_path}/assets/#{path}"
75
74
  end
76
75
 
77
76
  # Get url for toobar.
@@ -80,7 +79,7 @@ module Rack
80
79
  #
81
80
  # @return [String]
82
81
  def url_for_toolbar(token)
83
- "#{@request.script_name}#{BASE_PATH}/toolbar/#{token}"
82
+ "#{get_base_path}/toolbar/#{token}"
84
83
  end
85
84
 
86
85
  # Get url for the webprofiler.
@@ -92,14 +91,20 @@ module Rack
92
91
  def url_for_profiler(token = nil, panel = nil)
93
92
  query = ""
94
93
  query = "?panel=#{panel}" unless panel.nil?
95
- "#{@request.script_name}#{BASE_PATH}/#{token}#{query}"
94
+ "#{get_base_path}/#{token}#{query}"
96
95
  end
97
96
 
98
97
  # Get url to clean webprofiler.
99
98
  #
100
99
  # @return [String]
101
100
  def url_for_clean_profiler
102
- "#{@request.script_name}#{BASE_PATH}/clean"
101
+ "#{get_base_path}/clean"
102
+ end
103
+
104
+ private
105
+
106
+ def get_base_path
107
+ "#{@request.env["ORIGINAL_SCRIPT_NAME"]}#{BASE_PATH}"
103
108
  end
104
109
  end
105
110
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class WebProfiler
3
- VERSION = "0.1.0-beta2".freeze
3
+ VERSION = "0.1.0".freeze
4
4
  end
5
5
  end
@@ -5,29 +5,53 @@ module Rack
5
5
  class WebProfiler
6
6
  # View
7
7
  class View
8
+ # Initialize a new view.
9
+ #
10
+ # @param template [String] template file path or content
11
+ # @option layout [String, nil] layout file path or content
12
+ # @option context [Rack::WebProfiler::View::Context, nil]
8
13
  def initialize(template, layout: nil, context: nil)
9
14
  @template = template
10
15
  @layout = layout
11
16
  @context = context
17
+
18
+ @erb_options = {
19
+ safe_level: nil,
20
+ trim_mode: "<>-",
21
+ eoutvar: "@_erbout",
22
+ }
12
23
  end
13
24
 
25
+ # Get the result of view rendering.
26
+ #
27
+ # @param variables [Hash, Binding] view variables
28
+ #
29
+ # @return [String]
14
30
  def result(variables = {})
15
31
  unless @template.nil?
16
32
  templates = [read_template(@template)]
17
33
  templates << read_template(@layout) unless @layout.nil?
18
34
 
19
- content = templates.inject(nil) do |prev, temp|
35
+ templates.inject(nil) do |prev, temp|
20
36
  render(temp, variables) { prev }
21
37
  end
22
38
  end
23
39
  end
24
40
 
41
+ # Get the context.
42
+ #
43
+ # @return [Rack::WebProfiler::View::Context]
25
44
  def context
26
45
  @context ||= Context.new
27
46
  end
28
47
 
29
- private
48
+ protected
30
49
 
50
+ # Read a template. Returns file content if template is a file path.
51
+ #
52
+ # @param template [String] template file path or content
53
+ #
54
+ # @return [String]
31
55
  def read_template(template)
32
56
  unless template.empty?
33
57
  path = ::File.expand_path("../../templates/#{template}", __FILE__)
@@ -36,36 +60,35 @@ module Rack
36
60
  template
37
61
  end
38
62
 
39
- def options
40
- @options ||= {
41
- :safe_level => nil,
42
- :trim_mode => '%-',
43
- :eoutvar => '@_erbout',
44
- }
45
- end
46
-
63
+ # Render view.
64
+ #
65
+ # @param str [String] view content
66
+ # @param variables [Hash, Binding] view variables
67
+ #
68
+ # @return [String]
69
+ #
70
+ # @todo better error when there is an ERB error.
47
71
  def render(str, variables = {})
48
- opts = options
49
-
50
72
  format_variables(variables).each do |name, value|
51
73
  context.instance_variable_set("@#{name}", value)
52
74
  end
53
75
 
76
+ erb = ::ERB.new(str, *@erb_options.values_at(:safe_level, :trim_mode, :eoutvar))
77
+
54
78
  context.instance_eval do
55
- erb = ::ERB.new(str, *opts.values_at(:safe_level, :trim_mode, :eoutvar))
56
- erb.result(binding).sub(/\A\n/, '')
79
+ erb.result(binding).sub(/\A\n/, "")
57
80
  end
58
- # @todo better error when there is an ERB error.
59
81
  end
60
82
 
83
+ # Format variables to inject them into view context.
84
+ #
85
+ # @param v [Hash, Binding] variables
86
+ #
87
+ # @return [Hash]
61
88
  def format_variables(v)
62
89
  case v
63
90
  when Binding
64
- h = {}
65
- v.eval("instance_variables").each do |k|
66
- h[k.to_s.sub(/^@/, '')] = v.eval("instance_variable_get(:#{k})")
67
- end
68
- h
91
+ binding_to_hash(v)
69
92
  when Hash
70
93
  v
71
94
  else
@@ -73,163 +96,256 @@ module Rack
73
96
  end
74
97
  end
75
98
 
76
- # CommonHelpers.
77
- module CommonHelpers
78
- def content_for(key, content = nil, &block)
79
- block ||= proc { |*| content }
80
- content_blocks[key.to_sym] << capture_later(&block)
81
- end
82
-
83
- def content_for?(key)
84
- content_blocks[key.to_sym].any?
99
+ # Returns a [Hash] from a [Binding].
100
+ #
101
+ # @param v [Binding]
102
+ #
103
+ # @return [Hash]
104
+ def binding_to_hash(v)
105
+ h = {}
106
+ v.eval("instance_variables").each do |k|
107
+ h[k.to_s.sub(/^@/, "")] = v.eval("instance_variable_get(:#{k})")
85
108
  end
109
+ h
110
+ end
86
111
 
87
- def yield_content(key, default = nil)
88
- return default if content_blocks[key.to_sym].empty?
89
- content_blocks[key.to_sym].map { |b| capture(&b) }.join
90
- end
91
-
92
- #
93
- def partial(path, variables: nil)
94
- return "" if path.nil?
95
-
96
- variables ||= binding if variables.nil?
97
-
98
- capture do
99
- WebProfiler::View.new(path, context: self).result(variables)
112
+ # Helpers.
113
+ module Helpers
114
+ # Common helpers.
115
+ module Common
116
+ def content_for(key, content = nil, &block)
117
+ block ||= proc { |*| content }
118
+ content_blocks[key.to_sym] << capture_later(&block)
100
119
  end
101
- end
102
120
 
103
- #
104
- def h(obj)
105
- case obj
106
- when String
107
- ::ERB::Util.html_escape(obj)
108
- else
109
- ::ERB::Util.html_escape(obj.inspect)
121
+ def content_for?(key)
122
+ content_blocks[key.to_sym].any?
110
123
  end
111
- end
112
124
 
113
- #
114
- def highlight(code: nil, language: nil)
115
- language = language.to_sym if language.is_a? String
116
-
117
- case language
118
- when :ruby
119
- lexer = Rouge::Lexers::Ruby.new
120
- when :json
121
- lexer = Rouge::Lexers::Jsonnet.new
122
- when :xml
123
- lexer = Rouge::Lexers::XML.new
124
- else
125
- lexer = Rouge::Lexers::PlainText.new
125
+ def yield_content(key, default = nil)
126
+ return default if content_blocks[key.to_sym].empty?
127
+ content_blocks[key.to_sym].map { |b| capture(&b) }.join
126
128
  end
127
129
 
128
- code = capture(&Proc.new) if block_given?
130
+ # Render a partial view.
131
+ #
132
+ # @param path [String] path to partial
133
+ # @option variables [Hash, nil] variables for partial
134
+ #
135
+ # @return [String]
136
+ def partial(path, variables: nil)
137
+ return "" if path.nil?
129
138
 
130
- formatter = Rouge::Formatters::HTML.new
131
- formatter = Rouge::Formatters::HTMLPygments.new(formatter, css_class='highlight')
139
+ variables ||= binding if variables.nil?
132
140
 
133
- "<div class=\"highlight\">#{formatter.format(lexer.lex(code))}</div>"
134
- end
141
+ capture do
142
+ WebProfiler::View.new(path, context: self).result(variables)
143
+ end
144
+ end
135
145
 
136
- def capture(&block)
137
- @capture = nil
138
- @_erbout, _buf_was = '', @_erbout
139
- result = yield
140
- @_erbout = _buf_was
141
- result.strip.empty? && @capture ? @capture : result
142
- end
146
+ # Escape html.
147
+ #
148
+ # @param obj
149
+ #
150
+ # @return [String]
151
+ def h(obj)
152
+ case obj
153
+ when String
154
+ ::ERB::Util.html_escape(obj)
155
+ else
156
+ ::ERB::Util.html_escape(obj.inspect)
157
+ end
158
+ end
143
159
 
144
- private
160
+ # Highlight text.
161
+ #
162
+ # @option code [String]
163
+ # @option mimetype [String, nil]
164
+ # @option language [String, nil]
165
+ # @option formatter_opts [Hash]
166
+ #
167
+ # @yield code.
168
+ #
169
+ # @return [String]
170
+ def highlight(code: "", mimetype: nil, language: nil, formatter_opts: {})
171
+ language = language.to_s if language.is_a? Symbol
172
+
173
+ lexer = ::Rouge::Lexer.guess(mimetype: mimetype) if mimetype.is_a? String
174
+ lexer = ::Rouge::Lexer.find_fancy(language) if language.is_a? String
175
+ lexer ||= ::Rouge::Lexers::PlainText.new
176
+
177
+ code = capture(&Proc.new) if block_given?
178
+ code ||= ""
179
+
180
+ formatter = WebProfiler::Rouge::HTMLFormatter.new(formatter_opts)
181
+
182
+ "<div class=\"highlight\">#{formatter.format(lexer.lex(code))}</div>"
183
+ end
145
184
 
146
- def capture_later(&block)
147
- proc { |*| @capture = capture(&block) }
148
- end
185
+ #
186
+ #
187
+ # @yield
188
+ def capture(&block)
189
+ @capture = nil
190
+ buf_was = @_erbout
191
+ @_erbout = ""
149
192
 
150
- def content_blocks
151
- @content_blocks ||= Hash.new {|h,k| h[k] = [] }
152
- end
153
- end
193
+ result = yield
154
194
 
155
- # CollectorHelpers.
156
- module CollectorHelpers
195
+ @_erbout = buf_was
196
+ result.strip.empty? && @capture ? @capture : result
197
+ end
157
198
 
158
- #
159
- def collector_status(collector, collection)
160
- collector_data_storage(collector, collection, :status)
161
- end
199
+ #
200
+ #
201
+ # @yield
202
+ def capture_later(&block)
203
+ proc { |*| @capture = capture(&block) }
204
+ end
205
+
206
+ private
162
207
 
163
- #
164
- def collector_datas(collector, collection)
165
- collector_data_storage(collector, collection, :datas)
208
+ #
209
+ #
210
+ # @return [Hash]
211
+ def content_blocks
212
+ @content_blocks ||= Hash.new { |h, k| h[k] = [] }
213
+ end
166
214
  end
167
215
 
168
- def collector_tab(collector, collection)
169
- return nil unless is_collection_contains_datas_for_collector?(collection, collector)
216
+ # Collector helpers.
217
+ module Collector
218
+ # Get collector status from a collection.
219
+ #
220
+ # @param collector [Rack::WebProfiler::Collector::Definition]
221
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
222
+ #
223
+ # @return [Symbol, nil]
224
+ def collector_status(collector, collection)
225
+ collector_data_storage(collector, collection, :status)
226
+ end
170
227
 
171
- c = collector_view_context(collector, collection)
172
- c.tab_content
173
- end
228
+ #
229
+ #
230
+ # @param collector [Rack::WebProfiler::Collector::Definition]
231
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
232
+ def collector_datas(collector, collection)
233
+ collector_data_storage(collector, collection, :datas)
234
+ end
174
235
 
175
- def collector_panel(collector, collection)
176
- return nil unless is_collection_contains_datas_for_collector?(collection, collector)
236
+ #
237
+ # @param collector [Rack::WebProfiler::Collector::Definition]
238
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
239
+ def collector_tab(collector, collection)
240
+ return nil unless collection_contains_datas_for_collector?(collection, collector)
177
241
 
178
- c = collector_view_context(collector, collection)
179
- c.panel_content
180
- end
242
+ c = collector_view_context(collector, collection)
243
+ c.tab_content
244
+ end
181
245
 
182
- def collector_has_tab?(collector, collection)
183
- collector_data_storage(collector, collection, :show_tab)
184
- end
246
+ #
247
+ # @param collector [Rack::WebProfiler::Collector::Definition]
248
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
249
+ def collector_panel(collector, collection)
250
+ return nil unless collection_contains_datas_for_collector?(collection, collector)
185
251
 
186
- def collector_has_panel?(collector, collection)
187
- collector_data_storage(collector, collection, :show_panel)
188
- end
252
+ c = collector_view_context(collector, collection)
253
+ c.panel_content
254
+ end
189
255
 
190
- private
256
+ #
257
+ # @param collector [Rack::WebProfiler::Collector::Definition]
258
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
259
+ def collector_has_tab?(collector, collection)
260
+ collector_data_storage(collector, collection, :show_tab)
261
+ # !collector_tab(collector, collection).nil?
262
+ end
191
263
 
192
- def collector_view_context(collector, collection)
193
- collectors_view_context[collector.name] ||= begin
194
- v = WebProfiler::Collector::View.new(collector.template)
195
- v.result(collector: collector, collection: collection)
196
- v.context
264
+ #
265
+ # @param collector [Rack::WebProfiler::Collector::Definition]
266
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
267
+ def collector_has_panel?(collector, collection)
268
+ collector_data_storage(collector, collection, :show_panel)
269
+ # !collector_panel(collector, collection).nil?
197
270
  end
198
- end
199
271
 
200
- def collector_data_storage(collector, collection, key = nil)
201
- return nil unless is_collection_contains_datas_for_collector?(collection, collector)
272
+ private
273
+
274
+ # Get a collector view Context.
275
+ #
276
+ # @param collector [Rack::WebProfiler::Collector::Definition]
277
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
278
+ #
279
+ # @return [Rack::WebProfiler::View::Context]
280
+ def collector_view_context(collector, collection)
281
+ collectors_view_context[collector.identifier] ||= begin
282
+ v = WebProfiler::Collector::View.new(collector.template)
283
+ v.result(collector: collector, collection: collection)
284
+ v.context
285
+ end
286
+ end
202
287
 
203
- storage = collection.datas[collector.name.to_sym]
204
- storage[key] if !key.nil? && storage.has_key?(key)
205
- end
288
+ #
289
+ #
290
+ # @param collector [Rack::WebProfiler::Collector::Definition]
291
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
292
+ # @param key [Symbol, String]
293
+ #
294
+ # @return
295
+ def collector_data_storage(collector, collection, key = nil)
296
+ return nil unless collection_contains_datas_for_collector?(collection, collector)
297
+
298
+ storage = collection.datas[collector.identifier.to_sym]
299
+ storage[key] if !key.nil? && storage.key?(key)
300
+ end
206
301
 
207
- def is_valid_collector?(collector)
208
- !collector.nil? \
209
- && collector.kind_of?(WebProfiler::Collector::Definition)
210
- end
302
+ # Check if collector is valid.
303
+ #
304
+ # @param collector [Rack::WebProfiler::Collector::Definition]
305
+ #
306
+ # @return [Boolean]
307
+ def valid_collector?(collector)
308
+ !collector.nil? \
309
+ && collector.is_a?(WebProfiler::Collector::Definition)
310
+ end
211
311
 
212
- def is_valid_collection?(collection)
213
- !collection.nil? \
214
- && collection.kind_of?(WebProfiler::Model::CollectionRecord)
215
- end
312
+ # Check if collection is valid.
313
+ #
314
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
315
+ #
316
+ # @return [Boolean]
317
+ def valid_collection?(collection)
318
+ !collection.nil? \
319
+ && collection.is_a?(WebProfiler::Model::CollectionRecord)
320
+ end
216
321
 
217
- def is_collection_contains_datas_for_collector?(collection, collector)
218
- is_valid_collector?(collector) \
219
- && is_valid_collection?(collection) \
220
- && collection.datas.has_key?(collector.name.to_sym)
221
- end
322
+ # @param collector [Rack::WebProfiler::Collector::Definition]
323
+ # @param collection [Rack::WebProfiler::Model::CollectionRecord]
324
+ #
325
+ # @return [Boolean]
326
+ def collection_contains_datas_for_collector?(collection, collector)
327
+ valid_collector?(collector) \
328
+ && valid_collection?(collection) \
329
+ && collection.datas.key?(collector.identifier.to_sym)
330
+ end
222
331
 
223
- private
332
+ private
224
333
 
225
- def collectors_view_context
226
- @collectors_view_context ||= {}
334
+ # Get the collectors view context.
335
+ #
336
+ # @return [Hash]
337
+ def collectors_view_context
338
+ @collectors_view_context ||= {}
339
+ end
227
340
  end
228
341
  end
229
342
 
343
+ # View Context.
230
344
  class Context
231
- include CommonHelpers
232
- include CollectorHelpers
345
+
346
+ # Include helpers into the Context.
347
+ include Helpers::Common
348
+ include Helpers::Collector
233
349
  end
234
350
  end
235
351
  end
@@ -10,29 +10,69 @@ module Rack
10
10
  autoload :Controller, "rack/web_profiler/controller"
11
11
  autoload :Engine, "rack/web_profiler/engine"
12
12
  autoload :Model, "rack/web_profiler/model"
13
+ autoload :Response, "rack/web_profiler/response"
13
14
  autoload :Request, "rack/web_profiler/request"
14
15
  autoload :Router, "rack/web_profiler/router"
15
16
  autoload :View, "rack/web_profiler/view"
16
17
 
18
+ # Classes about Rouge gem customization.
19
+ module Rouge
20
+ autoload :HTMLFormatter, "rack/web_profiler/rouge/html_formatter"
21
+ end
22
+
23
+ # Env key constants.
24
+ ENV_RUNTIME_START = "rack_webprofiler.runtime_start".freeze
25
+ ENV_RUNTIME = "rack_webprofiler.runtime".freeze
26
+ ENV_EXCEPTION = "rack_webprofiler.exception".freeze
27
+
17
28
  class << self
29
+ # Configure the WebProfiler.
30
+ #
31
+ # @yield the Config object.
32
+ #
33
+ # @return [Rack::WebProfiler::Config]
18
34
  def config
19
35
  @config ||= Config.new
20
36
  @config.build!(&Proc.new) if block_given?
21
37
  @config
22
38
  end
23
39
 
40
+ # Register one or many collectors.
41
+ #
42
+ # @param collector_class [Array, Class]
24
43
  def register_collector(collector_class)
25
44
  config.collectors.add_collector collector_class
26
45
  end
46
+ alias register_collectors register_collector
27
47
 
48
+ # Unregister one or many collectors.
49
+ #
50
+ # @param collector_class [Array, Class]
28
51
  def unregister_collector(collector_class)
29
52
  config.collectors.remove_collector collector_class
30
53
  end
54
+ alias unregister_collectors unregister_collector
55
+
56
+ def data(k = nil, v = :undefined)
57
+ @data ||= {}
58
+
59
+ return @data if k === nil
60
+
61
+ @data[k] = v unless v === :undefined
62
+ @data[k] if @data.key?(k)
63
+ end
64
+
65
+ def reset_data!
66
+ @data = {}
67
+ end
31
68
  end
32
69
 
70
+ attr_reader :data
71
+
33
72
  # Initialize
34
73
  #
35
74
  # @param app [Proc]
75
+ # @option tmp_dir [String]
36
76
  def initialize(app, tmp_dir: nil)
37
77
  @app = app
38
78
 
@@ -46,9 +86,11 @@ module Rack
46
86
  #
47
87
  # @return [Array]
48
88
  def call(env)
89
+ WebProfiler.reset_data!
90
+
49
91
  begin
50
92
  request = WebProfiler::Request.new(env)
51
- request.start_runtime!
93
+ env[ENV_RUNTIME_START] = Time.now.to_f
52
94
 
53
95
  response = WebProfiler::Router.response_for(request)
54
96
  return response.finish if response.is_a? Rack::Response
@@ -74,10 +116,11 @@ module Rack
74
116
  #
75
117
  # @return [Rack::Response]
76
118
  def process(request, body, status, headers, exception = nil)
77
- request.save_runtime!
119
+ request.env[ENV_RUNTIME] = Time.now.to_f - request.env[ENV_RUNTIME_START]
120
+ request.env[ENV_EXCEPTION] = nil
78
121
 
79
- unless exception.nil?
80
- request.save_exception(exception)
122
+ if !exception.nil?
123
+ request.env[ENV_EXCEPTION] = exception
81
124
  WebProfiler::Engine.process_exception(request).finish
82
125
  else
83
126
  WebProfiler::Engine.process(request, body, status, headers).finish