speed_gun 0.0.1

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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rubocop.yml +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +161 -0
  7. data/Rakefile +1 -0
  8. data/app/assets/javascripts/browser.js +65 -0
  9. data/app/assets/javascripts/profiler.js +45 -0
  10. data/app/views/speed_gun/_meter.html.slim +9 -0
  11. data/lib/speed_gun/app/public/browser.js +65 -0
  12. data/lib/speed_gun/app/public/jquery-1.10.2.min.js +6 -0
  13. data/lib/speed_gun/app/public/profile.js +5 -0
  14. data/lib/speed_gun/app/public/profiler.js +45 -0
  15. data/lib/speed_gun/app/public/style.css +170 -0
  16. data/lib/speed_gun/app/views/meter.html.slim +9 -0
  17. data/lib/speed_gun/app/views/profile.slim +97 -0
  18. data/lib/speed_gun/app.rb +58 -0
  19. data/lib/speed_gun/browser/navigation.rb +23 -0
  20. data/lib/speed_gun/browser/timing.rb +92 -0
  21. data/lib/speed_gun/browser.rb +22 -0
  22. data/lib/speed_gun/config.rb +59 -0
  23. data/lib/speed_gun/hook.rb +25 -0
  24. data/lib/speed_gun/middleware.rb +91 -0
  25. data/lib/speed_gun/profiler/action_controller.rb +12 -0
  26. data/lib/speed_gun/profiler/action_view.rb +12 -0
  27. data/lib/speed_gun/profiler/active_record.rb +16 -0
  28. data/lib/speed_gun/profiler/base.rb +139 -0
  29. data/lib/speed_gun/profiler/js.rb +17 -0
  30. data/lib/speed_gun/profiler/manual.rb +14 -0
  31. data/lib/speed_gun/profiler/rack.rb +7 -0
  32. data/lib/speed_gun/profiler.rb +124 -0
  33. data/lib/speed_gun/railtie.rb +33 -0
  34. data/lib/speed_gun/store/base.rb +9 -0
  35. data/lib/speed_gun/store/file.rb +62 -0
  36. data/lib/speed_gun/store/memcache.rb +27 -0
  37. data/lib/speed_gun/store/memory.rb +22 -0
  38. data/lib/speed_gun/store/redis.rb +28 -0
  39. data/lib/speed_gun/store.rb +6 -0
  40. data/lib/speed_gun/template.rb +15 -0
  41. data/lib/speed_gun/version.rb +3 -0
  42. data/lib/speed_gun.rb +52 -0
  43. data/speed_gun.gemspec +29 -0
  44. metadata +184 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b40c0f702aa3870e1ebe8d74a1f3a9eb2a1ca466
