lookout-query_reviewer 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +136 -0
  3. data/Rakefile +24 -0
  4. data/lib/query_reviewer.rb +66 -0
  5. data/lib/query_reviewer/array_extensions.rb +29 -0
  6. data/lib/query_reviewer/controller_extensions.rb +67 -0
  7. data/lib/query_reviewer/mysql_adapter_extensions.rb +92 -0
  8. data/lib/query_reviewer/mysql_analyzer.rb +62 -0
  9. data/lib/query_reviewer/query_warning.rb +17 -0
  10. data/lib/query_reviewer/rails.rb +37 -0
  11. data/lib/query_reviewer/sql_query.rb +131 -0
  12. data/lib/query_reviewer/sql_query_collection.rb +103 -0
  13. data/lib/query_reviewer/sql_sub_query.rb +45 -0
  14. data/lib/query_reviewer/tasks.rb +8 -0
  15. data/lib/query_reviewer/views/_box.html.erb +11 -0
  16. data/lib/query_reviewer/views/_box_ajax.js +34 -0
  17. data/lib/query_reviewer/views/_box_body.html.erb +73 -0
  18. data/lib/query_reviewer/views/_box_disabled.html.erb +2 -0
  19. data/lib/query_reviewer/views/_box_header.html.erb +1 -0
  20. data/lib/query_reviewer/views/_box_includes.html.erb +234 -0
  21. data/lib/query_reviewer/views/_explain.html.erb +30 -0
  22. data/lib/query_reviewer/views/_js_includes.html.erb +68 -0
  23. data/lib/query_reviewer/views/_js_includes_new.html.erb +68 -0
  24. data/lib/query_reviewer/views/_profile.html.erb +26 -0
  25. data/lib/query_reviewer/views/_query_sql.html.erb +8 -0
  26. data/lib/query_reviewer/views/_query_trace.html.erb +31 -0
  27. data/lib/query_reviewer/views/_query_with_warning.html.erb +54 -0
  28. data/lib/query_reviewer/views/_spectrum.html.erb +10 -0
  29. data/lib/query_reviewer/views/_warning_no_query.html.erb +8 -0
  30. data/lib/query_reviewer/views/query_review_box_helper.rb +99 -0
  31. data/query_reviewer_defaults.yml +39 -0
  32. metadata +77 -0
