rack-profiler 0.0.3 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f67856e0027806b21c8fa11c400055049be97e5f
4
- data.tar.gz: 50a680263ec4263e64cf53f63ff991bed6d6bd8e
3
+ metadata.gz: 10111d8a7faa32f82444b864868a3364a4c557b3
4
+ data.tar.gz: b77adab1e71c584c5075da95b8eb60f737c84d79
5
5
  SHA512:
6
- metadata.gz: 8df8668240edd5c83482b5f9c67efd68c191af79fc279eb6f704af00139ad98a1b219f4cfa8c481ec557b6761be64f8891d1b09cdb754a1833fa442653c03875
7
- data.tar.gz: 18c2d0048b5bc978d7937ca24b8d727ef2b815f00e1a097cbfca81538c33ecf5ef799ef86435e0728ab828fe41a6c61c3e5f9a1a8c58a69a375c7540eaf1910d
6
+ metadata.gz: 3306764da5aa9f681a1025ce5a0c43ea7cd08d210b8813e0a8e9ff7ab93ab7551ffdf11305479a28f7889e2641a0207170e32ed21e84b6c27117580529494514
7
+ data.tar.gz: 0647b6ba8a86a09f3d45e2d71c3c71164d494637364cdfdb8af90865ab1a488affc1fe115c9d2530f39f18af3ae53e638bf9b15f3a3e950a594a9d4d8d290fde
data/README.md CHANGED
@@ -1,6 +1,21 @@
1
1
  # Rack::Profiler
2
2
 
