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
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
|