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) & Rails.env.development?
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
- @@alert_db_time = 0.16
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
- @@sql = []
9
- @@include_when_new_relic_installed = false
10
- @@loaded = false
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
- @@sql = []
14
+ self.query_subscriber.reset!
22
15
  end
23
16
 
24
- def self.to_sym
25
- :queries
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
- db_time = @@sql.inject(0){|sum, item| sum += item.time }
30
- query_color = generate_red_color(@@sql.length, alert_sql_number)
31
- db_color = generate_red_color(db_time, alert_db_time)
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
- <span style="background-color:#{query_color}">Queries (#{@@sql.length})</span>
35
- <span style="background-color:#{db_color}">DB (#{"%.6f" % db_time}s)</span>
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('qtable_#{i}')\" style=\"color:#A00;\">explain</a>" if item.explain
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
- <b id="qtitle_#{i}">#{escape(item.type.to_s.upcase)}</b> (#{sql_links.join(' | ')})<br />
58
- #{print_name_and_time(item.name, item.time)}<br />
59
- <span id="explain_#{i}">#{print_query(item.query)}</span><br />
60
- #{print_explain(i, item.explain) if item.explain}
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)}&nbsp;
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
- def print_explain(i, explain)
107
- mount_table(parse_explain(explain), :id => "qtable_#{i}", :style => 'margin:10px;display:none;', :summary => "Debug information for #{title}")
108
- end
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
- def generate_red_color(value, alert)
111
- c = ((value.to_f/alert).to_i - 1) * 16
112
- c = 0 if c < 0
113
- c = 15 if c > 15
58
+ def print_query(query)
59
+ escape(query.to_s.gsub(/(\s)+/, ' ').gsub('`', ''))
60
+ end
114
61
 
115
- c = (15-c).to_s(16)
116
- "#ff#{c*4}"
117
- end
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
- def alert_ratio
120
- alert_db_time / alert_sql_number
121
- end
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
- module Extensions
127
- class Sql
128
- attr_accessor :type, :name, :time, :query, :explain, :trace
80
+ class QuerySubscriberNotifactionEvent
81
+ attr_reader :event, :trace, :query
82
+ delegate :name, :payload, :duration, :time, :type, :to => :event
129
83
 
130
- def initialize(type, name, time, query, explain)
131
- @type = type
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
- module QueryAnalyzer
144
- def self.included(base)
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 execute_with_analyzer(query, name = nil)
151
- query_results = nil
152
- time = Benchmark.realtime { query_results = execute_without_analyzer(query, name) }
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
- if query =~ /^(select|create|update|delete)\b/i
155
- type = $&.downcase.to_sym
156
- explain = nil
98
+ class QuerySubscriber < ActiveSupport::LogSubscriber
99
+ attr_accessor :events
157
100
 
158
- if adapter_name == 'MySQL' && type == :select && Footnotes::Notes::QueriesNote.sql_explain
159
- log_silence do
160
- explain = execute_without_analyzer("EXPLAIN #{query}", name)
161
- end
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
- query_results
106
+ def reset!
107
+ self.events.clear
167
108
  end
168
- end
169
109
 
170
- module AbstractAdapter
171
- def log_silence
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
@@ -1,3 +1,3 @@
1
1
  module Footnotes
2
- VERSION = "3.7.1"
2
+ VERSION = "3.7.2"
3
3
  end
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.1
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-04-25 00:00:00 Z
13
+ date: 2011-05-02 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails