lookout-query_reviewer 0.1.5

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