speed_gun 0.0.4 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/speed_gun/railtie.rb
CHANGED
@@ -1,33 +1,24 @@
|
|
1
1
|
require 'speed_gun'
|
2
|
-
require 'speed_gun/store/file'
|
3
2
|
|
4
3
|
class SpeedGun::Railtie < ::Rails::Railtie
|
5
4
|
initializer 'speed_gun' do |app|
|
6
5
|
app.middleware.insert(0, SpeedGun::Middleware)
|
7
6
|
|
8
|
-
SpeedGun.config
|
9
|
-
SpeedGun.config
|
10
|
-
|
11
|
-
|
12
|
-
SpeedGun.config.skip_paths << /^#{Regexp.escape(app.config.assets.prefix)}/
|
13
|
-
SpeedGun.config[:store] =
|
14
|
-
SpeedGun::Store::File.new(path: Rails.root.join('tmp/speed_gun'))
|
7
|
+
SpeedGun.config.logger = Rails.logger
|
8
|
+
SpeedGun.config.skip_paths.push(
|
9
|
+
/^#{Regexp.escape(app.config.assets.prefix)}/
|
10
|
+
)
|
15
11
|
|
16
12
|
ActiveSupport.on_load(:action_controller) do
|
17
|
-
require 'speed_gun/profiler/
|
13
|
+
require 'speed_gun/profiler/action_controller_profiler'
|
18
14
|
end
|
19
15
|
|
20
16
|
ActiveSupport.on_load(:action_view) do
|
21
|
-
require 'speed_gun/profiler/
|
17
|
+
require 'speed_gun/profiler/action_view_profiler'
|
22
18
|
end
|
23
19
|
|
24
20
|
ActiveSupport.on_load(:active_record) do
|
25
|
-
require 'speed_gun/profiler/
|
26
|
-
|
27
|
-
SpeedGun::Profiler::ActiveRecord.hook_method(
|
28
|
-
ActiveRecord::Base.connection.class,
|
29
|
-
:execute
|
30
|
-
)
|
21
|
+
require 'speed_gun/profiler/active_record_profiler'
|
31
22
|
end
|
32
23
|
end
|
33
24
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'speed_gun/store'
|
2
|
+
|
3
|
+
class SpeedGun::Store::ElasticSearchStore < SpeedGun::Store
|
4
|
+
DEFAULT_INDEX = 'speed_gun'
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@index = options[:index] || DEFAULT_INDEX
|
8
|
+
@async = options.fetch(:async, true)
|
9
|
+
@client = options[:client] || default_clinet(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def save(object)
|
13
|
+
@async ? save_with_async(object) : save_without_async(object)
|
14
|
+
end
|
15
|
+
|
16
|
+
def load(klass, id)
|
17
|
+
hit = @client.search(
|
18
|
+
index: @index,
|
19
|
+
body: {
|
20
|
+
query: {
|
21
|
+
match: {
|
22
|
+
"_id" => id,
|
23
|
+
"_type" => underscore(klass.name)
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
)['hits']['hits'].first['_source']
|
28
|
+
|
29
|
+
klass.from_hash(id, hit)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def save_with_async(object)
|
35
|
+
Thread.new(object) { |object| save_without_async(object) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def save_without_async(object)
|
39
|
+
@client.index(
|
40
|
+
index: @index,
|
41
|
+
type: underscore(object.class.name),
|
42
|
+
id: object.id,
|
43
|
+
body: object.to_hash.merge(
|
44
|
+
'@timestamp' => Time.now
|
45
|
+
)
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def index(klass)
|
50
|
+
[@prefix, underscore(klass.name)].join('-')
|
51
|
+
end
|
52
|
+
|
53
|
+
def underscore(name)
|
54
|
+
name = name
|
55
|
+
name.sub!(/^[A-Z]/) { |c| c.downcase }
|
56
|
+
name.gsub!(/[A-Z]/) { |c| "_#{c.downcase}" }
|
57
|
+
name.gsub!('::', '')
|
58
|
+
end
|
59
|
+
|
60
|
+
def default_clinet(options)
|
61
|
+
require 'elasticsearch' unless defined?(Elasticsearch)
|
62
|
+
Elasticsearch::Client.new(options)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'speed_gun/store'
|
2
|
+
|
3
|
+
class SpeedGun::Store::FluentLoggerStore < SpeedGun::Store
|
4
|
+
DEFAULT_PREFIX = 'speed_gun'
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@prefix = options[:prefix] || DEFAULT_PREFIX
|
8
|
+
@logger = options[:logger] || default_logger(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def save(object)
|
12
|
+
@logger.post(tag(object), object.to_hash.merge(id: object.id))
|
13
|
+
end
|
14
|
+
|
15
|
+
def load(klass, id)
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def tag(object)
|
22
|
+
object.class.name.sub(/.*::/, '').downcase
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_logger(options)
|
26
|
+
require 'fluent-logger' unless defined?(Fluent::Logger)
|
27
|
+
Fluent::Logger::FluentLogger.new(@prefix, options)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'speed_gun/store'
|
2
|
+
|
3
|
+
class SpeedGun::Store::MemcacheStroe < SpeedGun::Store
|
4
|
+
DEFAULT_PREFIX = 'speed-gun'
|
5
|
+
DEFAULT_EXPIRES_IN_SECONDS = 60 * 60 * 24
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@prefix = options[:prefix] || DEFAULT_PREFIX
|
9
|
+
@client = options[:client] || default_client(options)
|
10
|
+
@expires = (options[:expires] || DEFAULT_EXPIRES_IN_SECONDS).to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
def save(object)
|
14
|
+
@client.set(
|
15
|
+
key(object.class, object.id),
|
16
|
+
object.to_hash.to_msgpack,
|
17
|
+
@expires
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def load(klass, id)
|
22
|
+
klass.from_hash(id, MessagePack.unpack(@client.get(key(klass, id))))
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def key(klass, id)
|
28
|
+
klass_name = klass.name
|
29
|
+
klass_name.gsub!(/([a-z])([A-Z])/) { |c| "#{$1.to_s}_#{$2.to_s.downcase}" }
|
30
|
+
klass_name.gsub!(/[A-Z]/) { |c| "#{c.downcase}" }
|
31
|
+
klass_name.gsub!('::', '-')
|
32
|
+
|
33
|
+
[@prefix, klass_name, id].join('-')
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_client(options)
|
37
|
+
require 'dalli' unless defined?(Dalli)
|
38
|
+
Dalli.new(options)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'speed_gun/store'
|
2
|
+
|
3
|
+
class SpeedGun::Store::MemoryStore < SpeedGun::Store
|
4
|
+
DEFAULT_MAX_ENTRIES = 1000
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@max_entries = options[:max_entries] || DEFAULT_MAX_ENTRIES
|
8
|
+
@store = {}
|
9
|
+
@stored_list = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def save(object)
|
13
|
+
id = "#{object.class.name}-#{object.id}"
|
14
|
+
@store[id] = object.to_hash
|
15
|
+
@stored_list.push(id)
|
16
|
+
|
17
|
+
@store.delete(@stored_list.shift) while @stored_list.length > @max_entries
|
18
|
+
end
|
19
|
+
|
20
|
+
def load(klass, id)
|
21
|
+
klass.from_hash(id, @store["#{klass.name}-#{id}"])
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'speed_gun/store'
|
2
|
+
|
3
|
+
class SpeedGun::Store::MultipleStore < SpeedGun::Store
|
4
|
+
def initialize(stores = [])
|
5
|
+
@stores = stores
|
6
|
+
end
|
7
|
+
|
8
|
+
def save(object)
|
9
|
+
@stores.each do |store|
|
10
|
+
store.save(object)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def load(klass, id)
|
15
|
+
@stores.each do |store|
|
16
|
+
ret = store.load(klass, id)
|
17
|
+
|
18
|
+
return ret if ret
|
19
|
+
end
|
20
|
+
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'msgpack'
|
2
|
+
require 'speed_gun/store'
|
3
|
+
|
4
|
+
class SpeedGun::Store::RedisStore < SpeedGun::Store
|
5
|
+
DEFAULT_PREFIX = 'speed-gun'
|
6
|
+
DEFAULT_EXPIRES_IN_SECONDS = 60 * 60 * 24
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@prefix = options[:prefix] || DEFAULT_PREFIX
|
10
|
+
@client = options[:client] || default_client(options)
|
11
|
+
@expires = (options[:expires] || DEFAULT_EXPIRES_IN_SECONDS).to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def save(object)
|
15
|
+
@client.setex(
|
16
|
+
key(object.class, object.id),
|
17
|
+
@expires,
|
18
|
+
object.to_hash.to_msgpack
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def load(klass, id)
|
23
|
+
klass.from_hash(id, MessagePack.unpack(@client.get(key(klass, id))))
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def key(klass, id)
|
29
|
+
klass_name = klass.name
|
30
|
+
klass_name.gsub!(/([a-z])([A-Z])/) { |c| "#{$1.to_s}_#{$2.to_s.downcase}" }
|
31
|
+
klass_name.gsub!(/[A-Z]/) { |c| "#{c.downcase}" }
|
32
|
+
klass_name.gsub!('::', '-')
|
33
|
+
|
34
|
+
[@prefix, klass_name, id].join('-')
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_client(options)
|
38
|
+
require 'redis' unless defined? Redis
|
39
|
+
Redis.new(options)
|
40
|
+
end
|
41
|
+
end
|
data/lib/speed_gun/store.rb
CHANGED
data/lib/speed_gun/template.rb
CHANGED
data/lib/speed_gun/version.rb
CHANGED
data/lib/speed_gun.rb
CHANGED
@@ -1,52 +1,43 @@
|
|
1
|
+
require 'forwardable'
|
1
2
|
require 'thread'
|
3
|
+
require 'speed_gun/version'
|
4
|
+
require 'speed_gun/config'
|
5
|
+
require 'speed_gun/profile'
|
6
|
+
require 'speed_gun/middleware'
|
2
7
|
|
3
8
|
module SpeedGun
|
4
9
|
class << self
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
Thread.current[:speed_gun_current]
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.current=(profiler)
|
13
|
-
Thread.current[:speed_gun_current] = profiler
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.config
|
17
|
-
@config ||= SpeedGun::Config.new
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.active?
|
21
|
-
current && current.active?
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.activate!
|
25
|
-
current && current.activate!
|
26
|
-
end
|
10
|
+
# @return [SpeedGun::Config] the config of speed gun
|
11
|
+
def config
|
12
|
+
@config ||= Config.new
|
13
|
+
end
|
27
14
|
|
28
|
-
|
29
|
-
|
30
|
-
|
15
|
+
# @return [SpeedGun::Profile, nil] the profile of a current thread
|
16
|
+
def current_profile
|
17
|
+
Thread.current[:speed_gun_current_profile]
|
18
|
+
end
|
31
19
|
|
32
|
-
|
33
|
-
|
34
|
-
|
20
|
+
# Set the profile of a current thread
|
21
|
+
#
|
22
|
+
# @param profile [SpeedGun::Profile] the profile
|
23
|
+
# @return [SpeedGun::Profile] the profile of a current thread
|
24
|
+
def current_profile=(profile)
|
25
|
+
Thread.current[:speed_gun_current_profile] = profile
|
26
|
+
end
|
35
27
|
|
36
|
-
|
37
|
-
|
38
|
-
|
28
|
+
# Discard the profile of a current thread
|
29
|
+
#
|
30
|
+
# @return [nil]
|
31
|
+
def discard_profile!
|
32
|
+
self.current_profile = nil
|
33
|
+
end
|
39
34
|
|
40
|
-
|
41
|
-
if
|
42
|
-
|
43
|
-
|
44
|
-
current && current.profile(title, *args, &block)
|
35
|
+
# @see SpeedGun::Config#enabled?
|
36
|
+
# @return [Boolean] true if enabled speed gun
|
37
|
+
def enabled?
|
38
|
+
config.enabled?
|
45
39
|
end
|
46
40
|
end
|
47
41
|
end
|
48
42
|
|
49
|
-
require 'speed_gun/version'
|
50
|
-
require 'speed_gun/config'
|
51
|
-
require 'speed_gun/middleware'
|
52
43
|
require 'speed_gun/railtie' if defined?(Rails)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SpeedGun::Config do
|
4
|
+
subject(:config) { described_class.new }
|
5
|
+
|
6
|
+
describe '#enable!' do
|
7
|
+
before do
|
8
|
+
config.disable!
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'enables the config' do
|
12
|
+
expect(config).to_not be_enabled
|
13
|
+
config.enable!
|
14
|
+
expect(config).to be_enabled
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#disable!' do
|
19
|
+
it 'disables the config' do
|
20
|
+
expect(config).to_not be_disabled
|
21
|
+
config.disable!
|
22
|
+
expect(config).to be_disabled
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#enabled?' do
|
27
|
+
it 'defaults to true' do
|
28
|
+
expect(config.enabled?).to be_true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#disabled?' do
|
33
|
+
it 'defaults to false' do
|
34
|
+
expect(config.disabled?).to be_false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SpeedGun::Event do
|
4
|
+
let(:event_name) { 'spec.test' }
|
5
|
+
|
6
|
+
subject(:event) { described_class.new(event_name) }
|
7
|
+
|
8
|
+
describe '#id' do
|
9
|
+
subject { event.id }
|
10
|
+
|
11
|
+
it { should be_kind_of(String) }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#name' do
|
15
|
+
subject { event.name }
|
16
|
+
|
17
|
+
it { should be_kind_of(String) }
|
18
|
+
it { should eq(event_name) }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#started_at' do
|
22
|
+
subject { event.started_at }
|
23
|
+
|
24
|
+
it { should be_kind_of(Time) }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#finished_at' do
|
28
|
+
subject { event.finished_at }
|
29
|
+
|
30
|
+
context 'when finished event' do
|
31
|
+
before { event.finish! }
|
32
|
+
|
33
|
+
it { should be_kind_of(Time) }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when continues event' do
|
37
|
+
it { should be_nil }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#finish!' do
|
42
|
+
it 'finishes the event' do
|
43
|
+
expect(event).to_not be_finished
|
44
|
+
event.finish!
|
45
|
+
expect(event).to be_finished
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#duration' do
|
50
|
+
subject(:duration) { event.duration }
|
51
|
+
|
52
|
+
context 'when continues event' do
|
53
|
+
it { should eq(-1) }
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when finished event' do
|
57
|
+
before { event.finish! }
|
58
|
+
|
59
|
+
it { should be_kind_of(Float) }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#to_hash' do
|
64
|
+
it 'valid serialize' do
|
65
|
+
expect(
|
66
|
+
SpeedGun::Event.from_hash(event.id, event.to_hash).to_hash
|
67
|
+
).to eq(event.to_hash)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
|
4
|
+
describe SpeedGun::Middleware do
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
SpeedGun.config.skip_paths << '/skip'
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:app) do
|
12
|
+
builder = Rack::Builder.new do
|
13
|
+
use SpeedGun::Middleware
|
14
|
+
|
15
|
+
map '/skip' do
|
16
|
+
process = lambda do |env|
|
17
|
+
[
|
18
|
+
200,
|
19
|
+
{ 'Content-Type' => 'text/html' },
|
20
|
+
"<html><BODY><h1>Skip</h1></BODY>\n \t</html>"
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
run process
|
25
|
+
end
|
26
|
+
|
27
|
+
map '/html' do
|
28
|
+
process = lambda do |env|
|
29
|
+
[
|
30
|
+
200,
|
31
|
+
{ 'Content-Type' => 'text/html' },
|
32
|
+
"<html><BODY><h1>Hi</h1></BODY>\n \t</html>"
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
run process
|
37
|
+
end
|
38
|
+
end
|
39
|
+
builder.to_app
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'GET /skip' do
|
43
|
+
subject(:response) { get '/skip' }
|
44
|
+
|
45
|
+
it { should be_ok }
|
46
|
+
|
47
|
+
describe '#headers' do
|
48
|
+
subject { response.headers }
|
49
|
+
|
50
|
+
it { should_not be_has_key('X-SpeedGun-Profile-Id') }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'GET /html' do
|
55
|
+
subject(:response) { get '/html' }
|
56
|
+
|
57
|
+
it { should be_ok }
|
58
|
+
|
59
|
+
describe '#headers' do
|
60
|
+
subject { response.headers }
|
61
|
+
|
62
|
+
it { should be_has_key('X-SpeedGun-Profile-Id') }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SpeedGun::Profile do
|
4
|
+
subject(:profile) { described_class.new }
|
5
|
+
|
6
|
+
describe '#id' do
|
7
|
+
subject { profile.id }
|
8
|
+
|
9
|
+
it { should be_kind_of(String) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#events' do
|
13
|
+
subject { profile.events }
|
14
|
+
|
15
|
+
it { should be_kind_of(Array) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#record!' do
|
19
|
+
let(:logger) { double(debug: nil) }
|
20
|
+
let(:event) { SpeedGun::Event.new('spec.test') }
|
21
|
+
|
22
|
+
before { profile.config.logger = logger }
|
23
|
+
|
24
|
+
it 'records event' do
|
25
|
+
expect(profile.record!(event)).to eq(profile.events)
|
26
|
+
expect(profile.events).to include(event)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#to_hash' do
|
31
|
+
let(:event) { SpeedGun::Event.new('spec.test') }
|
32
|
+
|
33
|
+
before { profile.record!(event) }
|
34
|
+
|
35
|
+
it 'valid serialize' do
|
36
|
+
expect(
|
37
|
+
SpeedGun::Profile.from_hash(profile.id, profile.to_hash).to_hash
|
38
|
+
).to eq(profile.to_hash)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SpeedGun do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
describe '#config' do
|
7
|
+
subject { described_class.config }
|
8
|
+
|
9
|
+
it { should be_kind_of(SpeedGun::Config) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#current_profile' do
|
13
|
+
let(:profile) { double }
|
14
|
+
subject(:current_profile) { described_class.current_profile }
|
15
|
+
|
16
|
+
it 'defaults to be nil' do
|
17
|
+
expect(current_profile).to be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'thread localy' do
|
21
|
+
described_class.current_profile = profile
|
22
|
+
expect(current_profile).to eq(profile)
|
23
|
+
|
24
|
+
thread = Thread.new { expect(described_class.current_profile).to be_nil }
|
25
|
+
thread.join
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#discard_profile!' do
|
30
|
+
let(:profile) { double }
|
31
|
+
|
32
|
+
it 'discards current profile' do
|
33
|
+
described_class.current_profile = profile
|
34
|
+
described_class.discard_profile!
|
35
|
+
expect(described_class.current_profile).to be_nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#enabled?' do
|
40
|
+
context 'when enabled' do
|
41
|
+
before { described_class.config.stub(enabled?: true) }
|
42
|
+
|
43
|
+
it { should be_enabled }
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when disabled' do
|
47
|
+
before { described_class.config.stub(enabled?: false) }
|
48
|
+
|
49
|
+
it { should_not be_enabled }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'simplecov-console'
|
3
|
+
require 'coveralls'
|
4
|
+
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
6
|
+
SimpleCov::Formatter::HTMLFormatter,
|
7
|
+
SimpleCov::Formatter::Console,
|
8
|
+
Coveralls::SimpleCov::Formatter
|
9
|
+
]
|
10
|
+
SimpleCov.start do
|
11
|
+
add_filter('spec')
|
12
|
+
end
|