rack-insight 0.5.0

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 (126) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +1 -0
  3. data/.simplecov +4 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG +58 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +82 -0
  8. data/LICENSE +24 -0
  9. data/README.md +189 -0
  10. data/Rakefile +27 -0
  11. data/TODO +7 -0
  12. data/lib/rack-insight.rb +1 -0
  13. data/lib/rack/insight.rb +19 -0
  14. data/lib/rack/insight/app.rb +198 -0
  15. data/lib/rack/insight/config.rb +30 -0
  16. data/lib/rack/insight/database.rb +193 -0
  17. data/lib/rack/insight/enable-button.rb +43 -0
  18. data/lib/rack/insight/filtered_backtrace.rb +45 -0
  19. data/lib/rack/insight/instrumentation.rb +9 -0
  20. data/lib/rack/insight/instrumentation/backstage.rb +10 -0
  21. data/lib/rack/insight/instrumentation/client.rb +20 -0
  22. data/lib/rack/insight/instrumentation/instrument.rb +109 -0
  23. data/lib/rack/insight/instrumentation/package-definition.rb +58 -0
  24. data/lib/rack/insight/instrumentation/probe-definition.rb +20 -0
  25. data/lib/rack/insight/instrumentation/probe.rb +196 -0
  26. data/lib/rack/insight/instrumentation/setup.rb +32 -0
  27. data/lib/rack/insight/logger.rb +53 -0
  28. data/lib/rack/insight/options.rb +116 -0
  29. data/lib/rack/insight/panel.rb +135 -0
  30. data/lib/rack/insight/panel_app.rb +31 -0
  31. data/lib/rack/insight/panels-content.rb +22 -0
  32. data/lib/rack/insight/panels-header.rb +18 -0
  33. data/lib/rack/insight/panels/active_record_panel.rb +46 -0
  34. data/lib/rack/insight/panels/active_resource_panel.rb +48 -0
  35. data/lib/rack/insight/panels/active_resource_panel/query.rb +27 -0
  36. data/lib/rack/insight/panels/cache_panel.rb +68 -0
  37. data/lib/rack/insight/panels/cache_panel/panel_app.rb +46 -0
  38. data/lib/rack/insight/panels/cache_panel/stats.rb +90 -0
  39. data/lib/rack/insight/panels/log_panel.rb +53 -0
  40. data/lib/rack/insight/panels/memory_panel.rb +36 -0
  41. data/lib/rack/insight/panels/mongo_panel.rb +41 -0
  42. data/lib/rack/insight/panels/mongo_panel/mongo_extension.rb +24 -0
  43. data/lib/rack/insight/panels/mongo_panel/stats.rb +46 -0
  44. data/lib/rack/insight/panels/rails_info_panel.rb +19 -0
  45. data/lib/rack/insight/panels/redis_panel.rb +42 -0
  46. data/lib/rack/insight/panels/redis_panel/redis_extension.rb +23 -0
  47. data/lib/rack/insight/panels/redis_panel/stats.rb +50 -0
  48. data/lib/rack/insight/panels/request_variables_panel.rb +70 -0
  49. data/lib/rack/insight/panels/speedtracer_panel.rb +89 -0
  50. data/lib/rack/insight/panels/speedtracer_panel/profiling.rb +29 -0
  51. data/lib/rack/insight/panels/speedtracer_panel/trace-app.rb +52 -0
  52. data/lib/rack/insight/panels/speedtracer_panel/tracer.rb +213 -0
  53. data/lib/rack/insight/panels/sphinx_panel.rb +41 -0
  54. data/lib/rack/insight/panels/sphinx_panel/stats.rb +94 -0
  55. data/lib/rack/insight/panels/sql_panel.rb +53 -0
  56. data/lib/rack/insight/panels/sql_panel/panel_app.rb +37 -0
  57. data/lib/rack/insight/panels/sql_panel/query.rb +94 -0
  58. data/lib/rack/insight/panels/templates_panel.rb +58 -0
  59. data/lib/rack/insight/panels/templates_panel/rendering.rb +81 -0
  60. data/lib/rack/insight/panels/timer_panel.rb +40 -0
  61. data/lib/rack/insight/params_signature.rb +61 -0
  62. data/lib/rack/insight/path-filter.rb +23 -0
  63. data/lib/rack/insight/public/__insight__/bookmarklet.html +10 -0
  64. data/lib/rack/insight/public/__insight__/bookmarklet.js +223 -0
  65. data/lib/rack/insight/public/__insight__/insight.css +235 -0
  66. data/lib/rack/insight/public/__insight__/insight.js +127 -0
  67. data/lib/rack/insight/public/__insight__/jquery-1.3.2.js +4376 -0
  68. data/lib/rack/insight/public/__insight__/jquery.tablesorter.min.js +1 -0
  69. data/lib/rack/insight/public/__insight__/spinner.gif +0 -0
  70. data/lib/rack/insight/rack_static_bug_avoider.rb +16 -0
  71. data/lib/rack/insight/redirect_interceptor.rb +25 -0
  72. data/lib/rack/insight/render.rb +72 -0
  73. data/lib/rack/insight/request-recorder.rb +22 -0
  74. data/lib/rack/insight/rspec_matchers.rb +33 -0
  75. data/lib/rack/insight/toolbar.rb +69 -0
  76. data/lib/rack/insight/version.rb +7 -0
  77. data/lib/rack/insight/views/enable-button.html.erb +21 -0
  78. data/lib/rack/insight/views/error.html.erb +17 -0
  79. data/lib/rack/insight/views/headers_fragment.html.erb +20 -0
  80. data/lib/rack/insight/views/panels/active_record.html.erb +17 -0
  81. data/lib/rack/insight/views/panels/active_resource.html.erb +47 -0
  82. data/lib/rack/insight/views/panels/cache.html.erb +93 -0
  83. data/lib/rack/insight/views/panels/execute_sql.html.erb +32 -0
  84. data/lib/rack/insight/views/panels/explain_sql.html.erb +32 -0
  85. data/lib/rack/insight/views/panels/log.html.erb +21 -0
  86. data/lib/rack/insight/views/panels/mongo.html.erb +32 -0
  87. data/lib/rack/insight/views/panels/profile_sql.html.erb +32 -0
  88. data/lib/rack/insight/views/panels/rails_info.html.erb +19 -0
  89. data/lib/rack/insight/views/panels/redis.html.erb +46 -0
  90. data/lib/rack/insight/views/panels/request_variables.html.erb +25 -0
  91. data/lib/rack/insight/views/panels/speedtracer/serverevent.html.erb +10 -0
  92. data/lib/rack/insight/views/panels/speedtracer/servertrace.html.erb +12 -0
  93. data/lib/rack/insight/views/panels/speedtracer/traces.html.erb +18 -0
  94. data/lib/rack/insight/views/panels/sphinx.html.erb +32 -0
  95. data/lib/rack/insight/views/panels/sql.html.erb +43 -0
  96. data/lib/rack/insight/views/panels/templates.html.erb +6 -0
  97. data/lib/rack/insight/views/panels/timer.html.erb +19 -0
  98. data/lib/rack/insight/views/panels/view_cache.html.erb +19 -0
  99. data/lib/rack/insight/views/redirect.html.erb +16 -0
  100. data/lib/rack/insight/views/request_fragment.html.erb +25 -0
  101. data/lib/rack/insight/views/toolbar.html.erb +29 -0
  102. data/rack-insight.gemspec +40 -0
  103. data/spec/custom_matchers.rb +0 -0
  104. data/spec/fixtures/config.ru +8 -0
  105. data/spec/fixtures/dummy_panel.rb +2 -0
  106. data/spec/fixtures/sample_app.rb +72 -0
  107. data/spec/fixtures/star_trek_panel.rb +1 -0
  108. data/spec/insight_spec.rb +163 -0
  109. data/spec/instrumentation_spec.rb +188 -0
  110. data/spec/rack/insight/config_spec.rb +20 -0
  111. data/spec/rack/insight/panels/active_record_panel_spec.rb +43 -0
  112. data/spec/rack/insight/panels/active_resource_panel_spec.rb +40 -0
  113. data/spec/rack/insight/panels/cache_panel_spec.rb +178 -0
  114. data/spec/rack/insight/panels/log_panel_spec.rb +44 -0
  115. data/spec/rack/insight/panels/memory_panel_spec.rb +21 -0
  116. data/spec/rack/insight/panels/mongo_panel_spec_pending.rb +52 -0
  117. data/spec/rack/insight/panels/rails_info_panel_spec.rb +29 -0
  118. data/spec/rack/insight/panels/redis_panel_spec.rb +67 -0
  119. data/spec/rack/insight/panels/speedtracer_panel_spec.rb +86 -0
  120. data/spec/rack/insight/panels/sql_panel_spec.rb +146 -0
  121. data/spec/rack/insight/panels/templates_panel_spec.rb +86 -0
  122. data/spec/rack/insight/panels/timer_panel_spec.rb +38 -0
  123. data/spec/rcov.opts +1 -0
  124. data/spec/spec.opts +1 -0
  125. data/spec/spec_helper.rb +111 -0
  126. metadata +380 -0
