speed_gun 0.0.4 → 1.0.0.rc1
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 +4 -4
- data/.coveralls.yml +1 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Rakefile +6 -1
- data/lib/speed_gun/app/views/meter.html.slim +4 -9
- data/lib/speed_gun/config.rb +33 -42
- data/lib/speed_gun/event.rb +72 -0
- data/lib/speed_gun/middleware.rb +43 -43
- data/lib/speed_gun/profile.rb +102 -0
- data/lib/speed_gun/profiler/action_controller_profiler.rb +14 -0
- data/lib/speed_gun/profiler/action_view_profiler.rb +11 -0
- data/lib/speed_gun/profiler/active_record_profiler.rb +11 -0
- data/lib/speed_gun/profiler/active_support_notifications_profiler.rb +29 -0
- data/lib/speed_gun/profiler/rack_profiler.rb +7 -0
- data/lib/speed_gun/profiler.rb +11 -118
- data/lib/speed_gun/railtie.rb +7 -16
- data/lib/speed_gun/store/elastic_search_store.rb +64 -0
- data/lib/speed_gun/store/fluent_logger_store.rb +29 -0
- data/lib/speed_gun/store/memcache_store.rb +40 -0
- data/lib/speed_gun/store/memory_store.rb +23 -0
- data/lib/speed_gun/store/multiple_store.rb +23 -0
- data/lib/speed_gun/store/redis_store.rb +41 -0
- data/lib/speed_gun/store.rb +7 -3
- data/lib/speed_gun/template.rb +1 -1
- data/lib/speed_gun/version.rb +1 -1
- data/lib/speed_gun.rb +30 -39
- data/spec/lib/speed_gun/config_spec.rb +37 -0
- data/spec/lib/speed_gun/event_spec.rb +70 -0
- data/spec/lib/speed_gun/middleware_spec.rb +65 -0
- data/spec/lib/speed_gun/profile_spec.rb +41 -0
- data/spec/lib/speed_gun_spec.rb +52 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/simplecov.rb +12 -0
- data/speed_gun.gemspec +10 -7
- metadata +102 -56
- data/app/assets/javascripts/browser.js +0 -83
- data/app/assets/javascripts/profiler.js +0 -45
- data/app/views/speed_gun/_meter.html.slim +0 -9
- data/lib/speed_gun/app/public/browser.js +0 -83
- data/lib/speed_gun/app/public/jquery-1.10.2.min.js +0 -6
- data/lib/speed_gun/app/public/profile.js +0 -5
- data/lib/speed_gun/app/public/profiler.js +0 -45
- data/lib/speed_gun/app/public/style.css +0 -170
- data/lib/speed_gun/app/views/profile.slim +0 -97
- data/lib/speed_gun/app.rb +0 -58
- data/lib/speed_gun/browser/navigation.rb +0 -23
- data/lib/speed_gun/browser/timing.rb +0 -92
- data/lib/speed_gun/browser.rb +0 -22
- data/lib/speed_gun/hook.rb +0 -25
- data/lib/speed_gun/profiler/action_controller.rb +0 -12
- data/lib/speed_gun/profiler/action_view.rb +0 -12
- data/lib/speed_gun/profiler/active_record.rb +0 -16
- data/lib/speed_gun/profiler/base.rb +0 -139
- data/lib/speed_gun/profiler/js.rb +0 -17
- data/lib/speed_gun/profiler/manual.rb +0 -14
- data/lib/speed_gun/profiler/rack.rb +0 -7
- data/lib/speed_gun/store/base.rb +0 -9
- data/lib/speed_gun/store/file.rb +0 -62
- data/lib/speed_gun/store/memcache.rb +0 -27
- data/lib/speed_gun/store/memory.rb +0 -22
- data/lib/speed_gun/store/redis.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a38f7425f4a2a540896f5b7a966cc5585c28de8c
|
4
|
+
data.tar.gz: 5475d18a057f641dd22f573bded80f1f5ffde58d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 520937f45fcee60a4f24d187d85ccfc204b0c059dd3604ac0196db7880e5b46cf8fc011da5e26b513560ac62a252543af734e27862c8c64871253e805db72382
|
7
|
+
data.tar.gz: 24f430cd3d83e1eb25d31db0de0004ae359b1745e8f548cd46ac9d724af9d571ccf26e007dfef870007520c71a173dd0458a499fcba07d7864a97b01f2285a83
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Rakefile
CHANGED
@@ -1,9 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
span#speed_gun_total(style="vertical-align: middle;")
|
6
|
-
- unless SpeedGun.config.no_include_jquery?
|
7
|
-
script(type="text/javascript" src="#{SpeedGun.config.prefix}/jquery-1.10.2.min.js")
|
8
|
-
script(type="text/javascript" src="#{SpeedGun.config.prefix}/browser.js")
|
9
|
-
script(type="text/javascript" src="#{SpeedGun.config.prefix}/profiler.js")
|
1
|
+
div.speed-gun(style="position: fixed; bottom: -1px; right: -1px; border: 1px solid #999; border-radius: 3px 0 0 0; background-color: white; font-size: 9px;")
|
2
|
+
a(href="#" style="display: block; padding: 5px 10px")
|
3
|
+
= "%0.2f" % (duration * 1000)
|
4
|
+
| ms
|
data/lib/speed_gun/config.rb
CHANGED
@@ -1,59 +1,50 @@
|
|
1
|
+
require 'hashie'
|
1
2
|
require 'speed_gun'
|
3
|
+
require 'speed_gun/store/memory_store'
|
2
4
|
|
3
|
-
class SpeedGun::Config <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def enable
|
9
|
-
fetch(:enable, true)
|
10
|
-
end
|
5
|
+
class SpeedGun::Config < Hashie::Dash
|
6
|
+
# @!attribute [rw]
|
7
|
+
# @return [Boolean] true if enabled speed gun
|
8
|
+
property :enable, default: true
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
# @!attribute [rw]
|
11
|
+
# @return [Object, nil] logger of the speed gun
|
12
|
+
property :logger, default: nil
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
# @!attribute [rw]
|
15
|
+
# @return [Array<Regexp>] paths of skip the speed gun
|
16
|
+
property :skip_paths, default: []
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
# @!attribute [rw]
|
19
|
+
# @return [SpeedGun::Store] store of events and profiles
|
20
|
+
property :store, default: SpeedGun::Store::MemoryStore.new
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
# @!attribute [rw]
|
23
|
+
# @return [Boolean] true if enable auto injection
|
24
|
+
property :auto_inject, default: true
|
27
25
|
|
28
|
-
|
29
|
-
|
26
|
+
# @return [true]
|
27
|
+
def enable!
|
28
|
+
self[:enable] = true
|
30
29
|
end
|
31
30
|
|
32
|
-
|
33
|
-
|
31
|
+
# @return [false]
|
32
|
+
def disable!
|
33
|
+
self[:enable] = false
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
# @return [Boolean] true if enabled speed gun
|
37
|
+
def enabled?
|
38
|
+
!!enable
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
-
|
41
|
+
# @return [Boolean] true if disabled speed gun
|
42
|
+
def disabled?
|
43
|
+
!enabled?
|
42
44
|
end
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
def skip_paths
|
49
|
-
self[:skip_paths] ||= [/favicon/]
|
50
|
-
end
|
51
|
-
|
52
|
-
def force_profile?
|
53
|
-
fetch(:force_profile, true)
|
54
|
-
end
|
55
|
-
|
56
|
-
def authorize_proc
|
57
|
-
self[:authorize_proc] ||= ->(request) { true }
|
46
|
+
# @return [Boolean] true if enable auto injection
|
47
|
+
def auto_inject?
|
48
|
+
auto_inject
|
58
49
|
end
|
59
50
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'speed_gun'
|
2
|
+
|
3
|
+
class SpeedGun::Event
|
4
|
+
def self.from_hash(id, hash)
|
5
|
+
event = new(
|
6
|
+
hash['name'],
|
7
|
+
hash['payload'],
|
8
|
+
Time.at(hash['started_at']),
|
9
|
+
hash['finished_at'] ? Time.at(hash['finished_at']) : nil
|
10
|
+
)
|
11
|
+
event.instance_variable_set(:@id, id)
|
12
|
+
|
13
|
+
event
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [String] event ID
|
17
|
+
attr_reader :id
|
18
|
+
|
19
|
+
# @return [String] event name
|
20
|
+
attr_reader :name
|
21
|
+
|
22
|
+
# @return [Hashie::Mash] payload
|
23
|
+
attr_reader :payload
|
24
|
+
|
25
|
+
# @return [Time] start time
|
26
|
+
attr_reader :started_at
|
27
|
+
|
28
|
+
# @return [Time, nil] finish time
|
29
|
+
attr_reader :finished_at
|
30
|
+
|
31
|
+
# @param name [String] event name
|
32
|
+
# @param payload [Hash] payload
|
33
|
+
# @param started_at [Time] start time
|
34
|
+
# @param finished_at [Time, nil] finish time
|
35
|
+
# @return [SpeedGun::Event] instance of SpeedGun::Event
|
36
|
+
def initialize(name, payload = {}, started_at = Time.now, finished_at = nil)
|
37
|
+
@id = SecureRandom.uuid
|
38
|
+
@name = name
|
39
|
+
@payload = Hashie::Mash.new(payload)
|
40
|
+
@started_at = started_at
|
41
|
+
@finished_at = finished_at
|
42
|
+
end
|
43
|
+
|
44
|
+
# Finish event
|
45
|
+
#
|
46
|
+
# @return [Time] finish time
|
47
|
+
def finish!
|
48
|
+
@finished_at = Time.now
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [true, false] true if the event is finished
|
52
|
+
def finished?
|
53
|
+
!@finished_at.nil?
|
54
|
+
end
|
55
|
+
|
56
|
+
# Time duration of the event
|
57
|
+
#
|
58
|
+
# @return [Float] a duration of the event
|
59
|
+
def duration
|
60
|
+
finished? ? finished_at.to_f - started_at.to_f : -1
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_hash
|
64
|
+
{
|
65
|
+
'name' => name,
|
66
|
+
'payload' => payload,
|
67
|
+
'started_at' => started_at.to_f,
|
68
|
+
'finished_at' => finished? ? finished_at.to_f : nil,
|
69
|
+
'duration' => duration
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
data/lib/speed_gun/middleware.rb
CHANGED
@@ -1,60 +1,70 @@
|
|
1
1
|
require 'speed_gun'
|
2
|
-
require 'speed_gun/app'
|
3
|
-
require 'speed_gun/profiler'
|
4
|
-
require 'speed_gun/profiler/rack'
|
5
2
|
require 'speed_gun/template'
|
3
|
+
require 'speed_gun/profiler/rack_profiler'
|
6
4
|
|
7
5
|
class SpeedGun::Middleware
|
8
|
-
BODY_END_REGEXP = /<\/(?:body|html)>/
|
6
|
+
BODY_END_REGEXP = /<\/(?:body|html)>/i
|
9
7
|
|
8
|
+
# @param app [#call] Rack application
|
9
|
+
# @return [SpeedGun::Middleware] a instance of SpeedGun::Middleware
|
10
10
|
def initialize(app)
|
11
11
|
@app = app
|
12
12
|
end
|
13
13
|
|
14
|
+
# Handle rack request
|
15
|
+
#
|
16
|
+
# @return [Rack::Response]
|
14
17
|
def call(env)
|
15
|
-
|
18
|
+
if with_speed_gun?(env)
|
19
|
+
call_with_speed_gun(env)
|
20
|
+
else
|
21
|
+
call_without_speed_gun(env)
|
22
|
+
end
|
23
|
+
end
|
16
24
|
|
17
|
-
|
25
|
+
private
|
18
26
|
|
19
|
-
|
20
|
-
|
21
|
-
SpeedGun.current = nil
|
27
|
+
def with_speed_gun?(env)
|
28
|
+
SpeedGun.enabled? && !skip?(env['PATH_INFO'])
|
22
29
|
end
|
23
30
|
|
24
|
-
|
31
|
+
def skip?(path)
|
32
|
+
SpeedGun.config.skip_paths.any? { |regexp| regexp.match(path) }
|
33
|
+
end
|
25
34
|
|
26
|
-
def
|
27
|
-
|
35
|
+
def call_without_speed_gun(env)
|
36
|
+
@app.call(env)
|
37
|
+
end
|
28
38
|
|
29
|
-
|
39
|
+
def call_with_speed_gun(env)
|
40
|
+
SpeedGun.current_profile = SpeedGun::Profile.new
|
41
|
+
SpeedGun.current_profile.request_method = env['REQUEST_METHOD'].to_s.upcase
|
42
|
+
SpeedGun.current_profile.path = env['PATH_INFO'].to_s
|
43
|
+
SpeedGun.current_profile.query = env['QUERY_STRING'].to_s
|
30
44
|
|
31
|
-
|
32
|
-
|
33
|
-
SpeedGun.current.dump
|
45
|
+
response = SpeedGun::Profiler::RackProfier.profile do
|
46
|
+
call_without_speed_gun(env)
|
34
47
|
end
|
35
48
|
|
36
|
-
|
37
|
-
inject_body(status, headers, body)
|
38
|
-
else
|
39
|
-
return [status, headers, body]
|
40
|
-
end
|
41
|
-
end
|
49
|
+
SpeedGun.current_profile.status = response[0]
|
42
50
|
|
43
|
-
|
44
|
-
|
51
|
+
if SpeedGun.current_profile.active?
|
52
|
+
inject_header(response[1])
|
53
|
+
if SpeedGun.current_profile.config.auto_inject?
|
54
|
+
response = inject_body(*response)
|
55
|
+
end
|
56
|
+
end
|
45
57
|
|
46
|
-
|
47
|
-
|
58
|
+
response
|
59
|
+
ensure
|
60
|
+
if SpeedGun.current_profile.active?
|
61
|
+
SpeedGun.config.store.save(SpeedGun.current_profile)
|
62
|
+
end
|
63
|
+
SpeedGun.discard_profile!
|
48
64
|
end
|
49
65
|
|
50
66
|
def inject_header(headers)
|
51
|
-
|
52
|
-
headers.delete('ETag')
|
53
|
-
headers.delete('Date')
|
54
|
-
headers['Cache-Control'] = 'must-revalidate, private, max-age=0'
|
55
|
-
end
|
56
|
-
|
57
|
-
headers['X-SPEEDGUN-ID'] = SpeedGun.current.id
|
67
|
+
headers['X-SpeedGun-Profile-Id'] = SpeedGun.current_profile.id
|
58
68
|
end
|
59
69
|
|
60
70
|
def inject_body(status, headers, body)
|
@@ -78,14 +88,4 @@ class SpeedGun::Middleware
|
|
78
88
|
SpeedGun::Template.render + matched
|
79
89
|
end
|
80
90
|
end
|
81
|
-
|
82
|
-
def under_speed_gun?(env)
|
83
|
-
if SpeedGun.config.prefix_regexp.match(env['PATH_INFO'])
|
84
|
-
env['PATH_INFO'] =
|
85
|
-
env['PATH_INFO'].sub(SpeedGun.config.prefix_regexp, '')
|
86
|
-
true
|
87
|
-
else
|
88
|
-
false
|
89
|
-
end
|
90
|
-
end
|
91
91
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'speed_gun'
|
3
|
+
require 'speed_gun/event'
|
4
|
+
|
5
|
+
class SpeedGun::Profile
|
6
|
+
def self.from_hash(id, hash)
|
7
|
+
profile = new
|
8
|
+
|
9
|
+
hash['events'].map! do |event_id|
|
10
|
+
SpeedGun.config.store.load(SpeedGun::Event, event_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
hash['id'] = id
|
14
|
+
hash.delete('duration')
|
15
|
+
hash.each_pair do |key, val|
|
16
|
+
profile.instance_variable_set(:"@#{key}", val)
|
17
|
+
end
|
18
|
+
|
19
|
+
profile
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [String] profile ID
|
23
|
+
attr_reader :id
|
24
|
+
|
25
|
+
# @return [Array<SpeedGun::Event>] recorded events
|
26
|
+
attr_reader :events
|
27
|
+
|
28
|
+
# @return [SpeedGun::Config] the config of the profile
|
29
|
+
attr_reader :config
|
30
|
+
|
31
|
+
# @return [Integer] status code of the response
|
32
|
+
attr_accessor :status
|
33
|
+
|
34
|
+
# @return [String] method of the request
|
35
|
+
attr_accessor :request_method
|
36
|
+
|
37
|
+
# @return [String] path of the request
|
38
|
+
attr_accessor :path
|
39
|
+
|
40
|
+
# @return [String] query of the request
|
41
|
+
attr_accessor :query
|
42
|
+
|
43
|
+
# @return [SpeedGun::Profile] instance of SpeedGun::Profile
|
44
|
+
def initialize(config = SpeedGun.config.dup)
|
45
|
+
@id = SecureRandom.uuid
|
46
|
+
@events = []
|
47
|
+
@config = config
|
48
|
+
@active = true
|
49
|
+
end
|
50
|
+
|
51
|
+
# Record an event
|
52
|
+
#
|
53
|
+
# @param event [SpeedGun::Event] record event
|
54
|
+
# @return [Array<SpeedGun::Event>] recorded events
|
55
|
+
def record!(event)
|
56
|
+
config.logger.debug(
|
57
|
+
"[SpeedGun] Record Event: #{event.name}: #{'%0.2f' % (event.duration * 1000)}ms"
|
58
|
+
) if config.logger
|
59
|
+
config.store.save(event) if active?
|
60
|
+
@events.push(event)
|
61
|
+
end
|
62
|
+
|
63
|
+
def active?
|
64
|
+
@active
|
65
|
+
end
|
66
|
+
|
67
|
+
def deactive?
|
68
|
+
!active?
|
69
|
+
end
|
70
|
+
|
71
|
+
def activate!
|
72
|
+
@active = true
|
73
|
+
end
|
74
|
+
|
75
|
+
def deactivate!
|
76
|
+
@active = false
|
77
|
+
end
|
78
|
+
|
79
|
+
def earliest_started_at
|
80
|
+
@events.sort_by(&:started_at).first.started_at
|
81
|
+
end
|
82
|
+
|
83
|
+
def latest_finished_at
|
84
|
+
@events.sort_by { |event| event.finished_at || 0 }.last.finished_at
|
85
|
+
end
|
86
|
+
|
87
|
+
def duration
|
88
|
+
finished_at = latest_finished_at
|
89
|
+
finished_at ? finished_at - earliest_started_at : 0
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_hash
|
93
|
+
{
|
94
|
+
'events' => events.map(&:id),
|
95
|
+
'status' => status,
|
96
|
+
'request_method' => request_method,
|
97
|
+
'path' => path,
|
98
|
+
'query' => query,
|
99
|
+
'duration' => duration
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'speed_gun/profiler/active_support_notifications_profiler'
|
2
|
+
|
3
|
+
class SpeedGun::Profiler::ActionControllerProfiler <
|
4
|
+
SpeedGun::Profiler::ActiveSupportNotificatiosProfiler
|
5
|
+
|
6
|
+
subscribe(
|
7
|
+
/^(process_action|send_file|send_data|redirect_to)\.action_controller$/,
|
8
|
+
[:request]
|
9
|
+
)
|
10
|
+
|
11
|
+
def self.name
|
12
|
+
'action_controller'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'speed_gun/profiler/active_support_notifications_profiler'
|
2
|
+
|
3
|
+
class SpeedGun::Profiler::ActionViewProfiler <
|
4
|
+
SpeedGun::Profiler::ActiveSupportNotificatiosProfiler
|
5
|
+
|
6
|
+
subscribe /^!(render_template|render_partial)\.action_view$/
|
7
|
+
|
8
|
+
def self.name
|
9
|
+
'action_view'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'speed_gun/profiler/active_support_notifications_profiler'
|
2
|
+
|
3
|
+
class SpeedGun::Profiler::ActiveRecordProfiler <
|
4
|
+
SpeedGun::Profiler::ActiveSupportNotificatiosProfiler
|
5
|
+
|
6
|
+
subscribe(/\.active_record$/, [:binds])
|
7
|
+
|
8
|
+
def self.name
|
9
|
+
'active_record'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'speed_gun/profiler'
|
2
|
+
|
3
|
+
class SpeedGun::Profiler::ActiveSupportNotificatiosProfiler < SpeedGun::Profiler
|
4
|
+
def self.subscribe(event, ignore_payload = [])
|
5
|
+
klass = self
|
6
|
+
ActiveSupport::Notifications.subscribe(event) do |*args|
|
7
|
+
klass.record(event, *args, ignore_payload)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.record(event, name, started, ended, id, payload, ignore_payload)
|
12
|
+
name = "#{self.name}.#{name.sub(event, '\1')}"
|
13
|
+
|
14
|
+
payload.symbolize_keys!
|
15
|
+
|
16
|
+
ignore_payload.each do |key|
|
17
|
+
payload.delete(key)
|
18
|
+
end
|
19
|
+
|
20
|
+
payload[:backtrace] = backtrace
|
21
|
+
|
22
|
+
event = SpeedGun::Event.new(name, payload, started, ended)
|
23
|
+
SpeedGun.current_profile.record!(event)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.backtrace
|
27
|
+
Rails.backtrace_cleaner.clean(caller[2..-1])
|
28
|
+
end
|
29
|
+
end
|
data/lib/speed_gun/profiler.rb
CHANGED
@@ -1,128 +1,21 @@
|
|
1
1
|
require 'speed_gun'
|
2
|
-
require 'speed_gun/store'
|
3
|
-
require 'speed_gun/browser'
|
4
|
-
require 'speed_gun/hook'
|
5
|
-
require 'securerandom'
|
6
|
-
require 'msgpack'
|
7
|
-
require 'multi_json'
|
8
2
|
|
3
|
+
# @abstract
|
9
4
|
class SpeedGun::Profiler
|
10
|
-
|
11
|
-
|
12
|
-
def self.load(id)
|
13
|
-
src = SpeedGun.store[id]
|
14
|
-
|
15
|
-
return nil unless src
|
16
|
-
|
17
|
-
restore(src)
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.restore(src)
|
21
|
-
data = src.kind_of?(String) ? MessagePack.unpack(src) : src
|
22
|
-
|
23
|
-
profiler = new({})
|
24
|
-
profiler.restore_by_hash(data)
|
25
|
-
|
26
|
-
profiler
|
27
|
-
end
|
28
|
-
|
29
|
-
def initialize(env)
|
30
|
-
@id = SecureRandom.uuid
|
31
|
-
@path = env['PATH_INFO']
|
32
|
-
@query = env['QUERY_STRING']
|
33
|
-
@env = env
|
34
|
-
@requested_at = Time.now
|
35
|
-
@profiles = []
|
36
|
-
@browser = nil
|
37
|
-
@active = true
|
38
|
-
@now_profile = nil
|
39
|
-
end
|
40
|
-
attr_reader :id, :path, :query, :env, :requested_at, :profiles, :browser
|
41
|
-
attr_accessor :now_profile
|
42
|
-
|
43
|
-
def profile(type, *args, &block)
|
44
|
-
profiler = PROFILERS[type]
|
45
|
-
|
46
|
-
if profiler
|
47
|
-
profiler.profile(self, *args, &block)
|
48
|
-
else
|
49
|
-
yield
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def skip?
|
54
|
-
SpeedGun.config.skip_paths.any? { |prefix| prefix.match(@path) }
|
55
|
-
end
|
56
|
-
|
57
|
-
def active?
|
58
|
-
@active && !skip?
|
59
|
-
end
|
60
|
-
|
61
|
-
def activate!
|
62
|
-
@active = true
|
5
|
+
def self.profile(*args, &block)
|
6
|
+
new.profile(*args, &block)
|
63
7
|
end
|
64
8
|
|
65
|
-
def
|
66
|
-
|
67
|
-
end
|
9
|
+
def profile(name = self.class.name, payload = {}, &block)
|
10
|
+
starts_at = Time.now
|
68
11
|
|
69
|
-
|
70
|
-
SpeedGun.store[id] = to_msgpack
|
12
|
+
ret = yield
|
71
13
|
|
72
|
-
SpeedGun::
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
@browser = SpeedGun::Browser.new(hash)
|
77
|
-
end
|
78
|
-
|
79
|
-
def as_msgpack(*args)
|
80
|
-
{
|
81
|
-
id: @id,
|
82
|
-
path: @path,
|
83
|
-
query: @query,
|
84
|
-
env: msgpackable_env,
|
85
|
-
requested_at: @requested_at.to_i,
|
86
|
-
profiles: @profiles.map { |profile| profile.as_msgpack(*args) },
|
87
|
-
browser: @browser ? @browser.as_msgpack(*args) : nil,
|
88
|
-
}
|
89
|
-
end
|
90
|
-
|
91
|
-
def to_msgpack(*args)
|
92
|
-
as_msgpack(*args).to_msgpack(*args)
|
93
|
-
end
|
14
|
+
event = SpeedGun::Event.new(
|
15
|
+
name, payload, starts_at, Time.now
|
16
|
+
)
|
17
|
+
SpeedGun.current_profile.record!(event)
|
94
18
|
|
95
|
-
|
96
|
-
MultiJson.dump(as_msgpack(*args))
|
97
|
-
end
|
98
|
-
|
99
|
-
def restore_by_hash(hash)
|
100
|
-
hash.each_pair do |key, val|
|
101
|
-
instance_variable_set(:"@#{key}", restore_attribute(key, val))
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def restore_attribute(key, val)
|
106
|
-
case key
|
107
|
-
when 'requested_at'
|
108
|
-
Time.at(val)
|
109
|
-
when 'profiles'
|
110
|
-
val.map { |profile| SpeedGun::Profiler::Base.load(profile) }
|
111
|
-
when 'browser'
|
112
|
-
val ? SpeedGun::Browser.new(val) : val
|
113
|
-
else
|
114
|
-
val
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
private
|
119
|
-
|
120
|
-
def msgpackable_env
|
121
|
-
env = {}
|
122
|
-
@env.each_pair { |key, val| env[key] = val if key[0] =~ /[A-Z]/ }
|
123
|
-
env
|
19
|
+
return ret
|
124
20
|
end
|
125
21
|
end
|
126
|
-
|
127
|
-
require 'speed_gun/profiler/manual'
|
128
|
-
require 'speed_gun/profiler/js'
|