rails-footnotes 3.7.1 → 3.7.2
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.
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
|