4
+ data.tar.gz: 738743cbdf2c13d04392d9e994327e7d5ec8adb6
5
+ SHA512:
6
+ metadata.gz: edf1b6096de4f1af119d765f674d4776b79c5646f0039dc17dc0e01cf486797a75eb7b08a6549246e897a0476aec656933f44395bda159069366ffe97a8b41b2
7
+ data.tar.gz: 1b6f3b24ea288632ab2d89101f1d9ee3e69b002051c8bff29a96cef42e90a4b64624643a018a4db8ae158f10986a39d0e6729a1d5b47b8473e83c668926f486a
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ Documentation:
2
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in speed_gun.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Sho Kusano
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # SpeedGun
2
+
3
+ First, profile. Second, profile.
4
+
5
+ SpeedGun is a better web app profiler on Rails and Rack apps.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'speed_gun'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install speed_gun
20
+
21
+ ## Usage
22
+
23
+ ### Rails
24
+
25
+ You don't require settings in development.
26
+
27
+ In production. You should set `enable_if` and `authorize_proc` configs.
28
+
29
+ ### Sinatra
30
+
31
+ ```ruby
32
+ require 'speed_gun'
33
+
34
+ class MyApplication < Sinatra::Base
35
+ use SpeedGun::Middleware
36
+ end
37
+ ```
38
+
39
+ ## Profiling
40
+
41
+ ### Built-in Profilers
42
+
43
+ SpeedGun has built-in profilers.
44
+
45
+ - `SpeedGun::Profiler::ActionController`
46
+ - `SpeedGun::Profiler::ActionView`
47
+ - `SpeedGun::Profiler::ActiveRecord`
48
+ - `SpeedGun::Profiler::Rack`
49
+
50
+ these profilers don't need configuration.
51
+
52
+ ### Manual Profiling
53
+
54
+ If you want take profile manually. You can use `SpeedGun.profile` method.
55
+
56
+ ```ruby
57
+ SpeedGun.profile("MyProfile#method") do
58
+ my_profile.method()
59
+ end
60
+ ```
61
+
62
+ ### Javascript Profiling
63
+
64
+ SpeedGun is supporting profiling on javascript. You can use `speedGun.profile` or `speedGun.profileMethod`.
65
+
66
+ ```javascript
67
+ speedGun.profile("any title", function() { ... codes ...});
68
+
69
+ var object = { func: function() { ... codes ... } };
70
+ speedGun.profileMethod(object, "func", "any title");
71
+ ```
72
+
73
+ And SpeedGun collect browser informations.
74
+
75
+ - User Agent
76
+ - Perfomance API(if implemented)
77
+
78
+ ### Custom Profiler
79
+
80
+ You can create your custom profilers. a custom profiler require `title` method.
81
+
82
+ Some examples:
83
+
84
+ #### SimpleCustomProfiler
85
+
86
+ ```ruby
87
+ class SimpleCustomProfiler < SpeedGun::Profiler::Base
88
+ def title
89
+ 'simple'
90
+ end
91
+ end
92
+
93
+ SpeedGun.profile(:simple_custom_profiler) { ... }
94
+ ```
95
+
96
+ #### BeforeFilterProfiler
97
+
98
+ ```ruby
99
+ class BeforeFilerProfiler < SpeedGun::Profiler::Base
100
+ # `hook_method` is a helper of method profiling.
101
+ hook_method ApplicationControler, :some_filter
102
+ end
103
+
104
+ class ApplicationControler
105
+ def some_filer
106
+ ...
107
+ end
108
+ end
109
+ ```
110
+
111
+ #### ForceGCProfiler
112
+
113
+ ```ruby
114
+ class ForceGCProfiler < SpeedGun::Profiler::Base
115
+ # You can define profiler type name.
116
+ def self.type
117
+ :force_gc_profiler
118
+ end
119
+
120
+ # `#before_profile` is called on before profiling.
121
+ def before_profile
122
+ @before_gc_disable = GC.enable
123
+ GC.start
124
+ end
125
+
126
+ # `#after_profile` is called on after profiling.
127
+ def after_profile
128
+ GC.disable if @before_gc_disable
129
+ end
130
+ end
131
+
132
+ SpeedGun.profile(:force_gc_profiler) { ... }
133
+ ```
134
+
135
+ ## Store
136
+
137
+ SpeedGun store request informations(profiling, environments and browser infos). You can select store engines.
138
+
139
+ ### Built-in Stores
140
+
141
+ - `SpeedGun::Store::Memory` (default store engine on rack)
142
+ - `max_entries` option: Set number of max profile entries(default: 100)
143
+ - `SpeedGun::Store::File` (default store engine on rails)
144
+ - `path` option: Set stored path(default: `/tmp/speed_gun` or `Rails.root/tmp/speed_gun`)
145
+ - `expires` option: Set expires in seconds(default: 1 day)
146
+ - `SpeedGun::Store::Memcache` (before `require 'speed_gun/store/memcache'`)
147
+ - `client` option: Set memcache client instance(default: `Dalli::Clinet.new`)
148
+ - `prefix` option: Set prefix of your profile key(default: `'speed-gun-'`)
149
+ - `expires` option: Set expires in seconds(default: 1 day)
150
+ - `SpeedGun::Store::Redis` (before `require 'speed_gun/store/redis'`)
151
+ - `client` option: Set redis client instance(default: `Redis.new`)
152
+ - `prefix` option: Set prefix of your profile key(default: `'speed-gun-'`)
153
+ - `expires` option: Set expires in seconds(default: 1 day)
154
+
155
+ ### Custom Store
156
+
157
+ SpeedGun's store engines requires `[]` and `[]=` methods.
158
+
159
+ ## Contributing
160
+
161
+ Please pull-requests :octocat: <http://github.com/rosylilly/speed_gun>
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,65 @@
1
+ if(!window['speedGun']) { window.speedGun = {}; };
2
+
3
+ (function($) {
4
+ if(!$) { return }
5
+
6
+ speedGun.sendBrowserInfo = function() {
7
+ var data = {};
8
+ var p = window['performance'];
9
+
10
+ data.user_agent = navigator.userAgent;
11
+
12
+ if(p['navigation']) {
13
+ data.navigation = {
14
+ type: p.navigation.type,
15
+ redirect_count: p.navigation.redirectCount
16
+ };
17
+ }
18
+
19
+ if(p['timing']) {
20
+ var t = p.timing;
21
+ data.timing = {
22
+ navigationStart: t.navigationStart,
23
+ redirectStart: t.redirectStart,
24
+ unloadEventStart: t.unloadEventStart,
25
+ unloadEventEnd: t.unloadEventEnd,
26
+ redirectEnd: t.redirectEnd,
27
+ fetchStart: t.fetchStart,
28
+ domainLookupStart: t.domainLookupStart,
29
+ domainLookupEnd: t.domainLookupEnd,
30
+ connectStart: t.connectStart,
31
+ secureConnectionStart: t.secureConnectionStart,
32
+ connectEnd: t.connectEnd,
33
+ requestStart: t.requestStart,
34
+ responseStart: t.responseStart,
35
+ responseEnd: t.responseEnd,
36
+ domLoading: t.domLoading,
37
+ domInteractive: t.domInteractive,
38
+ domContentLoadedEventStart: t.domContentLoadedEventStart,
39
+ domContentLoadedEventEnd: t.domContentLoadedEventEnd,
40
+ domComplete: t.domComplete,
41
+ loadEventStart: t.loadEventStart,
42
+ loadEventEnd: t.loadEventEnd,
43
+ };
44
+ }
45
+
46
+ speedGun.send({ browser: data });
47
+ $('#speed_gun_total').text(
48
+ (t.domContentLoadedEventEnd - t.navigationStart).toString() + 'ms'
49
+ );
50
+ };
51
+
52
+ speedGun.send = function(data) {
53
+ $.post(speedGun.endpoint, data, function() {});
54
+ };
55
+
56
+ var loadedInterval = setInterval(function() {
57
+ if (performance.timing.loadEventEnd != 0) {
58
+ clearInterval(loadedInterval);
59
+
60
+ speedGun.id = $('#speed_gun').data('speed-gun-id');
61
+ speedGun.endpoint = $('#speed_gun').data('speed-gun-endpoint') + "/" + speedGun.id;
62
+ speedGun.sendBrowserInfo()
63
+ }
64
+ }, 100);
65
+ })(window['jQuery'] || window['Zepto']);
@@ -0,0 +1,45 @@
1
+ if(!window['speedGun']) { window.speedGun = {}; };
2
+ speedGun.enableConsoleProfile = !!(window['console'] && console['profile']);
3
+ speedGun.profileCount = 0;
4
+
5
+ speedGun.profile = function(title, func) {
6
+ speedGun.profileCount++;
7
+ if(!func) {
8
+ func = title;
9
+ title = undefined;
10
+ };
11
+ if(!title) {
12
+ title = "Speed Gun Profile #" + speedGun.profileCount;
13
+ };
14
+ var callstack = [];
15
+ var caller = arguments['callee'];
16
+ if(caller) {
17
+ while(caller) {
18
+ caller = caller['caller'];
19
+ if(caller) { callstack.push(caller.toString()); };
20
+ }
21
+ }
22
+ var before = +(new Date);
23
+ if(speedGun.enableConsoleProfile) { console.profile(title); };
24
+ ret = func();
25
+ if(speedGun.enableConsoleProfile) { console.profileEnd(title); };
26
+ var elapsedTime = (+(new Date)) - before;
27
+ if(speedGun['send']) {
28
+ speedGun.send(
29
+ { js: { title: title, elapsed_time: elapsedTime, backtrace: callstack } }
30
+ );
31
+ };
32
+ return ret;
33
+ };
34
+
35
+ speedGun.profileMethod = function(object, methodName, title) {
36
+ if(!title) { title = "#" + methodName; };
37
+ var method = object[methodName];
38
+ var func = function() {
39
+ var args = arguments;
40
+ return speedGun.profile(title, function() {
41
+ return method.apply(object, args);
42
+ });
43
+ };
44
+ object[methodName] = func;
45
+ }
@@ -0,0 +1,9 @@
1
+ #speed_gun(data-speed-gun-endpoint="#{SpeedGun.config.prefix}/profile" data-speed-gun-id="#{SpeedGun.current.id}" data-rack-ms="#{SpeedGun.current.profiles.first.elapsed_time * 1000}")
2
+ - if SpeedGun.config.show_button?
3
+ #speed_gun_button(style="position: fixed; bottom: 10px; right: 10px;")
4
+ a#toggle_speed_gun(href="#{File.join(SpeedGun.config.prefix, 'profile', SpeedGun.current.id)}" target="_blank" style="display: block; padding: 2px 5px; font-size: 9px; line-height: 2; box-shadow: 0 0 2px #333; background-color: #fff; color: #333; text-decoration: none; border-radius: 3px;")
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")
@@ -0,0 +1,65 @@
1
+ if(!window['speedGun']) { window.speedGun = {}; };
2
+
3
+ (function($) {
4
+ if(!$) { return }
5
+
6
+ speedGun.sendBrowserInfo = function() {
7
+ var data = {};
8
+ var p = window['performance'];
9
+
10
+ data.user_agent = navigator.userAgent;
11
+
12
+ if(p['navigation']) {
13
+ data.navigation = {
14
+ type: p.navigation.type,
15
+ redirect_count: p.navigation.redirectCount
16
+ };
17
+ }
18
+
19
+ if(p['timing']) {
20
+ var t = p.timing;
21
+ data.timing = {
22
+ navigationStart: t.navigationStart,
23
+ redirectStart: t.redirectStart,
24
+ unloadEventStart: t.unloadEventStart,
25
+ unloadEventEnd: t.unloadEventEnd,
26
+ redirectEnd: t.redirectEnd,
27
+ fetchStart: t.fetchStart,
28
+ domainLookupStart: t.domainLookupStart,
29
+ domainLookupEnd: t.domainLookupEnd,
30
+ connectStart: t.connectStart,
31
+ secureConnectionStart: t.secureConnectionStart,
32
+ connectEnd: t.connectEnd,
33
+ requestStart: t.requestStart,
34
+ responseStart: t.responseStart,
35
+ responseEnd: t.responseEnd,
36
+ domLoading: t.domLoading,
37
+ domInteractive: t.domInteractive,
38
+ domContentLoadedEventStart: t.domContentLoadedEventStart,
39
+ domContentLoadedEventEnd: t.domContentLoadedEventEnd,
40
+ domComplete: t.domComplete,
41
+ loadEventStart: t.loadEventStart,
42
+ loadEventEnd: t.loadEventEnd,
43
+ };
44
+ }
45
+
46
+ speedGun.send({ browser: data });
47
+ $('#speed_gun_total').text(
48
+ (t.domContentLoadedEventEnd - t.navigationStart).toString() + 'ms'
49
+ );
50
+ };
51
+
52
+ speedGun.send = function(data) {
53
+ $.post(speedGun.endpoint, data, function() {});
54
+ };
55
+
56
+ var loadedInterval = setInterval(function() {
57
+ if (performance.timing.loadEventEnd != 0) {
58
+ clearInterval(loadedInterval);
59
+
60
+ speedGun.id = $('#speed_gun').data('speed-gun-id');
61
+ speedGun.endpoint = $('#speed_gun').data('speed-gun-endpoint') + "/" + speedGun.id;
62
+ speedGun.sendBrowserInfo()
63
+ }
64
+ }, 100);
65
+ })(window['jQuery'] || window['Zepto']);