sql_tracer 0.0.6 → 0.0.7
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.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/sql_tracer/application.css +5 -0
- data/app/assets/stylesheets/sql_tracer/style.css +191 -0
- data/app/controllers/sql_tracer/sql_tracer_controller.rb +15 -0
- data/app/views/sql_tracer/sql_tracer/index.html.erb +141 -0
- data/config/routes.rb +4 -0
- data/lib/sql_tracer/engine.rb +4 -0
- data/lib/sql_tracer/formatter.rb +80 -0
- data/lib/sql_tracer/helper.rb +29 -0
- data/lib/sql_tracer/request_logger.rb +13 -0
- data/lib/sql_tracer/sql_logger.rb +27 -0
- data/lib/sql_tracer/sql_stack.rb +28 -0
- data/lib/sql_tracer/version.rb +3 -0
- data/lib/sql_tracer.rb +26 -0
- metadata +15 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 982974c81f2a39e7c1cb812423788ed733434750
|
4
|
+
data.tar.gz: 14a302d2095e86805fb12e6f164f553293c89ed5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b72ef9736956a00c8561dc64246079bcf79805ef32a24ccd4f4e0efc7baa3244d8293ad69fd24c312ca74885deb83705a00a5f81fd655db9d71b3a4791b6b72d
|
7
|
+
data.tar.gz: bfa565ccb801c5fa052277ec22f8ddfd2eb3c42fa74542a1a1ffe9620178b030508d4a6d2595743e7350a78e059bb59105ab7ebfbf14a1aaa95dcea9fb60703a
|
@@ -0,0 +1,191 @@
|
|
1
|
+
body {
|
2
|
+
margin: 0;
|
3
|
+
font-family: 'Roboto';
|
4
|
+
font-size: 14px;
|
5
|
+
background: #ffffff;
|
6
|
+
}
|
7
|
+
|
8
|
+
h3 {
|
9
|
+
color: #fff;
|
10
|
+
font-size: 24px;
|
11
|
+
text-align: center;
|
12
|
+
margin-top: 30px;
|
13
|
+
padding-bottom: 30px;
|
14
|
+
border-bottom: 1px solid #eee;
|
15
|
+
margin-bottom: 30px;
|
16
|
+
font-weight: 300;
|
17
|
+
}
|
18
|
+
|
19
|
+
/*.container {*/
|
20
|
+
/*max-width: 970px;*/
|
21
|
+
/*}*/
|
22
|
+
|
23
|
+
div[class*='col-'] {
|
24
|
+
padding: 0 30px;
|
25
|
+
}
|
26
|
+
|
27
|
+
.wrap {
|
28
|
+
box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
|
29
|
+
border-radius: 4px;
|
30
|
+
}
|
31
|
+
|
32
|
+
a:focus,
|
33
|
+
a:hover,
|
34
|
+
a:active {
|
35
|
+
outline: 0;
|
36
|
+
text-decoration: none;
|
37
|
+
}
|
38
|
+
|
39
|
+
.container {
|
40
|
+
width: 90%;
|
41
|
+
}
|
42
|
+
.panel {
|
43
|
+
border-width: 0 0 1px 0;
|
44
|
+
border-style: solid;
|
45
|
+
border-color: #fff;
|
46
|
+
background: none;
|
47
|
+
box-shadow: none;
|
48
|
+
}
|
49
|
+
|
50
|
+
.panel:last-child {
|
51
|
+
border-bottom: none;
|
52
|
+
}
|
53
|
+
|
54
|
+
.panel-group > .panel:first-child .panel-heading {
|
55
|
+
border-radius: 4px 4px 0 0;
|
56
|
+
}
|
57
|
+
|
58
|
+
.panel-group .panel {
|
59
|
+
border-radius: 0;
|
60
|
+
}
|
61
|
+
|
62
|
+
.panel-group .panel + .panel {
|
63
|
+
margin-top: 0;
|
64
|
+
}
|
65
|
+
|
66
|
+
.panel-heading {
|
67
|
+
background-color: #18504a;
|
68
|
+
border-radius: 0;
|
69
|
+
border: none;
|
70
|
+
color: #fff;
|
71
|
+
padding: 0;
|
72
|
+
}
|
73
|
+
|
74
|
+
.panel-title a {
|
75
|
+
display: block;
|
76
|
+
color: #fff;
|
77
|
+
padding: 15px;
|
78
|
+
position: relative;
|
79
|
+
font-size: 16px;
|
80
|
+
font-weight: 400;
|
81
|
+
}
|
82
|
+
|
83
|
+
.panel-body {
|
84
|
+
background: rgba(153,153,153,0.29);
|
85
|
+
}
|
86
|
+
|
87
|
+
.panel:last-child .panel-body {
|
88
|
+
border-radius: 0 0 4px 4px;
|
89
|
+
}
|
90
|
+
|
91
|
+
.panel:last-child .panel-heading {
|
92
|
+
border-radius: 0 0 4px 4px;
|
93
|
+
-webkit-transition: border-radius 0.3s linear 0.2s;
|
94
|
+
transition: border-radius 0.3s linear 0.2s;
|
95
|
+
}
|
96
|
+
|
97
|
+
.panel:last-child .panel-heading.active {
|
98
|
+
border-radius: 0;
|
99
|
+
-webkit-transition: border-radius linear 0s;
|
100
|
+
transition: border-radius linear 0s;
|
101
|
+
}
|
102
|
+
|
103
|
+
/* #bs-collapse icon scale option */
|
104
|
+
|
105
|
+
.panel-heading a:before {
|
106
|
+
content: '\e146';
|
107
|
+
position: absolute;
|
108
|
+
font-family: 'Material Icons';
|
109
|
+
right: 5px;
|
110
|
+
top: 10px;
|
111
|
+
font-size: 24px;
|
112
|
+
-webkit-transition: all 0.5s;
|
113
|
+
transition: all 0.5s;
|
114
|
+
-webkit-transform: scale(1);
|
115
|
+
transform: scale(1);
|
116
|
+
}
|
117
|
+
|
118
|
+
.panel-heading.active a:before {
|
119
|
+
content: ' ';
|
120
|
+
-webkit-transition: all 0.5s;
|
121
|
+
transition: all 0.5s;
|
122
|
+
-webkit-transform: scale(0);
|
123
|
+
transform: scale(0);
|
124
|
+
}
|
125
|
+
|
126
|
+
/*.panel-heading a:after {*/
|
127
|
+
/*content: ' ';*/
|
128
|
+
/*font-size: 24px;*/
|
129
|
+
/*position: absolute;*/
|
130
|
+
/*font-family: 'Material Icons';*/
|
131
|
+
/*right: 5px;*/
|
132
|
+
/*top: 10px;*/
|
133
|
+
/*-webkit-transform: scale(0);*/
|
134
|
+
/*transform: scale(0);*/
|
135
|
+
/*-webkit-transition: all 0.5s;*/
|
136
|
+
/*transition: all 0.5s;*/
|
137
|
+
/*}*/
|
138
|
+
|
139
|
+
/*.panel-heading.active a:after {*/
|
140
|
+
/*content: '\e909';*/
|
141
|
+
/*-webkit-transform: scale(1);*/
|
142
|
+
/*transform: scale(1);*/
|
143
|
+
/*-webkit-transition: all 0.5s;*/
|
144
|
+
/*transition: all 0.5s;*/
|
145
|
+
/*}*/
|
146
|
+
|
147
|
+
/* #accordion rotate icon option */
|
148
|
+
|
149
|
+
.panel-heading a:before {
|
150
|
+
content: '\e316';
|
151
|
+
font-size: 24px;
|
152
|
+
position: absolute;
|
153
|
+
font-family: 'Material Icons';
|
154
|
+
right: 5px;
|
155
|
+
top: 10px;
|
156
|
+
-webkit-transform: rotate(180deg);
|
157
|
+
transform: rotate(180deg);
|
158
|
+
-webkit-transition: all 0.5s;
|
159
|
+
transition: all 0.5s;
|
160
|
+
}
|
161
|
+
|
162
|
+
.panel-heading.active a:before {
|
163
|
+
-webkit-transform: rotate(0deg);
|
164
|
+
transform: rotate(0deg);
|
165
|
+
-webkit-transition: all 0.5s;
|
166
|
+
transition: all 0.5s;
|
167
|
+
}
|
168
|
+
|
169
|
+
.sql_template {
|
170
|
+
padding-left: 20px;
|
171
|
+
background-color: #009688;
|
172
|
+
line-break: auto;
|
173
|
+
word-break: break-all;
|
174
|
+
}
|
175
|
+
|
176
|
+
.stack_info {
|
177
|
+
word-break: break-all;
|
178
|
+
/*padding-left: 40px;*/
|
179
|
+
}
|
180
|
+
|
181
|
+
.stack_info div {
|
182
|
+
padding-left: 50px;
|
183
|
+
/*padding-left: 40px;*/
|
184
|
+
}
|
185
|
+
|
186
|
+
#url_template,
|
187
|
+
#sqls_template,
|
188
|
+
#sql_template,
|
189
|
+
#stack_info {
|
190
|
+
display: none;
|
191
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SqlTracer
|
2
|
+
class SqlTracerController < ActionController::Base
|
3
|
+
skip_filter :build_navigations
|
4
|
+
skip_after_filter :persist_reqeust_logger
|
5
|
+
|
6
|
+
def index
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_latest_stack_info
|
10
|
+
ret = SqlTracer::SqlStack.to_json
|
11
|
+
SqlTracer::SqlStack.clear
|
12
|
+
render :json => ret
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="zh">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
+
<title>Sql Tracer</title>
|
8
|
+
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700' rel='stylesheet' type='text/css'>
|
9
|
+
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
10
|
+
<link rel="stylesheet" type="text/css" href="http://www.jq22.com/jquery/bootstrap-3.3.4.css">
|
11
|
+
<%= stylesheet_link_tag 'sql_tracer/application' %>
|
12
|
+
</head>
|
13
|
+
<body>
|
14
|
+
|
15
|
+
<section class="jq22-container">
|
16
|
+
<div class="container">
|
17
|
+
|
18
|
+
<div class="row-fluid">
|
19
|
+
<div class="span12">
|
20
|
+
<div class="hero-unit">
|
21
|
+
<h1>
|
22
|
+
Sql Tracer
|
23
|
+
</h1>
|
24
|
+
<p>
|
25
|
+
It helps you figure out what sqls are executed and trace method call stack, you can take a look at
|
26
|
+
<a class="btn btn-primary btn-xs" target="_blank" href="https://git.dev.fwmrm.net/qzhang/sql_tracer"> READ
|
27
|
+
ME</a>
|
28
|
+
to acquire more information.
|
29
|
+
</p>
|
30
|
+
<p>
|
31
|
+
If you have any questions or improvement, please open a issue.
|
32
|
+
<a class="btn btn-primary btn-xs" target="_blank" href="https://git.dev.fwmrm.net/qzhang/sql_tracer/issues/new">
|
33
|
+
New Issue
|
34
|
+
</a>
|
35
|
+
</p>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
<!-- end of #bs-collapse -->
|
40
|
+
</div>
|
41
|
+
|
42
|
+
|
43
|
+
<div id="url_template" class="url_template">
|
44
|
+
<div class="panel-heading">
|
45
|
+
<h4 class="panel-title">
|
46
|
+
<a data-toggle="collapse" data-parent="#" href="#one">
|
47
|
+
</a>
|
48
|
+
</h4>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
|
52
|
+
<div id="sql_template" class="panel-heading sql_template">
|
53
|
+
<h4 class="panel-title">
|
54
|
+
<a data-toggle="collapse" data-parent="#" href="#one-2" class="sql">
|
55
|
+
</a>
|
56
|
+
</h4>
|
57
|
+
</div>
|
58
|
+
<div id="stack_info" class="panel-collapse collapse stack_info" style="display: none">
|
59
|
+
<div class="panel-body ruby">
|
60
|
+
</div>
|
61
|
+
</div>
|
62
|
+
|
63
|
+
<div id="sqls_template" style="display: none"></div>
|
64
|
+
<!-- end of container -->
|
65
|
+
</section>
|
66
|
+
|
67
|
+
<script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>
|
68
|
+
<script src="http://www.jq22.com/jquery/bootstrap-3.3.4.js"></script>
|
69
|
+
<script type="text/javascript">
|
70
|
+
$(document).ready(function() {
|
71
|
+
refresh();
|
72
|
+
});
|
73
|
+
|
74
|
+
function refresh() {
|
75
|
+
$.ajax({
|
76
|
+
url: "/sql_tracer/get_latest_stack_info",
|
77
|
+
success: function(result, status) {
|
78
|
+
if (result) {
|
79
|
+
$.each(result, function(index, requestInfo) {
|
80
|
+
appendRequestInfo(requestInfo);
|
81
|
+
});
|
82
|
+
}
|
83
|
+
},
|
84
|
+
complete: function() {
|
85
|
+
setTimeout("refresh()", 3000)
|
86
|
+
}
|
87
|
+
});
|
88
|
+
}
|
89
|
+
|
90
|
+
function appendRequestInfo(requestInfo) {
|
91
|
+
var url = requestInfo.url;
|
92
|
+
var sqls = requestInfo.sqls || [];
|
93
|
+
var $url_template = $("#url_template").clone();
|
94
|
+
$url_template.attr("id", "");
|
95
|
+
$url_template.find("a").attr("href", "#");
|
96
|
+
$url_template.find("a").html(url);
|
97
|
+
$url_template.css("display", "block");
|
98
|
+
|
99
|
+
var $sqls_template = $("#sqls_template").clone();
|
100
|
+
$sqls_template.attr("id", "");
|
101
|
+
|
102
|
+
if (sqls && sqls.length > 0) {
|
103
|
+
$.each(sqls, function(index, sql_info) {
|
104
|
+
var $stack_info = $("#stack_info").clone();
|
105
|
+
$stack_info.attr("id", "");
|
106
|
+
$stack_info.find("div").html(sql_info.stack.join("<br\/>"));
|
107
|
+
|
108
|
+
var $sql_template = $("#sql_template").clone();
|
109
|
+
$sql_template.attr("id", "");
|
110
|
+
$sql_template.find("a").attr("href", "#");
|
111
|
+
$sql_template.find("a").html(sql_info.sql);
|
112
|
+
$sql_template.find("a").click(function() {
|
113
|
+
if ($stack_info.is(":visible")) {
|
114
|
+
$sql_template.removeClass('active');
|
115
|
+
} else {
|
116
|
+
$sql_template.addClass('active');
|
117
|
+
}
|
118
|
+
$stack_info.slideToggle();
|
119
|
+
});
|
120
|
+
$sqls_template.append($sql_template);
|
121
|
+
$sqls_template.append($stack_info);
|
122
|
+
});
|
123
|
+
} else {
|
124
|
+
$sqls_template.html('No effective sqls are detected.')
|
125
|
+
}
|
126
|
+
|
127
|
+
$url_template.find("a").click(function() {
|
128
|
+
if ($sqls_template.is(":visible")) {
|
129
|
+
$url_template.find(".panel-heading:first").removeClass('active');
|
130
|
+
} else {
|
131
|
+
$url_template.find(".panel-heading:first").addClass('active');
|
132
|
+
}
|
133
|
+
$sqls_template.slideToggle();
|
134
|
+
});
|
135
|
+
$url_template.append($sqls_template);
|
136
|
+
$(".container").append($url_template);
|
137
|
+
}
|
138
|
+
|
139
|
+
</script>
|
140
|
+
</body>
|
141
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'anbt-sql-formatter/formatter'
|
2
|
+
|
3
|
+
module SqlTracer
|
4
|
+
class Formatter
|
5
|
+
HEADER_PROMPT= '='*10 << '>'
|
6
|
+
FOOTER_PROMPT= '<' << '='*10
|
7
|
+
FORMATTER_CONFIG_TIP =
|
8
|
+
<<-TIP
|
9
|
+
You can add config to ui_config.yml to acquire advanced features
|
10
|
+
SQL_TRACER_FORMAT_SQL_ENABLED: true # show formatted and colored sql, default false
|
11
|
+
SQL_TRACER_FORMAT_STACK_ENABLED: true # show colored stack, default fasle
|
12
|
+
SQL_TRACER_SKIP_LIB: false # show all paths including the files in ruby gems, default true
|
13
|
+
TIP
|
14
|
+
|
15
|
+
def self.start_print
|
16
|
+
puts HEADER_PROMPT
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.end_print
|
20
|
+
puts FOOTER_PROMPT
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.print_tips
|
24
|
+
puts 'SqlTracer is watching and will capture backtrace when sql is executed.'
|
25
|
+
puts FORMATTER_CONFIG_TIP
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.print_sql(sql)
|
29
|
+
puts 'SQL:'
|
30
|
+
return sql if sql.blank?
|
31
|
+
formatted_sql = ' ' << (Helper.format_sql_enabled? ? colorize(sql_formatter.format(sql.squeeze(' ')), 32) : sql)
|
32
|
+
puts formatted_sql
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.print_backtrace(backtrace)
|
36
|
+
puts Helper.should_skip_lib? ? 'Backtrace: note that paths in ruby libs have been hidden' : 'Backtrace:'
|
37
|
+
backtrace.each do |line|
|
38
|
+
line = format_line(line) if Helper.format_stack_enabled?
|
39
|
+
(puts ' ' << line) if line.present?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.print_all(sql, backtrace)
|
44
|
+
Formatter.start_print
|
45
|
+
Formatter.print_sql(sql)
|
46
|
+
Formatter.print_backtrace(backtrace)
|
47
|
+
Formatter.end_print
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.remove_lib_path(backtrace)
|
51
|
+
backtrace.map do |path|
|
52
|
+
next if Helper.should_skip_lib? && path.include?('/.rvm/gems/')
|
53
|
+
path
|
54
|
+
end.compact
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.sql_formatter
|
58
|
+
return @formatter if @formatter
|
59
|
+
rule = AnbtSql::Rule.new
|
60
|
+
rule.keyword = AnbtSql::Rule::KEYWORD_UPPER_CASE
|
61
|
+
rule.function_names += %w(count sum)
|
62
|
+
rule.indent_string = ' '
|
63
|
+
@formatter = AnbtSql::Formatter.new(rule)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.format_line(line)
|
67
|
+
parts = line.match(/^(?<file>.+):(?<line>\d+):in `(?<code>.*)'$/)
|
68
|
+
if parts
|
69
|
+
"#{colorize(parts[:file], 32)}:#{colorize(parts[:line], 36)}:#{colorize(parts[:code], 31)}"
|
70
|
+
else
|
71
|
+
"#{colorize(line, 32)}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.colorize(text, color_code)
|
76
|
+
"\e[#{color_code}m#{text}\e[0m"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'anbt-sql-formatter/formatter'
|
2
|
+
|
3
|
+
module SqlTracer
|
4
|
+
class Helper
|
5
|
+
class << self
|
6
|
+
def format_sql_enabled?
|
7
|
+
@format_sql_enabled ||= (UIConfig.get(:SQL_TRACER_FORMAT_SQL_ENABLED) || false)
|
8
|
+
end
|
9
|
+
|
10
|
+
def format_stack_enabled?
|
11
|
+
@format_stack_enabled ||= (UIConfig.get(:SQL_TRACER_FORMAT_STACK_ENABLED) || false)
|
12
|
+
end
|
13
|
+
|
14
|
+
def should_skip_lib?
|
15
|
+
@should_skip_lib ||= (UIConfig.get(:SQL_TRACER_SKIP_LIB) || true)
|
16
|
+
end
|
17
|
+
|
18
|
+
def should_skip_by_keywords?(sql)
|
19
|
+
@keywords ||= (UIConfig.get(:SQL_TRACER_SQL_FILTER) || [])
|
20
|
+
return false if @keywords.blank?
|
21
|
+
@keywords.any? { |keyword| sql.include?(keyword) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def disable_console_output?
|
25
|
+
@console_output_disabled ||= (UIConfig.get(:SQL_TRACER_CONSOLE_OUTPUT_DISABLED) || false)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SqlTracer
|
2
|
+
module RequestLogger
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
after_filter :persist_reqeust_logger
|
6
|
+
|
7
|
+
def persist_reqeust_logger
|
8
|
+
SqlTracer::SqlStack.url = "#{request.method} #{request.path}"
|
9
|
+
SqlTracer::SqlStack.push
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'anbt-sql-formatter/formatter'
|
2
|
+
|
3
|
+
module SqlTracer
|
4
|
+
module SqlLogger
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
included do
|
7
|
+
alias_method :execute_without_sql_tracer, :execute
|
8
|
+
|
9
|
+
def execute(*args)
|
10
|
+
begin
|
11
|
+
sql = args.first
|
12
|
+
|
13
|
+
if sql =~ /^\s*(insert|update|delete)\s/i && !Helper.should_skip_by_keywords?(sql)
|
14
|
+
backtrace = Thread.current.backtrace
|
15
|
+
backtrace = Formatter.remove_lib_path(backtrace) if Helper.should_skip_lib?
|
16
|
+
Formatter.print_all(sql, backtrace) unless Helper.disable_console_output?
|
17
|
+
SqlTracer::SqlStack.sql_stack << { :sql => sql, :stack => backtrace }
|
18
|
+
end
|
19
|
+
rescue => e
|
20
|
+
Rails.logger.error "Failed to log sql in SqlTracer. Error: #{e.message}"
|
21
|
+
Rails.logger.error e.backtrace.join("\n")
|
22
|
+
end
|
23
|
+
execute_without_sql_tracer(*args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module SqlTracer
|
4
|
+
class SqlStack
|
5
|
+
@url = ''
|
6
|
+
@sql_stack = []
|
7
|
+
@sql_stacks = []
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_accessor :url, :sql_stack, :sql_stacks
|
11
|
+
|
12
|
+
def clear
|
13
|
+
@sql_stacks = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def push
|
17
|
+
@sql_stacks << { :url => "[#{Time.now.strftime('%H:%M:%S')}] #{@url}", :sqls => @sql_stack }
|
18
|
+
@sql_stack = []
|
19
|
+
@url = ''
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json
|
23
|
+
@sql_stacks.to_json
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/sql_tracer.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'sql_tracer/engine'
|
2
|
+
|
3
|
+
module SqlTracer
|
4
|
+
autoload :SqlLogger, 'sql_tracer/sql_logger'
|
5
|
+
autoload :Helper, 'sql_tracer/helper'
|
6
|
+
autoload :Formatter, 'sql_tracer/formatter'
|
7
|
+
autoload :RequestLogger, 'sql_tracer/request_logger'
|
8
|
+
autoload :SqlStack, 'sql_tracer/sql_stack'
|
9
|
+
end
|
10
|
+
|
11
|
+
# why does not work when wrapped in block ActiveSupport.on_load(:active_record) do
|
12
|
+
begin
|
13
|
+
require 'active_record/connection_adapters/mysql2_adapter'
|
14
|
+
ActiveRecord::ConnectionAdapters::Mysql2Adapter.send(:include, SqlTracer::SqlLogger)
|
15
|
+
SqlTracer::Formatter.print_tips
|
16
|
+
|
17
|
+
ActiveSupport.on_load(:action_controller) do
|
18
|
+
ActionController::Base.send(:include, SqlTracer::RequestLogger)
|
19
|
+
end
|
20
|
+
rescue LoadError, NameError => e
|
21
|
+
Rails.logger.error('Failed to injuect SqlTracer to ActiveRecord due to :' + e.message)
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sql_tracer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- xiaoye
|
@@ -30,7 +30,20 @@ email:
|
|
30
30
|
executables: []
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
|
-
files:
|
33
|
+
files:
|
34
|
+
- app/assets/stylesheets/sql_tracer/application.css
|
35
|
+
- app/assets/stylesheets/sql_tracer/style.css
|
36
|
+
- app/controllers/sql_tracer/sql_tracer_controller.rb
|
37
|
+
- app/views/sql_tracer/sql_tracer/index.html.erb
|
38
|
+
- config/routes.rb
|
39
|
+
- lib/sql_tracer.rb
|
40
|
+
- lib/sql_tracer/engine.rb
|
41
|
+
- lib/sql_tracer/formatter.rb
|
42
|
+
- lib/sql_tracer/helper.rb
|
43
|
+
- lib/sql_tracer/request_logger.rb
|
44
|
+
- lib/sql_tracer/sql_logger.rb
|
45
|
+
- lib/sql_tracer/sql_stack.rb
|
46
|
+
- lib/sql_tracer/version.rb
|
34
47
|
homepage: https://git.dev.fwmrm.net/qzhang/sql_tracer
|
35
48
|
licenses: []
|
36
49
|
metadata: {}
|