3
- Simple profiler for Rack applications
3
+ Simple profiler for Rack applications (Sinatra and Ruby on Rails for example).
4
+
5
+ `Rack::Profiler` uses the [Active Support Instrumentation API](http://guides.rubyonrails.org/active_support_instrumentation.html)
6
+ and subscribes to the following hooks:
7
+
8
+ * [sql.active_record](http://guides.rubyonrails.org/active_support_instrumentation.html#sql-active-record)
9
+ * [render_template.action_view](http://guides.rubyonrails.org/active_support_instrumentation.html#render_template.action_view)
10
+ * [render_partial.action_view](http://guides.rubyonrails.org/active_support_instrumentation.html#render_partial.action_view)
11
+ * [process_action.action_controller](http://guides.rubyonrails.org/active_support_instrumentation.html#process_action.action_controller)
12
+
13
+ You can also define your own events, by wrapping your code with the
14
+ [`Rack::Profiler.step`](#custom-steps).
15
+
16
+ `Rack::Profiler` is easy to integrate in any Rack application and it produces a
17
+ JSON response with the results. It also exposes a simple web dashboard to directly
18
+ issue HTTP requests to your application and see the results of the profiling.
4
19
 
5
20
  ## Installation
6
21
 
@@ -10,6 +25,8 @@ Add this line to your application's Gemfile:
10
25
  gem 'rack-profiler'
11
26
  ```
12
27
 
28
+ *You might want to put the gem in the development group if you are using Rails.*
29
+
13
30
  And then execute:
14
31
 
15
32
  $ bundle
@@ -18,7 +35,7 @@ Or install it yourself as:
18
35
 
19
36
  $ gem install rack-profiler
20
37
 
21
- ## Usage
38
+ ### Rack/Sinatra
22
39
 
23
40
  In your `config.ru` use the `Rack::Profiler` middleware at the beginning of your
24
41
  middleware stack:
@@ -28,21 +45,31 @@ require 'rack/profiler'
28
45
  use Rack::Profiler
29
46
  ```
30
47
 
31
- By default `Rack::Profiler` will subscribe to `ActiveRecord` SQL queries and to
32
- steps you define in your code with:
48
+ ### Rails
49
+
50
+ You can add the `Rack::Profiler` middleware at the beginning of your `config.ru`
51
+ like in the Rack/Sinatra installation or insert it in the middlewares stack configuration
52
+ in the `application.rb`:
33
53
 
34
54
  ```ruby
35
- Rack::Profiler.step('your-step-name') do
36
- # Do stuff. The profiler will tell you how long it took to perform this step
55
+ module YourApp
56
+ class Application < Rails::Application
57
+
58
+ # ...
59
+ config.middleware.insert_before Rack::Runtime, Rack::Profiler
60
+
61
+ end
37
62
  end
38
63
  ```
39
64
 
40
- You can also subscribe to more notifications:
65
+ ## Configuration
66
+
67
+ You can configure `Rack::Profiler` to subscribe to more notifications:
41
68
 
42
69
  ```ruby
43
- Rack::Profiler.configure do |profiler|
44
- # Subscribe to template rendering in a Rails app
45
- profiler.subscribe('render_template.action_view')
70
+ Rack::Profiler.configure do |config|
71
+ # Subscribe to email delivery in a Rails app
72
+ config.subscribe('deliver.action_mailer')
46
73
  end
47
74
  ```
48
75
 
@@ -50,12 +77,52 @@ You can also specify a backtrace filter to exclude lines that are not
50
77
  interesting:
51
78
 
52
79
  ```ruby
53
- Rack::Profiler.configure do |profiler|
80
+ Rack::Profiler.configure do |config|
54
81
  # Exclude gems from the backtrace
55
- profiler.filter_backtrace { |line| !line.include? '/gems/' }
82
+ config.filter_backtrace { |line| !line.include? '/gems/' }
56
83
  end
57
84
  ```
58
85
 
86
+ You can put these configurations in your `config.ru` for a Rack/Sinatra application
87
+ or in an initializer `config/rack_profiler.rb` for Rails apps.
88
+
89
+ ## Usage
90
+
91
+ ### Custom steps
92
+
93
+ By default `Rack::Profiler` will subscribe to `ActiveRecord` SQL queries,
94
+ `ActionView` rendering events (templates and partials), `ActionController`
95
+ actions and to steps you define in your code with:
96
+
97
+ ```ruby
98
+ Rack::Profiler.step('your-step-name') do
99
+ # Do stuff. The profiler will tell you how long it took to perform this step
100
+ end
101
+ ```
102
+
103
+ ### Web Dashboard
104
+
105
+ A graphical interface to profile your application pages/endpoints and display the
106
+ results is automatically mounted at this route:
107
+
108
+ http://<your-app-url>/rack-profiler
109
+
110
+ Just select the HTTP verb, insert the relative path to your app and add some
111
+ optional parameters like POST/PUT data: `Rack::Profiler` automatically send
112
+ the request to your app with the `rack-profiler` param and display the
113
+ results in a nice graphical way.
114
+
115
+
116
+ ### Raw JSON result
117
+
118
+ If you want to access the results of the profiling as raw JSON data, you can just
119
+ add the `rack-profiler` parameter (it can be null) to any HTTP request
120
+ to your app (GET, POST, PUT, PATCH, DELETE): `Rack::Profiler` will execute the
121
+ request and return a JSON response containing the results along with the
122
+ original response.
123
+
124
+ http://<your-app-url>/<path>?rack-profiler
125
+
59
126
  ## Contributing
60
127
 
61
128
  1. Fork it ( https://github.com/dawanda/rack-profiler/fork )
@@ -1,3 +1,5 @@
1
+ require "rack"
2
+ require "rack/request"
1
3
  require "rack/profiler/version"
2
4
  require "active_support/notifications"
3
5
 
@@ -6,22 +8,12 @@ module Rack
6
8
  class DummyError < StandardError; end
7
9
 
8
10
  module ClassMethods
9
- attr_reader :backtrace_filter
10
-
11
11
  def configure(&block)
12
- instance_exec(self, &block)
13
- end
14
-
15
- def filter_backtrace(&block)
16
- @backtrace_filter = block
12
+ block.call(config)
17
13
  end
18
14
 
19
- def dashboard_path=(path)
20
- @dashboard_path = path
21
- end
22
-
23
- def dashboard_path
24
- @dashboard_path || '/rack-profiler'
15
+ def config
16
+ @config ||= Configuration.new
25
17
  end
26
18
 
27
19
  def step(name, payload = {})
@@ -29,37 +21,42 @@ module Rack
29
21
  yield
30
22
  end
31
23
  end
24
+ end
25
+
26
+ class Configuration
27
+ attr_reader :subscriptions, :backtrace_filter
28
+ attr_accessor :dashboard_path
29
+
30
+ DEFAULT_SUBSCRIPTIONS = ['sql.active_record',
31
+ 'render_template.action_view',
32
+ 'render_partial.action_view',
33
+ 'process_action.action_controller',
34
+ 'rack-profiler.total_time',
35
+ 'rack-profiler.step']
32
36
 
33
- def render_dashboard
34
- dashboard = ::File.expand_path( '../../public/rack-profiler.html', ::File.dirname( __FILE__ ) )
35
- body = ::File.open(dashboard, ::File::RDONLY)
36
- [200, { 'Content-Type' => 'text/html' }, body]
37
+ def initialize
38
+ @subscriptions = DEFAULT_SUBSCRIPTIONS.clone
39
+ @dashboard_path = '/rack-profiler'
37
40
  end
38
41
 
39
- def subscribe(name)
40
- (@subscriptions ||= []) << name
42
+ def subscribe(*names)
43
+ names.each { |name| @subscriptions << name }
41
44
  @subscriptions.uniq!
42
45
  end
43
46
 
44
- def subscriptions
45
- @subscriptions || []
47
+ def filter_backtrace(&block)
48
+ @backtrace_filter = block
46
49
  end
47
50
  end
48
51
 
49
52
  extend ClassMethods
50
53
 
51
- # Subscribe to interesting events
52
- subscribe('sql.active_record')
53
- subscribe('render_template.action_view')
54
- subscribe('render_partial.action_view')
55
- subscribe('process_action.action_controller')
56
- subscribe('rack-profiler.step')
57
-
58
54
  attr_reader :events
59
55
 
60
56
  def initialize(app)
61
- subscribe_all_events
62
- @app = app
57
+ subscribe_to_all
58
+ @events = []
59
+ @app = app
63
60
  end
64
61
 
65
62
  def call(env)
@@ -67,13 +64,22 @@ module Rack
67
64
  status, headers, body = [nil, nil, nil]
68
65
  req = Rack::Request.new(env)
69
66
 
70
- if req.path == Profiler.dashboard_path
71
- Profiler.render_dashboard
67
+ if req.path == config.dashboard_path
68
+ render_dashboard
72
69
  elsif req.params.has_key?('rack-profiler')
73
- Profiler.step('total_time') do
70
+ ActiveSupport::Notifications.instrument('rack-profiler.total_time') do
74
71
  status, headers, body = @app.call(env)
75
72
  end
76
- [200, { 'Content-Type' => 'application/json' }, [{ events: nested_events, response: { status: status, headers: headers, body: stringify_body(body) } }.to_json]]
73
+ [ 200,
74
+ { 'Content-Type' => 'application/json' },
75
+ [ { events: events.sort_by { |event| event[:start] },
76
+ response: {
77
+ status: status,
78
+ headers: headers,
79
+ body: stringify_body(body)
80
+ }
81
+ }.to_json ]
82
+ ]
77
83
  else
78
84
  @status, @headers, @body = @app.call(env)
79
85
  end
@@ -95,28 +101,23 @@ module Rack
95
101
  end
96
102
  end
97
103
 
98
- def nested_events
99
- events.sort_by { |evt| evt[:start] }.reduce([]) do |list, evt|
100
- nest_event(list, list, evt)
101
- end
104
+ def config
105
+ self.class.config
102
106
  end
103
107
 
104
108
  private
105
109
 
106
- def subscribe_all_events
107
- self.class.subscriptions.each do |event|
108
- subscribe(event)
109
- end
110
+ def render_dashboard
111
+ dashboard = ::File.expand_path( '../../public/rack-profiler.html', ::File.dirname( __FILE__ ) )
112
+ body = ::File.open(dashboard, ::File::RDONLY)
113
+ [200, { 'Content-Type' => 'text/html' }, body]
110
114
  end
111
115
 
112
- def nest_event(list, children, evt)
113
- previous = children.last
114
- if previous && evt[:finish] <= previous[:finish]
115
- nest_event(list, previous[:children] ||= [], evt)
116
- else
117
- children << evt
116
+ def subscribe_to_all
117
+ # Subscribe to interesting events
118
+ config.subscriptions.each do |event|
119
+ subscribe(event)
118
120
  end
119
- list
120
121
  end
121
122
 
122
123
  def tap_backtrace
@@ -128,17 +129,17 @@ module Rack
128
129
  end
129
130
 
130
131
  def filtered_backtrace(backtrace)
131
- if self.class.backtrace_filter.nil?
132
+ if config.backtrace_filter.nil?
132
133
  backtrace
133
134
  else
134
- backtrace.select(&self.class.backtrace_filter)
135
+ backtrace.select(&config.backtrace_filter)
135
136
  end
136
137
  end
137
138
 
138
139
  def stringify_body(body)
139
140
  body.close if body.respond_to?(:close)
140
141
  str = ""
141
- body.each {|part| str << part }
142
+ body.each { |part| str << part }
142
143
  str
143
144
  end
144
145
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class Profiler
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
5
5
  end
@@ -16,6 +16,9 @@
16
16
  .response-info {
17
17
  margin-bottom: 1em;
18
18
  }
19
+ .response-info pre {
20
+ max-height: 350px;
21
+ }
19
22
 
20
23
  .pr-steps td:first-child {
21
24
  width: 800px;
@@ -23,7 +26,7 @@
23
26
 
24
27
  .step-bar {
25
28
  display: inline-block;
26
- background: #5bc0de;
29
+ background: #777;
27
30
  position: relative;
28
31
  box-sizing: border-box;
29
32
  margin-top: 0.2em;
@@ -31,6 +34,10 @@
31
34
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15)
32
35
  }
33
36
 
37
+ .step-bar.step-type-step {
38
+ background: #5bc0de;
39
+ }
40
+
34
41
  .step-bar.step-type-sql {
35
42
  background: #f0ad4e;
36
43
  }
@@ -51,6 +58,7 @@
51
58
  background-color: #f5f5f5;
52
59
  border: 1px solid #ccc;
53
60
  border-radius: 4px;
61
+ overflow-wrap: break-word;
54
62
  }
55
63
 
56
64
  .key-value-list li {
@@ -237,8 +245,11 @@
237
245
  .done(function( data, status, xhr ) {
238
246
  $(".stats").show()
239
247
 
240
- var rootEvent = data.events[0],
241
- queryCount = 0,
248
+ var rootEvent = data.events.filter(function(event) {
249
+ return event.name == 'rack-profiler.total_time'
250
+ })[0]
251
+
252
+ var queryCount = 0,
242
253
  headersKeyVal = exposeKeyValues( data.response.headers ),
243
254
  responseWrap = $.extend( {}, data.response, { headers: headersKeyVal } )
244
255
 
@@ -270,6 +281,7 @@
270
281
  case 'render_template.action_view': eventType = 'render-template'; break;
271
282
  case 'process_action.action_controller': eventType = 'process-action'; break;
272
283
  case 'rack-profiler.step': eventType = 'step'; break;
284
+ case 'rack-profiler.total_time': eventType = 'total-time'; break;
273
285
  default: eventType = 'other'
274
286
  }
275
287
 
@@ -285,10 +297,6 @@
285
297
  }
286
298
  $(".pr-steps tbody").append( Mustache.render( stepTmpl, stepEvent ) )
287
299
 
288
- // Recurse on children
289
- if ( event.children ) {
290
- renderEvents( event.children )
291
- }
292
300
  })
293
301
  }
294
302
 
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "rack"
21
22
  spec.add_dependency "activesupport", ">= 3.0.0"
22
23
 
23
24
  spec.add_development_dependency "bundler", "~> 1.7"
@@ -1,55 +1,50 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
+ require 'json'
3
+
4
+ def trigger_dummy_event(name, payload = {})
5
+ ActiveSupport::Notifications.instrument(name, payload) do
6
+ "do stuff"
7
+ end
8
+ end
2
9
 
3
10
  describe Rack::Profiler do
4
11
  let(:profiler) { Rack::Profiler.new(nil) }
5
12
 
6
- def trigger_dummy_event(name, payload = {})
7
- ActiveSupport::Notifications.instrument(name, payload) do
8
- "do stuff"
9
- end
13
+ it "has a version number" do
14
+ expect(Rack::Profiler::VERSION).not_to be_nil
10
15
  end
11
16
 
12
- it 'has a version number' do
13
- expect(Rack::Profiler::VERSION).not_to be nil
14
- end
17
+ describe :initialize do
18
+ it "subscribes to all subscriptions" do
19
+ config = Rack::Profiler::Configuration.new
20
+ config.subscribe("bar")
21
+ allow(Rack::Profiler).to receive(:config).and_return(config)
15
22
 
16
- describe :nested_events do
17
- it "returns events properly nested" do
18
- evt1 = { start: 1, finish: 10 }
19
- evt2 = { start: 2, finish: 3 }
20
- evt3 = { start: 4, finish: 8 }
21
- evt4 = { start: 5, finish: 8 }
22
- evt5 = { start: 9, finish: 10 }
23
- evts = [evt1, evt2, evt3, evt4, evt5]
24
- allow(profiler).to receive(:events).and_return(evts)
25
- nested = profiler.nested_events
26
- expect(nested.first).to be(evt1)
27
- expect(evt1[:children].first).to be(evt2)
28
- expect(evt1[:children][1]).to be(evt3)
29
- expect(evt3[:children].first).to be(evt4)
30
- expect(evt1[:children].last).to be(evt5)
23
+ profiler = Rack::Profiler.new(nil)
24
+ trigger_dummy_event("bar")
25
+ expect(profiler.events.last[:name]).to eq("bar")
31
26
  end
32
27
  end
33
28
 
34
29
  describe :subscribe do
35
30
  before do
36
- profiler.subscribe('foo')
31
+ profiler.subscribe("foo")
37
32
  end
38
33
 
39
- it "subscribe to event populating the event list" do
40
- trigger_dummy_event('foo')
34
+ it "subscribes to event populating the event list" do
35
+ trigger_dummy_event("foo")
41
36
  event = profiler.events.last
42
- expect(event[:name]).to eq('foo')
37
+ expect(event[:name]).to eq("foo")
43
38
  end
44
39
 
45
- it "populate event with the proper keys" do
46
- trigger_dummy_event('foo')
40
+ it "populates event with the proper keys" do
41
+ trigger_dummy_event("foo")
47
42
  event = profiler.events.last
48
43
  expect(event.keys).to include(:id, :name, :start, :finish, :duration, :payload, :backtrace)
49
44
  end
50
45
 
51
46
  it "adds the backtrace" do
52
- trigger_dummy_event('foo')
47
+ trigger_dummy_event("foo")
53
48
  event = profiler.events.last
54
49
  expect(event[:backtrace].any? do |line|
55
50
  line.include?("trigger_dummy_event")
@@ -57,10 +52,10 @@ describe Rack::Profiler do
57
52
  end
58
53
 
59
54
  it "filters the backtrace if a filter was provided" do
60
- Rack::Profiler.filter_backtrace do |line|
55
+ Rack::Profiler.config.filter_backtrace do |line|
61
56
  !line.include?("trigger_dummy_event")
62
57
  end
63
- trigger_dummy_event('foo')
58
+ trigger_dummy_event("foo")
64
59
  event = profiler.events.last
65
60
  expect(event[:backtrace].any? do |line|
66
61
  line.include?("trigger_dummy_event")
@@ -71,37 +66,175 @@ describe Rack::Profiler do
71
66
  end
72
67
 
73
68
  it "adds the payload" do
74
- trigger_dummy_event('foo', bar: 'baz')
69
+ trigger_dummy_event("foo", bar: "baz")
75
70
  event = profiler.events.last
76
- expect(event[:payload]).to eq(bar: 'baz')
71
+ expect(event[:payload]).to eq(bar: "baz")
77
72
  end
78
73
  end
79
74
 
80
- describe ".subscribe" do
81
- it "causes any newly created instance to subscribe to the given event" do
82
- Rack::Profiler.subscribe('bar')
83
- profiler = Rack::Profiler.new(nil)
84
- trigger_dummy_event('bar')
85
- event = profiler.events.last
86
- expect(event[:name]).to eq('bar')
75
+ describe :call do
76
+ let(:app) do
77
+ Proc.new { |env|
78
+ Rack::Profiler.step 'foo' do
79
+ [200, { 'X-My-Header' => 'foo' }, ['hello hello']]
80
+ end
81
+ }
82
+ end
83
+
84
+ let(:profiler) do
85
+ Rack::Profiler.new(app)
86
+ end
87
+
88
+ let(:env) do
89
+ {
90
+ "PATH_INFO" => "/",
91
+ "QUERY_STRING" => "",
92
+ "REMOTE_HOST" => "localhost",
93
+ "REQUEST_METHOD" => "GET",
94
+ "REQUEST_URI" => "http://localhost:3000/",
95
+ "SCRIPT_NAME" => "",
96
+ "SERVER_NAME" => "localhost",
97
+ "SERVER_PORT" => "3000",
98
+ "SERVER_PROTOCOL" => "HTTP/1.1",
99
+ "HTTP_HOST" => "localhost:3000",
100
+ "rack.version" => [1, 2],
101
+ "rack.input" => StringIO.new,
102
+ "rack.errors" => StringIO.new,
103
+ "rack.multithread" => true,
104
+ "rack.multiprocess" => false,
105
+ "rack.run_once" => false,
106
+ "rack.url_scheme" => "http",
107
+ "HTTP_VERSION" => "HTTP/1.1",
108
+ "REQUEST_PATH" => "/"
109
+ }
110
+ end
111
+
112
+ it "clears events" do
113
+ profiler.events << 'xxx'
114
+ profiler.call(env)
115
+ expect(profiler.events).not_to include('xxx')
116
+ end
117
+
118
+ context "when the path is config.dashboard_path" do
119
+ it "renders dashboard" do
120
+ expect(profiler).to receive(:render_dashboard)
121
+ profiler.call env.merge(
122
+ "PATH_INFO" => profiler.config.dashboard_path,
123
+ "REQUEST_PATH" => profiler.config.dashboard_path
124
+ )
125
+ end
126
+ end
127
+
128
+ context "when the rack-profiler parameter is not present" do
129
+ it "transparently returns the original response" do
130
+ expect(profiler.call(env)).to eq(app.call(env))
131
+ end
132
+ end
133
+
134
+ context "when the rack-profiler parameter is present" do
135
+ let(:env_with_param) {
136
+ env.merge('QUERY_STRING' => 'rack-profiler')
137
+ }
138
+
139
+ it "returns a JSON response" do
140
+ status, headers, body = profiler.call(env_with_param)
141
+ expect(headers).to match('Content-Type' => 'application/json')
142
+ expect { JSON.parse(body.join) }.not_to raise_error
143
+ end
144
+
145
+ it "puts the original response in the JSON payload" do
146
+ status, headers, body = profiler.call(env_with_param)
147
+ parsed_body = JSON.parse(body.join)
148
+ expect(parsed_body['response']).to eq(
149
+ 'status' => 200,
150
+ 'headers' => { 'X-My-Header' => 'foo' },
151
+ 'body' => 'hello hello'
152
+ )
153
+ end
154
+
155
+ it "puts the received events in the JSON payload" do
156
+ status, headers, body = profiler.call(env_with_param)
157
+ parsed_body = JSON.parse(body.join)
158
+ expect(
159
+ parsed_body['events'].map { |e| e['name'] }
160
+ ).to include('rack-profiler.total_time', 'rack-profiler.step')
161
+ end
87
162
  end
88
163
  end
89
164
 
90
165
  describe ".step" do
91
- it "calls ActiveSupport::Notifications.instrument with the right arguments" do
166
+ it "calls ActiveSupport::Notifications.instrument with the right args" do
92
167
  expect(ActiveSupport::Notifications).to receive(:instrument).with(
93
- 'rack-profiler.step', { step_name: 'xxx' })
94
- Rack::Profiler.step('xxx') do
168
+ "rack-profiler.step", { step_name: "xxx" })
169
+ Rack::Profiler.step("xxx") do
95
170
  "do stuff"
96
171
  end
97
172
  end
98
173
 
99
174
  it "mixes data in the payload if provided" do
100
175
  expect(ActiveSupport::Notifications).to receive(:instrument).with(
101
- 'rack-profiler.step', { step_name: 'xxx', foo: 'bar' })
102
- Rack::Profiler.step('xxx', foo: 'bar') do
176
+ "rack-profiler.step", { step_name: "xxx", foo: "bar" })
177
+ Rack::Profiler.step("xxx", foo: "bar") do
103
178
  "do stuff"
104
179
  end
105
180
  end
106
181
  end
182
+
183
+ describe ".configure" do
184
+ it "executes the given block passing the configuration object" do
185
+ config_inside_block = nil
186
+ Rack::Profiler.configure do |c|
187
+ config_inside_block = c
188
+ end
189
+ expect(config_inside_block).to be(Rack::Profiler.config)
190
+ end
191
+ end
192
+
193
+ describe ".config" do
194
+ it "instantiates a Configuration object if there is none" do
195
+ Rack::Profiler.send(:instance_variable_set, :@config, nil)
196
+ expect(Rack::Profiler.config).to be_a(Rack::Profiler::Configuration)
197
+ end
198
+ end
199
+ end
200
+
201
+ describe Rack::Profiler::Configuration do
202
+ let(:config) { Rack::Profiler::Configuration.new }
203
+
204
+ it "has the correct defaults" do
205
+ expect(config.dashboard_path).to eq('/rack-profiler')
206
+ expect(config.backtrace_filter).to be_nil
207
+ expect(config.subscriptions).to include(
208
+ *Rack::Profiler::Configuration::DEFAULT_SUBSCRIPTIONS
209
+ )
210
+ end
211
+
212
+ describe :subscribe do
213
+ it "adds entries to subscriptions" do
214
+ config.subscribe('bar')
215
+ expect(config.subscriptions).to include('bar')
216
+ end
217
+
218
+ it "accepts more than one subscription" do
219
+ config.subscribe('bar', 'baz')
220
+ expect(config.subscriptions).to include('bar', 'baz')
221
+ end
222
+
223
+ it "does not add duplicates" do
224
+ config.subscribe('bar', 'bar')
225
+ expect(
226
+ config.subscriptions.count { |s| s == 'bar' }
227
+ ).to eq(1)
228
+ end
229
+ end
230
+
231
+ describe :filter_backtrace do
232
+ it "sets the backtrace_filter" do
233
+ config.filter_backtrace do |line|
234
+ line.include? 'foo'
235
+ end
236
+ filtered = ['foo', 'foobar', 'baz'].select(&config.backtrace_filter)
237
+ expect(filtered).to eq(['foo', 'foobar'])
238
+ end
239
+ end
107
240
  end
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.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Ongaro
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-26 00:00:00.000000000 Z
12
+ date: 2015-01-27 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: activesupport
16
30
  requirement: !ruby/object:Gem::Requirement