@@ -0,0 +1,2 @@
1
+ <p>SQL analysis has been disabled for you. A cookie must be set to enable analysis. This generally slows down your browser, so it's only recommended for users analyzing SQL queries.</p>
2
+ <p id="query_review_enable_link"><b><a href="#" onclick="createCookie('query_review_enabled', '1'); query_review_hide('query_review_enable_link'); alert('Cookie successfully set.');">Enabled it</a> on next page load and from now on.</b></p>
@@ -0,0 +1 @@
1
+ <a href="#" onclick="query_review_toggle(this.parentNode.nextSibling.nextSibling.id); return false;">SQL <%= parent_div_status %></a>
@@ -0,0 +1,234 @@
1
+ <style>
2
+ div#query_review_parent {
3
+ position: absolute;
4
+ top: 1px;
5
+ left: 1px;
6
+ z-index: 100000;
7
+ }
8
+
9
+ div.query_review_container {
10
+ float: left;
11
+ }
12
+
13
+ div.query_review {
14
+ height: 18px;
15
+ margin: 1px;
16
+ opacity: 0.75;
17
+ padding-left: 3px;
18
+ padding-right: 3px;
19
+ border: 1px solid black;
20
+ font-size: 12px;
21
+ font-weight: bold;
22
+ text-align: left;
23
+ }
24
+
25
+ div.query_review.sql_ok {
26
+ background-color: #090;
27
+ color: #020;
28
+ }
29
+
30
+ div.query_review.sql_warning {
31
+ background-color: #FAE100;
32
+ color: #F05000;
33
+ }
34
+
35
+ div.query_review.sql_critical {
36
+ background-color: #F99;
37
+ color: #A00;
38
+ }
39
+
40
+ div.query_review.sql_disabled {
41
+ background-color: #BBB;
42
+ color: #555;
43
+ }
44
+
45
+ div.query_review a {
46
+ color: inherit;
47
+ text-decoration: none;
48
+ }
49
+
50
+ div.query_review_details {
51
+ width: 900px;
52
+ height: 600px;
53
+ opacity: 0.9;
54
+ margin: 1px;
55
+ padding: 2px;
56
+ border: 1px solid black;
57
+ font-size: 12px;
58
+ overflow: auto;
59
+ background-color: #DDD;
60
+ text-align: left;
61
+ text-indent: 0px;
62
+ color: black;
63
+ }
64
+
65
+ div.query_review_details p {
66
+ margin: 2px 0 2px 0;
67
+ padding: 0px;
68
+ }
69
+
70
+ div.query_review_details a {
71
+ color: #29ABE2;
72
+ }
73
+
74
+ div.query_review_details ul {
75
+ list-style-type: circle;
76
+ padding-left: 15px;
77
+ }
78
+
79
+ div.query_review_details li {
80
+ clear: both;
81
+ }
82
+
83
+ div.query_review_details code {
84
+ white-space: normal;
85
+ line-height: 120%;
86
+ }
87
+
88
+ div.query_review_details table.explain th {
89
+ cell-padding: 5px;
90
+ }
91
+
92
+ div.query_review_details .title {
93
+ font-weight: bold;
94
+ }
95
+
96
+ div.query_review_details .indent {
97
+ padding-left: 10px;
98
+ }
99
+
100
+ div.query_review_details .number {
101
+ font-weight: bold;
102
+ }
103
+
104
+ div.query_review_details .bad {
105
+ color: #900;
106
+ }
107
+
108
+ div.query_review_details .good {
109
+ color: #090;
110
+ }
111
+
112
+ div.query_review_details div.divider {
113
+ width: 504px;
114
+ position: relative;
115
+ left: -2px;
116
+ height: 1px;
117
+ border-top: 1px dashed black;
118
+ margin: 2px 0 2px 0;
119
+ }
120
+
121
+ div.query_review_details .small {
122
+ font-size: 10px;
123
+ }
124
+
125
+ div.query_review_details .tbpadded {
126
+ padding-top: 3px;
127
+ padding-bottom: 3px;
128
+ }
129
+
130
+ div.query_review_details .trace {
131
+ background-color: #0C1021;
132
+ color: #7F908A;
133
+ padding: 5px;
134
+ margin-right: 30px;
135
+ }
136
+
137
+ div.query_review_details .trace .bold {
138
+ color: white;
139
+ }
140
+
141
+ div.query_review_details div.spectrum_container {
142
+ margin-top: 4px;
143
+ width: 35px;
144
+ display: block;
145
+ float: left;
146
+ position: relative;
147
+ height: 14px;
148
+ margin-right: 5px;
149
+ }
150
+
151
+ div.query_review_details div.spectrum_elem {
152
+ width: 1px;
153
+ display: block;
154
+ float: left;
155
+ height: 10px;
156
+ }
157
+ div.query_review_details div.spectrum_pointer {
158
+ width: 2px;
159
+ display: block;
160
+ float: left;
161
+ position: absolute;
162
+ height: 14px;
163
+ background-color: black;
164
+ top: -2px;
165
+ }
166
+
167
+ div.query_review_details table {
168
+ background-color: white;
169
+ border: 1px solid gray;
170
+ padding: 0px;
171
+ margin: 0px;
172
+ }
173
+
174
+ div.query_review_details tbody {
175
+ border: 0px;
176
+ padding: 0px;
177
+ margin: 0px;
178
+ }
179
+
180
+ div.query_review_details thead {
181
+ border-bottom: 1px solid gray;
182
+ padding: 0px;
183
+ margin: 0px;
184
+ }
185
+
186
+
187
+ div.query_review_details tr {
188
+ border: 0px;
189
+ padding: 0px;
190
+ margin: 0px;
191
+ }
192
+
193
+ div.query_review_details td {
194
+ border: 1px solid gray;
195
+ padding: 3px;
196
+ margin: 0px;
197
+ overflow: hidden;
198
+ }
199
+
200
+ div.query_review_details th {
201
+ border: 1px solid gray;
202
+ padding: 3px;
203
+ margin: 0px;
204
+ }
205
+
206
+ </style>
207
+
208
+ <style>
209
+ .sql {
210
+ color: black;
211
+ }
212
+ .sql .String {
213
+ color: #009933;
214
+ }
215
+ .sql .Keyword {
216
+ color: #0000FF;
217
+ }
218
+ .sql .Constant {
219
+ color: #6782D3;
220
+ }
221
+ .sql .Number {
222
+ color: #0066FF;
223
+ }
224
+ .sql .Comment {
225
+ color: #0066FF;
226
+ font-style: italic;
227
+ }
228
+ </style>
229
+
230
+ <% if defined?(Rails::Railtie) %>
231
+ <%= render :partial => "/js_includes_new" %>
232
+ <% else %>
233
+ <%= render :partial => "/js_includes" %>
234
+ <% end %>
@@ -0,0 +1,30 @@
1
+ <table class="explain">
2
+ <thead>
3
+ <tr>
4
+ <th>table</th>
5
+ <th>select_type</th>
6
+ <th>type</th>
7
+ <th>extra</th>
8
+ <th>possible_keys</th>
9
+ <th>key</th>
10
+ <th>key length</th>
11
+ <th>ref</th>
12
+ <th>rows</th>
13
+ </tr>
14
+ </thead>
15
+ <tbody>
16
+ <% query.subqueries.each do |subquery| %>
17
+ <tr>
18
+ <td title="<%= h subquery.table %>"><%= h subquery.table %></td>
19
+ <td title="<%= h subquery.select_type %>"><%= h subquery.select_type %></td>
20
+ <td title="<%= h subquery.query_type %>"><%= h subquery.query_type %></td>
21
+ <td title="<%= h subquery.extra %>"><%= h subquery.extra %></td>
22
+ <td title="<%= h subquery.possible_keys %>"><%= h subquery.possible_keys %></td>
23
+ <td title="<%= h subquery.key %>"><%= h subquery.key %></td>
24
+ <td title="<%= h subquery.key_len %>"><%= h subquery.key_len %></td>
25
+ <td title="<%= h subquery.ref %>"><%= h subquery.ref %></td>
26
+ <td title="<%= h subquery.rows %>"><%= h subquery.rows %></td>
27
+ </tr>
28
+ <% end %>
29
+ </tbody>
30
+ </table>
@@ -0,0 +1,68 @@
1
+ <% javascript_tag do %>
2
+ //Super lame show/hide functions so we don't need any 3rd party JS libs
3
+ function query_review_show(id) {
4
+ document.getElementById(id).style.display = "block";
5
+ }
6
+
7
+ function query_review_hide(id) {
8
+ document.getElementById(id).style.display = "none";
9
+ }
10
+ function query_review_toggle(id) {
11
+ if(document.getElementById(id).style.display == "none") {
12
+ document.getElementById(id).style.display = "block";
13
+ } else {
14
+ document.getElementById(id).style.display = "none";
15
+ }
16
+ }
17
+ function createCookie(name,value,days) {
18
+ if (days) {
19
+ var date = new Date();
20
+ date.setTime(date.getTime()+(days*24*60*60*1000));
21
+ var expires = "; expires="+date.toGMTString();
22
+ }
23
+ else var expires = "";
24
+ document.cookie = name+"="+value+expires+"; path=/";
25
+ }
26
+
27
+ function readCookie(name) {
28
+ var nameEQ = name + "=";
29
+ var ca = document.cookie.split(';');
30
+ for(var i=0;i < ca.length;i++) {
31
+ var c = ca[i];
32
+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
33
+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
34
+ }
35
+ return null;
36
+ }
37
+
38
+ function eraseCookie(name) {
39
+ createCookie(name,"",-1);
40
+ }
41
+
42
+ function ignore_list() {
43
+ var ignore_list = readCookie("query_review_ignore_list")
44
+ if (!ignore_list)
45
+ ignore_list = []
46
+ else
47
+ ignore_list = ignore_list.split(",")
48
+ return ignore_list
49
+ }
50
+
51
+ function add_ignore_hash(h){
52
+ var list = ignore_list();
53
+ list[list.length] = h
54
+ createCookie("query_review_ignore_list", list.join(","))
55
+ }
56
+
57
+ function remove_ignore_hash(h) {
58
+ var list = ignore_list();
59
+ var new_list = []
60
+ for(var i=0; i<list.length; i++)
61
+ {
62
+ if(list[i].toString() != h.toString()) {
63
+ new_list[new_list.length] = list[i]
64
+ }
65
+ }
66
+ createCookie("query_review_ignore_list", new_list.join(","))
67
+ }
68
+ <% end %>
@@ -0,0 +1,68 @@
1
+ <%= javascript_tag do %>
2
+ //Super lame show/hide functions so we don't need any 3rd party JS libs
3
+ function query_review_show(id) {
4
+ document.getElementById(id).style.display = "block";
5
+ }
6
+
7
+ function query_review_hide(id) {
8
+ document.getElementById(id).style.display = "none";
9
+ }
10
+ function query_review_toggle(id) {
11
+ if(document.getElementById(id).style.display == "none") {
12
+ document.getElementById(id).style.display = "block";
13
+ } else {
14
+ document.getElementById(id).style.display = "none";
15
+ }
16
+ }
17
+ function createCookie(name,value,days) {
18
+ if (days) {
19
+ var date = new Date();
20
+ date.setTime(date.getTime()+(days*24*60*60*1000));
21
+ var expires = "; expires="+date.toGMTString();
22
+ }
23
+ else var expires = "";
24
+ document.cookie = name+"="+value+expires+"; path=/";
25
+ }
26
+
27
+ function readCookie(name) {
28
+ var nameEQ = name + "=";
29
+ var ca = document.cookie.split(';');
30
+ for(var i=0;i < ca.length;i++) {
31
+ var c = ca[i];
32
+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
33
+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
34
+ }
35
+ return null;
36
+ }
37
+
38
+ function eraseCookie(name) {
39
+ createCookie(name,"",-1);
40
+ }
41
+
42
+ function ignore_list() {
43
+ var ignore_list = readCookie("query_review_ignore_list")
44
+ if (!ignore_list)
45
+ ignore_list = []
46
+ else
47
+ ignore_list = ignore_list.split(",")
48
+ return ignore_list
49
+ }
50
+
51
+ function add_ignore_hash(h){
52
+ var list = ignore_list();
53
+ list[list.length] = h
54
+ createCookie("query_review_ignore_list", list.join(","))
55
+ }
56
+
57
+ function remove_ignore_hash(h) {
58
+ var list = ignore_list();
59
+ var new_list = []
60
+ for(var i=0; i<list.length; i++)
61
+ {
62
+ if(list[i].toString() != h.toString()) {
63
+ new_list[new_list.length] = list[i]
64
+ }
65
+ }
66
+ createCookie("query_review_ignore_list", new_list.join(","))
67
+ }
68
+ <% end %>
@@ -0,0 +1,26 @@
1
+ <table>
2
+ <thead>
3
+ <tr>
4
+ <th>stage</th>
5
+ <th>duration</th>
6
+ <th>user cpu</th>
7
+ <th>context switches</th>
8
+ <th>block ops</th>
9
+ <th>messages</th>
10
+ <th>page faults</th>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ <% query.profile.each do |profile| %>
15
+ <tr>
16
+ <td title="<%= h profile.Status %>"><%= h profile.Status %></td>
17
+ <td title="<%= h profile.Duration %> seconds"><%= h("%.4f" % profile.Duration.to_f) %>s</td>
18
+ <td title="USER: <%= profile.CPU_user.to_f %>s SYSTEM: <%= profile.CPU_system.to_f %>s"><%= h("%.4f" % profile.CPU_user.to_f) %>s</td>
19
+ <td title="Voluntary: <%= h profile.Context_voluntary %> Involuntary: <%= h profile.Context_involuntary %>"><%= h(profile.Context_voluntary.to_i + profile.Context_involuntary.to_i) %></td>
20
+ <td title="Ops in: <%= h profile.Block_ops_in %> Ops out: <%= h profile.Block_ops_out %>"><%= h(profile.Block_ops_in.to_i + profile.Block_ops_out.to_i) %></td>
21
+ <td title="Sent: <%= h profile.Messages_sent %> Received: <%= h profile.Messages_received %>"><%= h(profile.Messages_sent.to_i + profile.Messages_received.to_i) %></td>
22
+ <td title="Major: <%= h profile.Page_faults_major %> Minor: <%= h profile.Page_faults_minor %>"><%= h profile.Page_faults_major %></td>
23
+ <tr>
24
+ <% end %>
25
+ </tbody>
26
+ </table>
@@ -0,0 +1,8 @@
1
+ <span id="query_plain_sql_<%= query_sql.id %>" style="display: none;">
2
+ <%= syntax_highlighted_sql(query_sql.sql) %>
3
+ <% if query_sql.respond_to?(:subqueries) && query_sql.subqueries.length > 1 %>
4
+ <% end %>
5
+ </span>
6
+ <span id="query_sanitized_sql_<%= query_sql.id %>">
7
+ <%= syntax_highlighted_sql(query_sql.sanitized_sql) if query_sql.sanitized_sql %>
8
+ </span>
@@ -0,0 +1,31 @@
1
+ <div class="trace" id="trace_<%= query_id %>_abridged">
2
+ <code>
3
+ <% query_trace[0..(QueryReviewer::CONFIGURATION["stack_trace_lines"] - 1)].compact.each do |c| %>
4
+ <% if c.match(/:.*:/) %>
5
+ <% file = h(c.slice(0..(c.index(":", c.index(":")+1)-1))) %>
6
+ <span><%= file.split("/")[0..-2].join("/") %>/</span><span class="bold"><%= file.split("/").last %></span>
7
+ <br/>
8
+ <span class="indent"><%= h(c.slice((c.index(":", c.index(":")+1)+1)..-1)) %></span><br/>
9
+ <% else %>
10
+ <span><%= h c %></span><br/>
11
+ <% end %>
12
+ <% end %>
13
+ </code>
14
+ <a href="#" onclick="query_review_toggle('trace_<%= query_id %>_abridged'); query_review_toggle('trace_<%= query_id %>_full')" title="show full trace">FULL</a>
15
+ </div>
16
+
17
+ <div class="trace" style="display: none; max-height: 300px; overflow: scroll" id="trace_<%= query_id %>_full">
18
+ <code>
19
+ <% full_trace.compact.each do |c| %>
20
+ <% if c.match(/:.*:/) %>
21
+ <% file = h(c.slice(0..(c.index(":", c.index(":")+1)-1))) %>
22
+ <span><%= file.split("/")[0..-2].join("/") %>/</span><span class="bold"><%= file.split("/").last %></span>
23
+ <br/>
24
+ <span class="indent"><%= h(c.slice((c.index(":", c.index(":")+1)+1)..-1)) %></span><br/>
25
+ <% else %>
26
+ <span><%= h c %></span><br/>
27
+ <% end %>
28
+ <% end %>
29
+ </code>
30
+ <a href="#" onclick="query_review_toggle('trace_<%= query_id %>_abridged'); query_review_toggle('trace_<%= query_id %>_full')" title="show short trace">SHORT</a>
31
+ </div>