dev_panel 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/dev_panel.rb +10 -0
- data/lib/devpanel/extension.rb +47 -0
- data/lib/devpanel/middleware.rb +98 -0
- data/lib/devpanel/rails.rb +25 -0
- data/lib/devpanel/stats.rb +48 -0
- metadata +51 -0
data/lib/dev_panel.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module DevPanel
|
2
|
+
module Panel
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.after_filter :dev_panel_output
|
6
|
+
end
|
7
|
+
|
8
|
+
def dev_panel_output
|
9
|
+
self.response.body += dev_panel_ajax
|
10
|
+
end
|
11
|
+
|
12
|
+
def dev_panel_ajax
|
13
|
+
jquery_cdn + jquery_ui_cdn + ajax_call
|
14
|
+
end
|
15
|
+
|
16
|
+
def ajax_call
|
17
|
+
'<div id="DevPanel"></div><script type="text/javascript">
|
18
|
+
$.ajax({
|
19
|
+
url: "/__DevPanel/main",
|
20
|
+
success: function(response) {
|
21
|
+
$("#DevPanel").html(response);' + hide_container +
|
22
|
+
'
|
23
|
+
$("#devPanelHider").on("click", function(s) {
|
24
|
+
$("#devPanelContainer").toggle();
|
25
|
+
$.get("/__DevPanel/set_options?visible=" + $("#devPanelContainer").is(":visible"));
|
26
|
+
});
|
27
|
+
$("#devPanelWindow").draggable({stop: function() {
|
28
|
+
$.get("/__DevPanel/set_options?top=" + $("#devPanelWindow").position().top + "&left=" + $("#devPanelWindow").position().left);
|
29
|
+
}});
|
30
|
+
}
|
31
|
+
});
|
32
|
+
</script>'
|
33
|
+
end
|
34
|
+
|
35
|
+
def hide_container
|
36
|
+
(Stats.show?) ? '' : '$("#devPanelContainer").toggle()'
|
37
|
+
end
|
38
|
+
|
39
|
+
def jquery_cdn
|
40
|
+
'<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>'
|
41
|
+
end
|
42
|
+
|
43
|
+
def jquery_ui_cdn
|
44
|
+
'<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module DevPanel
|
2
|
+
class Middleware
|
3
|
+
def initialize(app)
|
4
|
+
@app = app
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
if env["REQUEST_URI"] =~ /__DevPanel\/main/
|
9
|
+
[200, { "Content-Type" => "text/plain; charset=utf-8" }, [dev_panel_output]]
|
10
|
+
elsif env["REQUEST_URI"] =~ /__DevPanel\/set_options/
|
11
|
+
params = Rack::Utils.parse_query(env['QUERY_STRING'], "&")
|
12
|
+
Stats.set_by_params(params)
|
13
|
+
[200, { "Content-Type" => "text/plain; charset=utf-8" }, ["#{Stats.show?} #{Stats.left} #{Stats.top}"]]
|
14
|
+
else
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def dev_panel_output
|
20
|
+
css + html_containers + html_table
|
21
|
+
end
|
22
|
+
|
23
|
+
def css
|
24
|
+
"<style>
|
25
|
+
#devPanelWindow {
|
26
|
+
border-radius: 3px;
|
27
|
+
margin-bottom: 2px;
|
28
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.03), 1px 1px 0 rgba(0, 0, 0, 0.05), -1px 1px 0 rgba(0, 0, 0, 0.05), 0 0 0 4px rgba(0, 0, 0, 0.04);
|
29
|
+
font-family: menlo, lucida console, monospace;
|
30
|
+
border: 2px solid #000;
|
31
|
+
}
|
32
|
+
|
33
|
+
#devPanelHider {
|
34
|
+
background: #F1F1F1;
|
35
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
36
|
+
font-family: arial;
|
37
|
+
font-size: 12.8px;
|
38
|
+
overflow: hidden;
|
39
|
+
padding: 6px 10px;
|
40
|
+
border: solid 1px #CCC;
|
41
|
+
border-bottom: 0;
|
42
|
+
border-top-left-radius: 2px;
|
43
|
+
border-top-right-radius: 2px;
|
44
|
+
}
|
45
|
+
|
46
|
+
#devPanelContainer {
|
47
|
+
font-family: menlo, lucida console, monospace;
|
48
|
+
background-color: #fff;
|
49
|
+
box-shadow: inset 3px 3px 3px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
50
|
+
}
|
51
|
+
|
52
|
+
#devPanelContainer td {
|
53
|
+
font-family: arial;
|
54
|
+
color: #000;
|
55
|
+
font-size: 10px;
|
56
|
+
font-weight: normal;
|
57
|
+
padding: 8px;
|
58
|
+
overflow: auto;
|
59
|
+
}
|
60
|
+
|
61
|
+
#devPanelContainer tr {
|
62
|
+
background-color: #FACC9B;;
|
63
|
+
}
|
64
|
+
|
65
|
+
#devPanelContainer td.firstColumn {
|
66
|
+
width: 60px;
|
67
|
+
font-weight: bold;
|
68
|
+
}
|
69
|
+
|
70
|
+
#devPanelContainer .alt {
|
71
|
+
background-color: #FFF;;
|
72
|
+
}
|
73
|
+
</style>"
|
74
|
+
end
|
75
|
+
|
76
|
+
def html_containers
|
77
|
+
str = '<div id="devPanelWindow" style="padding: 3px; color: #000; background-color: #F0F0F5; position: absolute; float: left; top: ' + Stats.top.to_s + 'px; left: ' + Stats.left.to_s + 'px;" >'
|
78
|
+
str += '<div id="devPanelHider" style="width: 150px; text-align:center; border: solid 1px #fff"><a href="#">Show/Hide Stats</a> / <span style="font-size: 10px">' + Stats.data[:action_controller].duration.round(0).to_s + 'ms</span></div>'
|
79
|
+
str += '<div id="devPanelContainer" style="width: 300px; padding-top: 20px">'
|
80
|
+
end
|
81
|
+
|
82
|
+
def html_table
|
83
|
+
str = '<table style="width: 300px; table-layout: fixed">'
|
84
|
+
str += "<tr class='alt'><td class='firstColumn'>Total Time:</td> <td>#{Stats.data[:action_controller].duration.round(2).to_s}ms</td></tr>"
|
85
|
+
controller_time = (Stats.data[:action_controller].duration - Stats.data[:action_controller].payload[:view_runtime])
|
86
|
+
str += "<tr><td class='firstColumn'>Controller Time:</td> <td> #{controller_time.round(2).to_s}ms</td></tr>"
|
87
|
+
str += "<tr class='alt'><td class='firstColumn'>View Time:</td> <td>#{Stats.data[:action_controller].payload[:view_runtime].round(2).to_s}ms</td></tr>"
|
88
|
+
str += "<tr><td class='firstColumn'>Partials Rendered:</td> <td> #{Stats.data[:partial_count] || 0}</td></tr>"
|
89
|
+
str += "<tr class='alt'><td class='firstColumn'>Response Code:</td> <td> #{Stats.data[:action_controller].payload[:status].to_s}</td></tr>"
|
90
|
+
str += "<tr><td class='firstColumn'>Controller:</td> <td> #{Stats.data[:action_controller].payload[:controller].to_s}</td></tr>"
|
91
|
+
str += "<tr class='alt'><td class='firstColumn'>Action:</td> <td> #{Stats.data[:action_controller].payload[:action].to_s}</td></tr>"
|
92
|
+
str += "<tr><td class='firstColumn'>Method:</td> <td> #{Stats.data[:action_controller].payload[:method].to_s}</td></tr>"
|
93
|
+
str += "<tr class='alt'><td class='firstColumn'>Params:</td> <td> #{Stats.data[:action_controller].payload[:params]}</td></tr>"
|
94
|
+
str += "<tr><td class='firstColumn'>Log:</td> <td> #{Stats.data[:log]}</td></tr>"
|
95
|
+
str += "</table></div></div>"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DevPanel
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer "dev_panel.configure_rails_initialization" do
|
4
|
+
unless Rails.env.production?
|
5
|
+
Rails.application.middleware.use DevPanel::Middleware
|
6
|
+
|
7
|
+
ActiveSupport::Notifications.subscribe('start_processing.action_controller') do |*args|
|
8
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
9
|
+
Stats.delete_data if event.payload[:format] == :html
|
10
|
+
end
|
11
|
+
|
12
|
+
ActiveSupport::Notifications.subscribe('process_action.action_controller') do |*args|
|
13
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
14
|
+
Stats.data[:action_controller] = event if event.payload[:format] == :html
|
15
|
+
end
|
16
|
+
|
17
|
+
ActiveSupport::Notifications.subscribe('render_partial.action_view') do |*args|
|
18
|
+
Stats.data[:partial_count] ||= 0
|
19
|
+
Stats.data[:partial_count] += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module DevPanel
|
2
|
+
class Stats
|
3
|
+
|
4
|
+
@@data ||= { log: "" }
|
5
|
+
@@visible = "false"
|
6
|
+
@@left = 0
|
7
|
+
@@top = 0
|
8
|
+
|
9
|
+
def self.set_by_params(params)
|
10
|
+
['visible', 'left', 'top'].each do |str|
|
11
|
+
Stats.send(str, params[str]) if params[str].present?
|
12
|
+
end
|
13
|
+
Stats.log(" ")
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.data
|
17
|
+
@@data ||= { log: "" }
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.delete_data
|
21
|
+
@@data = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.left(val = @@left)
|
25
|
+
return @@left if val.class != Fixnum && val.empty?
|
26
|
+
@@left = val || 0
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.top(val = @@top)
|
30
|
+
return @@top if val.class != Fixnum && val.empty?
|
31
|
+
@@top = val
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.visible(val = @@visible)
|
35
|
+
@@visible = val
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.show?
|
39
|
+
@@visible == "true"
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.log(log)
|
43
|
+
@@data[:log] ||= ""
|
44
|
+
@@data[:log] += CGI::escapeHTML("#{log}")
|
45
|
+
@@data[:log] += "<br>--------------<br>"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dev_panel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matthew Stopa
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-29 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A panel that appears in the browser to provide stats on page load times
|
15
|
+
and other debugging information for Rails 3
|
16
|
+
email: matthew.p.stopa@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/dev_panel.rb
|
22
|
+
- lib/devpanel/extension.rb
|
23
|
+
- lib/devpanel/middleware.rb
|
24
|
+
- lib/devpanel/rails.rb
|
25
|
+
- lib/devpanel/stats.rb
|
26
|
+
homepage: http://github.com/MattStopa/DevPanel
|
27
|
+
licenses: []
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 1.8.24
|
47
|
+
signing_key:
|
48
|
+
specification_version: 3
|
49
|
+
summary: DevPanel, a gem for performance stats and debugging information
|
50
|
+
test_files: []
|
51
|
+
has_rdoc:
|