rails-footnotes 3.7.1 → 3.7.2
Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc
CHANGED
@@ -32,7 +32,7 @@ For version greater then 3.7.0
|
|
32
32
|
If you want to add alternate logic to enable or disable footnotes,
|
33
33
|
add something like this to config/initializers/footnotes.rb:
|
34
34
|
|
35
|
-
if defined?(Footnotes)
|
35
|
+
if defined?(Footnotes) && Rails.env.development?
|
36
36
|
Footnotes.run! # first of all
|
37
37
|
|
38
38
|
# ... other init code
|
@@ -35,7 +35,7 @@ module Footnotes
|
|
35
35
|
if line =~ /Rendered (\S*) \(([\d\.]+)\S*?\)/
|
36
36
|
partial = $1
|
37
37
|
@controller.view_paths.each do |view_path|
|
38
|
-
path = File.join(view_path, "#{partial}*")
|
38
|
+
path = File.join(view_path.to_s, "#{partial}*")
|
39
39
|
files = Dir.glob(path)
|
40
40
|
for file in files
|
41
41
|
#TODO figure out what format got rendered if theres multiple
|
@@ -51,6 +51,6 @@ module Footnotes
|
|
51
51
|
partials.reverse
|
52
52
|
end
|
53
53
|
end
|
54
|
-
end
|
54
|
+
end
|
55
55
|
end
|
56
56
|
end
|
@@ -3,185 +3,113 @@ require "#{File.dirname(__FILE__)}/abstract_note"
|
|
3
3
|
module Footnotes
|
4
4
|
module Notes
|
5
5
|
class QueriesNote < AbstractNote
|
6
|
-
|
6
|
+
cattr_accessor :alert_db_time, :alert_sql_number, :orm, :instance_writter => false
|
7
|
+
|
8
|
+
@@alert_db_time = 16.0
|
7
9
|
@@alert_sql_number = 8
|
8
|
-
@@
|
9
|
-
@@
|
10
|
-
|
11
|
-
|
12
|
-
cattr_accessor :sql, :alert_db_time, :alert_sql_number, :alert_explain, :loaded, :sql_explain, :instance_writter => false
|
13
|
-
cattr_reader :include_when_new_relic_installed
|
14
|
-
|
15
|
-
def self.include_when_new_relic_installed=(include_me)
|
16
|
-
@@include_when_new_relic_installed = include_me
|
17
|
-
load if include_me
|
18
|
-
end
|
19
|
-
|
10
|
+
@@query_subscriber = nil
|
11
|
+
@@orm = [:active_record, :data_mapper]
|
12
|
+
|
20
13
|
def self.start!(controller)
|
21
|
-
|
14
|
+
self.query_subscriber.reset!
|
22
15
|
end
|
23
16
|
|
24
|
-
def self.
|
25
|
-
|
17
|
+
def self.query_subscriber
|
18
|
+
@@query_subscriber ||= Footnotes::Notes::QuerySubscriber.new(self.orm)
|
19
|
+
end
|
20
|
+
|
21
|
+
def events
|
22
|
+
self.class.query_subscriber.events
|
26
23
|
end
|
27
24
|
|
28
25
|
def title
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
queries = self.events.count
|
27
|
+
total_time = self.events.map(&:duration).sum / 1000.0
|
28
|
+
query_color = generate_red_color(self.events.count, alert_sql_number)
|
29
|
+
db_color = generate_red_color(total_time, alert_db_time)
|
32
30
|
|
33
31
|
<<-TITLE
|
34
|
-
|
35
|
-
|
32
|
+
<span style="background-color:#{query_color}">Queries (#{queries})</span>
|
33
|
+
<span style="background-color:#{db_color}">DB (#{"%.3f" % total_time}ms)</span>
|
36
34
|
TITLE
|
37
35
|
end
|
38
36
|
|
39
|
-
def stylesheet
|
40
|
-
<<-STYLESHEET
|
41
|
-
#queries_debug_info table td, #queries_debug_info table th{border:1px solid #A00; padding:0 3px; text-align:center;}
|
42
|
-
#queries_debug_info table thead, #queries_debug_info table tbody {color:#A00;}
|
43
|
-
#queries_debug_info p {background-color:#F3F3FF; border:1px solid #CCC; margin:12px; padding:4px 6px;}
|
44
|
-
#queries_debug_info a:hover {text-decoration:underline;}
|
45
|
-
STYLESHEET
|
46
|
-
end
|
47
|
-
|
48
37
|
def content
|
49
38
|
html = ''
|
50
|
-
|
51
|
-
@@sql.each_with_index do |item, i|
|
39
|
+
self.events.each_with_index do |event, index|
|
52
40
|
sql_links = []
|
53
|
-
sql_links << "<a href=\"javascript:Footnotes.toggle('
|
54
|
-
sql_links << "<a href=\"javascript:Footnotes.toggle('qtrace_#{i}')\" style=\"color:#00A;\">trace</a>" if item.trace
|
41
|
+
sql_links << "<a href=\"javascript:Footnotes.toggle('qtrace_#{index}')\" style=\"color:#00A;\">trace</a>"
|
55
42
|
|
56
43
|
html << <<-HTML
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
<p id="qtrace_#{i}" style="display:none;">#{parse_trace(item.trace) if item.trace}</p><br />
|
44
|
+
<b id="qtitle_#{index}">#{escape(event.type.to_s.upcase)}</b> (#{sql_links.join(' | ')})<br />
|
45
|
+
<span id="sql_#{index}">#{print_query(event.payload[:sql])}</span><br />
|
46
|
+
#{print_name_and_time(event.payload[:name], event.duration / 1000.0)}
|
47
|
+
<p id="qtrace_#{index}" style="display:none;">#{parse_trace(event.trace)}</p><br />
|
62
48
|
HTML
|
63
49
|
end
|
64
|
-
|
65
50
|
return html
|
66
51
|
end
|
67
|
-
|
68
|
-
def self.load
|
69
|
-
#only include when NewRelic is installed if configured to do so
|
70
|
-
if !loaded and included? and defined?(ActiveRecord)
|
71
|
-
ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, Footnotes::Extensions::AbstractAdapter
|
72
|
-
ActiveRecord::ConnectionAdapters.local_constants.each do |adapter|
|
73
|
-
next unless adapter =~ /.*[^Abstract]Adapter$/
|
74
|
-
next if adapter =~ /(SQLite|Salesforce)Adapter$/
|
75
|
-
eval("ActiveRecord::ConnectionAdapters::#{adapter}").send :include, Footnotes::Extensions::QueryAnalyzer
|
76
|
-
self.loaded = true
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
protected
|
82
|
-
def parse_explain(results)
|
83
|
-
table = []
|
84
|
-
table << results.fetch_fields.map(&:name)
|
85
|
-
results.each do |row|
|
86
|
-
table << row
|
87
|
-
end
|
88
|
-
table
|
89
|
-
end
|
90
|
-
|
91
|
-
def parse_trace(trace)
|
92
|
-
trace.map do |t|
|
93
|
-
s = t.split(':')
|
94
|
-
%[<a href="#{escape(Footnotes::Filter.prefix("#{Rails.root.to_s}/#{s[0]}", s[1].to_i, 1))}">#{escape(t)}</a><br />]
|
95
|
-
end.join
|
96
|
-
end
|
97
|
-
|
98
|
-
def print_name_and_time(name, time)
|
99
|
-
"<span style='background-color:#{generate_red_color(time, alert_ratio)}'>#{escape(name || 'SQL')} (#{sprintf('%f', time)}s)</span>"
|
100
|
-
end
|
101
|
-
|
102
|
-
def print_query(query)
|
103
|
-
escape(query.to_s.gsub(/(\s)+/, ' ').gsub('`', ''))
|
104
|
-
end
|
105
52
|
|
106
|
-
|
107
|
-
|
108
|
-
|
53
|
+
protected
|
54
|
+
def print_name_and_time(name, time)
|
55
|
+
"<span style='background-color:#{generate_red_color(time, alert_ratio)}'>#{escape(name || 'SQL')} (#{'%.3fms' % time})</span>"
|
56
|
+
end
|
109
57
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
c = 15 if c > 15
|
58
|
+
def print_query(query)
|
59
|
+
escape(query.to_s.gsub(/(\s)+/, ' ').gsub('`', ''))
|
60
|
+
end
|
114
61
|
|
115
|
-
|
116
|
-
|
117
|
-
|
62
|
+
def generate_red_color(value, alert)
|
63
|
+
c = ((value.to_f/alert).to_i - 1) * 16
|
64
|
+
c = 0 if c < 0; c = 15 if c > 15; c = (15-c).to_s(16)
|
65
|
+
"#ff#{c*4}"
|
66
|
+
end
|
118
67
|
|
119
|
-
|
120
|
-
|
121
|
-
|
68
|
+
def alert_ratio
|
69
|
+
alert_db_time / alert_sql_number
|
70
|
+
end
|
122
71
|
|
72
|
+
def parse_trace(trace)
|
73
|
+
trace.map do |t|
|
74
|
+
s = t.split(':')
|
75
|
+
%[<a href="#{escape(Footnotes::Filter.prefix("#{Rails.root.to_s}/#{s[0]}", s[1].to_i, 1))}">#{escape(t)}</a><br />]
|
76
|
+
end.join
|
77
|
+
end
|
123
78
|
end
|
124
|
-
end
|
125
79
|
|
126
|
-
|
127
|
-
|
128
|
-
|
80
|
+
class QuerySubscriberNotifactionEvent
|
81
|
+
attr_reader :event, :trace, :query
|
82
|
+
delegate :name, :payload, :duration, :time, :type, :to => :event
|
129
83
|
|
130
|
-
def initialize(
|
131
|
-
@
|
132
|
-
@name = name
|
133
|
-
@time = time
|
134
|
-
@query = query
|
135
|
-
@explain = explain
|
136
|
-
|
137
|
-
# Strip, select those ones from app and reject first two, because they
|
138
|
-
# are from the plugin
|
139
|
-
@trace = Kernel.caller.collect(&:strip).select{|i| i.gsub!(/^#{Rails.root}\//im, '') }[2..-1]
|
84
|
+
def initialize(event, ctrace)
|
85
|
+
@event, @ctrace, @query = event, ctrace, event.payload[:sql]
|
140
86
|
end
|
141
|
-
end
|
142
87
|
|
143
|
-
|
144
|
-
|
145
|
-
base.class_eval do
|
146
|
-
alias_method_chain :execute, :analyzer
|
147
|
-
end
|
88
|
+
def trace
|
89
|
+
@trace ||= @ctrace.collect(&:strip).select{|i| i.gsub!(/^#{Rails.root.to_s}\//, '') } || []
|
148
90
|
end
|
149
91
|
|
150
|
-
def
|
151
|
-
|
152
|
-
|
92
|
+
def type
|
93
|
+
return @type if @type
|
94
|
+
@type = self.query.match(/^(select|insert|update|delete|alter)\b/i) || 'Unknown'
|
95
|
+
end
|
96
|
+
end
|
153
97
|
|
154
|
-
|
155
|
-
|
156
|
-
explain = nil
|
98
|
+
class QuerySubscriber < ActiveSupport::LogSubscriber
|
99
|
+
attr_accessor :events
|
157
100
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
end
|
163
|
-
Footnotes::Notes::QueriesNote.sql << Footnotes::Extensions::Sql.new(type, name, time, query, explain)
|
164
|
-
end
|
101
|
+
def initialize(orm)
|
102
|
+
@events = []
|
103
|
+
orm.each {|adapter| ActiveSupport::LogSubscriber.attach_to adapter, self}
|
104
|
+
end
|
165
105
|
|
166
|
-
|
106
|
+
def reset!
|
107
|
+
self.events.clear
|
167
108
|
end
|
168
|
-
end
|
169
109
|
|
170
|
-
|
171
|
-
|
172
|
-
result = nil
|
173
|
-
if @logger
|
174
|
-
@logger.silence do
|
175
|
-
result = yield
|
176
|
-
end
|
177
|
-
else
|
178
|
-
result = yield
|
179
|
-
end
|
180
|
-
result
|
110
|
+
def sql(event)
|
111
|
+
@events << QuerySubscriberNotifactionEvent.new(event.dup, caller)
|
181
112
|
end
|
182
113
|
end
|
183
|
-
|
184
114
|
end
|
185
115
|
end
|
186
|
-
|
187
|
-
Footnotes::Notes::QueriesNote.load
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: rails-footnotes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 3.7.
|
5
|
+
version: 3.7.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Keenan Brock
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-05-02 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|