@@ -0,0 +1,40 @@
1
+ require 'benchmark'
2
+
3
+ module Rack::Insight
4
+ class TimerPanel < Panel
5
+ def initialize(app)
6
+ super
7
+ table_setup("timer")
8
+ end
9
+
10
+ def name
11
+ "timer"
12
+ end
13
+
14
+ def call(env)
15
+ status, headers, body = nil
16
+ @times = Benchmark.measure do
17
+ status, headers, body = @app.call(env)
18
+ end
19
+
20
+ store(env, [
21
+ ["User CPU time", "%.2fms" % (@times.utime * 1_000)],
22
+ ["System CPU time", "%.2fms" % (@times.stime * 1_000)],
23
+ ["Total CPU time", "%.2fms" % (@times.total * 1_000)],
24
+ ["Elapsed time", "%.2fms" % (@times.real * 1_000)]
25
+ ])
26
+
27
+ return [status, headers, body]
28
+ end
29
+
30
+ def heading_for_request(number)
31
+ measurements = retrieve(number).first
32
+
33
+ measurements.last.last
34
+ end
35
+
36
+ def content_for_request(number)
37
+ render_template "panels/timer", :measurements => retrieve(number).first
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,61 @@
1
+ require "digest"
2
+
3
+ module Rack::Insight
4
+
5
+ class ParamsSignature
6
+ extend ERB::Util
7
+
8
+ def self.sign(request, hash)
9
+ parts = []
10
+
11
+ hash.keys.sort.each do |key|
12
+ parts << "#{key}=#{u(hash[key])}"
13
+ end
14
+
15
+ signature = new(request).signature(hash)
16
+ parts << "hash=#{u(signature)}"
17
+
18
+ parts.join("&amp;")
19
+ end
20
+
21
+ attr_reader :request
22
+
23
+ def initialize(request)
24
+ @request = request
25
+ end
26
+
27
+ def secret_key
28
+ @request.env['rack-insight.secret_key']
29
+ end
30
+
31
+ def secret_key_blank?
32
+ secret_key.nil? || secret_key == ""
33
+ end
34
+
35
+ def validate!
36
+ if secret_key_blank?
37
+ raise SecurityError.new("Missing secret key")
38
+ elsif request.params["hash"] != signature(request.params)
39
+ raise SecurityError.new("Invalid query hash.")
40
+ end
41
+ end
42
+
43
+ def signature(params)
44
+ Digest::SHA1.hexdigest(signature_base(params))
45
+ end
46
+
47
+ def signature_base(params)
48
+ signature = []
49
+ signature << secret_key
50
+
51
+ params.keys.sort.each do |key|
52
+ next if key == "hash"
53
+ signature << params[key].to_s
54
+ end
55
+
56
+ signature.join(":")
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,23 @@
1
+ require 'rack/insight/logger'
2
+
3
+ module Rack::Insight
4
+ class PathFilter
5
+ include Logging
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ filters = env['rack-insight.path_filters'].map do |string|
12
+ %r{^#{string}}
13
+ end
14
+
15
+ unless filter = filters.find{|regex| regex =~ env['PATH_INFO']}
16
+ return [404, {}, []]
17
+ end
18
+
19
+ logger.debug{ "Shortcutting collection stack: #{filter} =~ #{env['PATH_INFO']}"}
20
+ return @app.call(env)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ <html>
2
+ <head>
3
+ </head>
4
+ <body>
5
+ <br/><br/><br/>
6
+ <a href="javascript: (function(){var script=document.createElement('script'); script.src='/__insight__/bookmarklet.js'; document.getElementsByTagName('head')[0].appendChild(script);})()">
7
+ Toggle Rack::Insight
8
+ </a>
9
+ </body>
10
+ </html>
@@ -0,0 +1,223 @@
1
+ /**
2
+ *
3
+ * Secure Hash Algorithm (SHA1)
4
+ * http://www.webtoolkit.info/
5
+ *
6
+ **/
7
+
8
+ document.SHA1 = function(msg) {
9
+ function rotate_left(n,s) {
10
+ var t4 = ( n<<s ) | (n>>>(32-s));
11
+ return t4;
12
+ };
13
+
14
+ function lsb_hex(val) {
15
+ var str="";
16
+ var i;
17
+ var vh;
18
+ var vl;
19
+
20
+ for( i=0; i<=6; i+=2 ) {
21
+ vh = (val>>>(i*4+4))&0x0f;
22
+ vl = (val>>>(i*4))&0x0f;
23
+ str += vh.toString(16) + vl.toString(16);
24
+ }
25
+ return str;
26
+ };
27
+
28
+ function cvt_hex(val) {
29
+ var str="";
30
+ var i;
31
+ var v;
32
+
33
+ for( i=7; i>=0; i-- ) {
34
+ v = (val>>>(i*4))&0x0f;
35
+ str += v.toString(16);
36
+ }
37
+ return str;
38
+ };
39
+
40
+
41
+ function Utf8Encode(string) {
42
+ string = string.replace(/\r\n/g,"\n");
43
+ var utftext = "";
44
+
45
+ for (var n = 0; n < string.length; n++) {
46
+
47
+ var c = string.charCodeAt(n);
48
+
49
+ if (c < 128) {
50
+ utftext += String.fromCharCode(c);
51
+ }
52
+ else if((c > 127) && (c < 2048)) {
53
+ utftext += String.fromCharCode((c >> 6) | 192);
54
+ utftext += String.fromCharCode((c & 63) | 128);
55
+ }
56
+ else {
57
+ utftext += String.fromCharCode((c >> 12) | 224);
58
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
59
+ utftext += String.fromCharCode((c & 63) | 128);
60
+ }
61
+
62
+ }
63
+
64
+ return utftext;
65
+ };
66
+
67
+ var blockstart;
68
+ var i, j;
69
+ var W = new Array(80);
70
+ var H0 = 0x67452301;
71
+ var H1 = 0xEFCDAB89;
72
+ var H2 = 0x98BADCFE;
73
+ var H3 = 0x10325476;
74
+ var H4 = 0xC3D2E1F0;
75
+ var A, B, C, D, E;
76
+ var temp;
77
+
78
+ msg = Utf8Encode(msg);
79
+
80
+ var msg_len = msg.length;
81
+
82
+ var word_array = new Array();
83
+ for( i=0; i<msg_len-3; i+=4 ) {
84
+ j = msg.charCodeAt(i)<<24 | msg.charCodeAt(i+1)<<16 |
85
+ msg.charCodeAt(i+2)<<8 | msg.charCodeAt(i+3);
86
+ word_array.push( j );
87
+ }
88
+
89
+ switch( msg_len % 4 ) {
90
+ case 0:
91
+ i = 0x080000000;
92
+ break;
93
+ case 1:
94
+ i = msg.charCodeAt(msg_len-1)<<24 | 0x0800000;
95
+ break;
96
+
97
+ case 2:
98
+ i = msg.charCodeAt(msg_len-2)<<24 | msg.charCodeAt(msg_len-1)<<16 | 0x08000;
99
+ break;
100
+
101
+ case 3:
102
+ i = msg.charCodeAt(msg_len-3)<<24 | msg.charCodeAt(msg_len-2)<<16 | msg.charCodeAt(msg_len-1)<<8 | 0x80;
103
+ break;
104
+ }
105
+
106
+ word_array.push( i );
107
+
108
+ while( (word_array.length % 16) != 14 ) word_array.push( 0 );
109
+
110
+ word_array.push( msg_len>>>29 );
111
+ word_array.push( (msg_len<<3)&0x0ffffffff );
112
+
113
+
114
+ for ( blockstart=0; blockstart<word_array.length; blockstart+=16 ) {
115
+
116
+ for( i=0; i<16; i++ ) W[i] = word_array[blockstart+i];
117
+ for( i=16; i<=79; i++ ) W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
118
+
119
+ A = H0;
120
+ B = H1;
121
+ C = H2;
122
+ D = H3;
123
+ E = H4;
124
+
125
+ for( i= 0; i<=19; i++ ) {
126
+ temp = (rotate_left(A,5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
127
+ E = D;
128
+ D = C;
129
+ C = rotate_left(B,30);
130
+ B = A;
131
+ A = temp;
132
+ }
133
+
134
+ for( i=20; i<=39; i++ ) {
135
+ temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
136
+ E = D;
137
+ D = C;
138
+ C = rotate_left(B,30);
139
+ B = A;
140
+ A = temp;
141
+ }
142
+
143
+ for( i=40; i<=59; i++ ) {
144
+ temp = (rotate_left(A,5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
145
+ E = D;
146
+ D = C;
147
+ C = rotate_left(B,30);
148
+ B = A;
149
+ A = temp;
150
+ }
151
+
152
+ for( i=60; i<=79; i++ ) {
153
+ temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
154
+ E = D;
155
+ D = C;
156
+ C = rotate_left(B,30);
157
+ B = A;
158
+ A = temp;
159
+ }
160
+
161
+ H0 = (H0 + A) & 0x0ffffffff;
162
+ H1 = (H1 + B) & 0x0ffffffff;
163
+ H2 = (H2 + C) & 0x0ffffffff;
164
+ H3 = (H3 + D) & 0x0ffffffff;
165
+ H4 = (H4 + E) & 0x0ffffffff;
166
+
167
+ }
168
+
169
+ var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
170
+
171
+ return temp.toLowerCase();
172
+ }
173
+
174
+ document.createCookie = function(name,value,days) {
175
+ if (days) {
176
+ var date = new Date();
177
+ date.setTime(date.getTime()+(days*24*60*60*1000));
178
+ var expires = "; expires="+date.toGMTString();
179
+ }
180
+ else
181
+ var expires = "";
182
+ document.cookie = name+"="+value+expires+"; path=/";
183
+ }
184
+
185
+ document.readCookie = function(name) {
186
+ var nameEQ = name + "=";
187
+ var ca = document.cookie.split(';');
188
+ for(var i=0;i < ca.length;i++) {
189
+ var c = ca[i];
190
+ while (c.charAt(0)==' ')
191
+ c = c.substring(1,c.length);
192
+ if (c.indexOf(nameEQ) == 0)
193
+ return c.substring(nameEQ.length,c.length);
194
+ }
195
+ return null;
196
+ }
197
+
198
+ document.eraseCookie = function(name) {
199
+ document.createCookie(name,"",-1);
200
+ }
201
+
202
+ document.insightEnable = function() {
203
+ var password = prompt("Rack::Insight password:", "");
204
+ if (password != null) {
205
+ document.createCookie('rack-insight_password', document.SHA1('rack-insight:'+password));
206
+ document.createCookie('rack-insight_enabled', "1");
207
+ window.location.reload();
208
+ }
209
+ }
210
+
211
+ document.insightDisable = function() {
212
+ document.eraseCookie('rack-insight_password');
213
+ document.eraseCookie('rack-insight_enabled');
214
+ window.location.reload();
215
+ }
216
+
217
+ document.insightBookmarklet = function() {
218
+ if (document.readCookie('rack-insight_password')) {
219
+ document.insightDisable()
220
+ } else {
221
+ document.insightEnable()
222
+ }
223
+ }
@@ -0,0 +1,235 @@
1
+ #rack-insight {
2
+ color: #000;
3
+ float: none;
4
+ margin: 0;
5
+ padding: 0;
6
+ position: static;
7
+ }
8
+
9
+ #rack-insight a {
10
+ color: #f7c757;
11
+ }
12
+ #rack-insight a:hover {
13
+ color: #aaa;
14
+ }
15
+
16
+ #rack-insight_toolbar {
17
+ background: #326342;
18
+ height: 30px;
19
+ z-index: 1000000000;
20
+ position:absolute;
21
+ left:0;
22
+ right:0;
23
+ cursor: pointer;
24
+ }
25
+ .insight_bottom #rack-insight_toolbar {
26
+ bottom:0;
27
+ border-top: 2px solid #234f32;
28
+ }
29
+ .insight_top #rack-insight_toolbar {
30
+ top:0;
31
+ border-bottom: 2px solid #234f32;
32
+ }
33
+
34
+ .insight_error #rack-insight_toolbar {
35
+ background: #ff0000;
36
+ color: #fff;
37
+ border: none;
38
+ }
39
+
40
+ .insight_error #rack-insight_toolbar p {
41
+ margin-top: 6px;
42
+ margin-left: 15px;
43
+ font-weight: bold;
44
+ color: #fff;
45
+ }
46
+
47
+ #rack-insight_toolbar ul {
48
+ margin: 0;
49
+ padding: 0;
50
+ list-style: none;
51
+ }
52
+
53
+ #rack-insight_toolbar li {
54
+ color: #fff;
55
+ display: inline;
56
+ font-size: 11px;
57
+ font-weight: bold;
58
+ float: none;
59
+ height: 20px;
60
+ margin: 0;
61
+ padding: 0;
62
+ line-height: 30px;
63
+ position: relative;
64
+ width: auto;
65
+ }
66
+ #rack-insight_toolbar li a {
67
+ border-left: 1px solid #487858;
68
+ padding: 8px 9px 9px;
69
+ }
70
+
71
+ #rack-insight_toolbar li a:hover {
72
+ background: #487858;
73
+ color: #fff;
74
+ }
75
+
76
+ #rack-insight_toolbar li:last-child {
77
+ border-right: 1px solid #487858;
78
+ }
79
+
80
+ #rack-insight_toolbar #rack-insight_disable_button {
81
+ color: red;
82
+ font-weight: bold;
83
+ padding-left: 5px;
84
+ }
85
+
86
+ #rack-insight_toolbar #rack-insight_debug_button {
87
+ color: #92ef3f;
88
+ padding-left: 5px;
89
+ }
90
+
91
+ #rack-insight .panel_content {
92
+ background: #2a5738;
93
+ border-bottom: 2px solid #234f32;
94
+ border-top: 2px solid #487858;
95
+ display: none;
96
+ position: absolute;
97
+ margin: 0;
98
+ padding: 10px;
99
+ width: auto;
100
+ left: 0px;
101
+ right: 0px;
102
+ color: black;
103
+ z-index: 1000000;
104
+ overflow: auto;
105
+ }
106
+
107
+ #rack-insight.insight_top .panel_content {
108
+ top: 32px;
109
+ }
110
+
111
+ #rack-insight.insight_bottom .panel_content {
112
+ bottom: 32px;
113
+ }
114
+
115
+ #rack-insight .panel_content p a,
116
+ #rack-insight .panel_content dl a {
117
+ color: #40684c;
118
+ }
119
+
120
+ #rack-insight .panel_content p a:hover,
121
+ #rack-insight .panel_content dl a:hover {
122
+ color: #92EF3F;
123
+ }
124
+
125
+ #rack-insight .panel_content h3 {
126
+ border-bottom: 1px solid #40684c;
127
+ color: #92ef3f;
128
+ padding: 0 0 5px;
129
+ }
130
+
131
+ #rack-insight .panel_content p {
132
+ padding: 0 5px;
133
+ }
134
+
135
+ #rack-insight .panel_content p,
136
+ #rack-insight .panel_content table,
137
+ #rack-insight .panel_content ol,
138
+ #rack-insight .panel_content dl {
139
+ margin: 5px 0 15px;
140
+ background-color: #fff;
141
+ }
142
+
143
+ #rack-insight .panel_content ul {
144
+ padding: 10px 30px 10px 30px;
145
+ background-color: #fff;
146
+ }
147
+
148
+ #rack-insight .panel_content ul ul {
149
+ padding: 0;
150
+ }
151
+
152
+ #rack-insight #speedtracer.panel_content ul ul {
153
+ padding: 0 0 0 8px;
154
+ }
155
+
156
+ #rack-insight .panel_content table {
157
+ width: 100%;
158
+ clear: both;
159
+ }
160
+
161
+ #rack-insight .panel_content table a {
162
+ color: #40684C;
163
+ }
164
+
165
+ #rack-insight .panel_content table th {
166
+ background-color: #9dcc49;
167
+ font-weight: bold;
168
+ color: #000;
169
+ font-size: 11px;
170
+ padding: 3px 7px 3px;
171
+ text-align: left;
172
+ cursor: pointer;
173
+ border-right: 1px solid #b9d977;
174
+ }
175
+
176
+ #rack-insight .panel_content table td {
177
+ padding: 5px 10px;
178
+ font-size: 11px;
179
+ background: #fff;
180
+ color: #000;
181
+ vertical-align: top;
182
+ }
183
+ #rack-insight .panel_content table tr.odd td {
184
+ background: #eee;
185
+ }
186
+
187
+ #rack-insight .panel_content .panel_controls {
188
+ float: right;
189
+ font-weight: bold;
190
+ }
191
+
192
+ #rack-insight .panel_content .panel_controls form {
193
+ display: inline;
194
+ }
195
+
196
+
197
+ #rack-insight .panel_content dt, #rack-insight .panel_content dd {
198
+ display: block;
199
+ }
200
+
201
+ #rack-insight .panel_content dd {
202
+ margin-left: 10px;
203
+ }
204
+
205
+ #rack-insight .panel_content table tr.odd td.insight_spinner,
206
+ #rack-insight .panel_content table tr.even td.insight_spinner,
207
+ #rack-insight .panel_content table td.insight_spinner,
208
+ #rack-insight .insight_spinner {
209
+ background-image: url(/__insight__/spinner.gif);
210
+ background-repeat: no-repeat;
211
+ background-position: center center;
212
+ text-indent: -3000px;
213
+ color: transparent;
214
+ }
215
+
216
+ #rack-insight #sql.panel_content th.time {
217
+ width: 80px;
218
+ }
219
+
220
+ #rack-insight #sql.panel_content th.backtrace {
221
+ width: 100px;
222
+ }
223
+
224
+ #rack-insight #sql.panel_content th.actions {
225
+ width: 150px;
226
+ }
227
+ #rack-insight #request_variables td.code > div {
228
+ max-height:200px;
229
+ max-width: 800px;
230
+ overflow:auto;
231
+ }
232
+
233
+ #rack-insight #templates ul {
234
+ padding-left:20px;
235
+ }