remnant 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/remnant/base.rb CHANGED
@@ -1,5 +1,16 @@
1
1
  class Remnant
2
2
  module ClassMethods
3
+ def color(default = false, heading = false)
4
+ return "\033[0m" if default
5
+ return "\033[0;01;33m" if heading
6
+
7
+ @current_color ||= "\033[0;01;36m"
8
+ @next_color ||= "\033[0;01;35m"
9
+
10
+ @current_color, @next_color = @next_color, @current_color
11
+ @current_color
12
+ end
13
+
3
14
  def configure(&block)
4
15
  configuration.instance_eval(&block)
5
16
  end
@@ -37,7 +48,7 @@ class Remnant
37
48
  end
38
49
  else
39
50
  # always log in development mode
40
- Rails.logger.info "--------------Remnants Discovered--------------"
51
+ Rails.logger.info "#{color(false, true)}--------------Remnants Discovered--------------#{color(true)}"
41
52
 
42
53
  Remnant::Discover.results.map do |remnant_key, ms|
43
54
  key = [
@@ -45,10 +56,30 @@ class Remnant
45
56
  remnant_key
46
57
  ].compact.join('.')
47
58
 
48
- Rails.logger.info "#{ms.to_i}ms\t#{key}"
59
+ Rails.logger.info "#{Remnant.color}#{ms.to_i}ms#{Remnant.color(true)}\t#{key}"
60
+ end
61
+
62
+ if Remnant::Template.enabled?
63
+ Rails.logger.info ""
64
+ Rails.logger.info "#{color(false, true)}----- Templates -----#{color(true)}"
65
+ Remnant::Template.trace.root.children.map do |rendering|
66
+ Remnant::Template.trace.log(Rails.logger, rendering, 0)
67
+ end
68
+ end
69
+
70
+ if Remnant::Database.enabled?
71
+ Rails.logger.info ""
72
+ Rails.logger.info("#{color(false, true)}---- Database (%.2fms) -----#{color(true)}" % (Remnant::Database.queries.map(&:time).sum * 1000))
73
+ if Remnant::Database.suppress?
74
+ Rails.logger.info "queries suppressed in development mode"
75
+ else
76
+ Remnant::Database.queries.map do |query|
77
+ Rails.logger.info("#{color}%.2fms#{color(true)}\t#{query.sql}" % (query.time * 1000))
78
+ end
79
+ end
49
80
  end
50
81
 
51
- Rails.logger.info "-----------------------------------------------"
82
+ Rails.logger.info "#{color(false, true)}-----------------------------------------------#{color(true)}"
52
83
  end
53
84
 
54
85
  # run hook if given
@@ -56,6 +87,8 @@ class Remnant
56
87
  Remnant.configuration.custom_hook.call(Remnant::Discover.results)
57
88
  end
58
89
 
90
+ Remnant::Database.reset
91
+ Remnant::Template.reset
59
92
  Remnant::Discover.results.clear
60
93
  end
61
94
  end
@@ -0,0 +1,19 @@
1
+ class Remnant
2
+ class Database
3
+ class Query
4
+ attr_reader :sql
5
+ attr_reader :time
6
+ attr_reader :backtrace
7
+
8
+ def initialize(sql, time, backtrace = [])
9
+ @sql = sql
10
+ @time = time
11
+ @backtrace = backtrace
12
+ end
13
+
14
+ def inspectable?
15
+ sql.strip =~ /^SELECT /i
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ class Remnant
2
+ class Database
3
+ module ClassMethods
4
+ def disable!
5
+ @enabled = false
6
+ end
7
+
8
+ def enable!
9
+ @enabled = true
10
+ end
11
+
12
+ def enabled?
13
+ @enabled
14
+ end
15
+
16
+ def unsuppress!
17
+ @suppress = false
18
+ end
19
+
20
+ def suppress?
21
+ @suppress || true
22
+ end
23
+
24
+ def record(sql, backtrace = [], &block)
25
+ return block.call unless Remnant::Database.enabled?
26
+
27
+ start_time = Time.now
28
+ result = block.call
29
+ queries << Remnant::Database::Query.new(sql, Time.now - start_time, backtrace)
30
+
31
+ return result
32
+ end
33
+
34
+ def reset
35
+ @suppress = true
36
+ Thread.current['remnant.database.queries'] = []
37
+ end
38
+
39
+ def queries
40
+ Thread.current['remnant.database.queries'] ||= []
41
+ end
42
+
43
+ def total_time
44
+ @total_time ||= (queries.inject(0) {|memo, query| memo + query.time}) * 1000
45
+ end
46
+ end
47
+ extend ClassMethods
48
+ end
49
+ end
@@ -3,7 +3,10 @@ class Remnant
3
3
  module ClassMethods
4
4
  def find(key, klass, method, instance = true)
5
5
  rediscover(key, klass, method, instance) if ActiveSupport::Dependencies.will_unload?(klass)
6
+ _inject(key, klass, method, instance)
7
+ end
6
8
 
9
+ def _inject(key, klass, method, instance)
7
10
  klass.class_eval <<-EOL, __FILE__, __LINE__
8
11
  #{"class << self" unless instance}
9
12
  def #{method}_with_remnant(*args, &block)
@@ -17,6 +20,11 @@ class Remnant
17
20
  EOL
18
21
  end
19
22
 
23
+ def find_with(klass, &block)
24
+ rediscover(klass, block) if ActiveSupport::Dependencies.will_unload?(klass)
25
+ block.call
26
+ end
27
+
20
28
  def measure(key, &block)
21
29
  if Remnant::Discover.running.include?(key)
22
30
  yield
@@ -51,8 +59,13 @@ class Remnant
51
59
  end
52
60
 
53
61
  def rediscover!
54
- remnants_to_rediscover.map do |(key, klass_name, method, instance)|
55
- find(key, klass_name.constantize, method, instance)
62
+ remnants_to_rediscover.map do |remnant|
63
+ if remnant.size == 4
64
+ key, klass_name, method, instance = remnant
65
+ _inject(key, klass_name.constantize, method, instance)
66
+ else
67
+ remant.first.call
68
+ end
56
69
  end
57
70
  end
58
71
  end
data/lib/remnant/rails.rb CHANGED
@@ -38,6 +38,40 @@ class Remnant
38
38
  Remnant::Discover.find('view', ActionController::Base, :render)
39
39
  Remnant::Discover.find('filters', ActionController::Filters::AfterFilter, :call)
40
40
 
41
+ #
42
+ # Template rendering
43
+ #
44
+ if defined?(ActionView) && defined?(ActionView::Template)
45
+ Remnant::Discover.find_with(ActionView::Template) do
46
+ ActionView::Template.class_eval do
47
+ def render_template_with_remnant(*args, &block)
48
+ ::Remnant::Template.record(path_without_format_and_extension) do
49
+ render_template_without_remnant(*args, &block)
50
+ end
51
+ end
52
+
53
+ alias_method_chain :render_template, :remnant
54
+ end
55
+ end
56
+ end
57
+
58
+ #
59
+ # database query time
60
+ #
61
+ if ::Rails::VERSION::MAJOR == 2
62
+ Remnant::Discover.find_with(ActiveRecord::ConnectionAdapters::AbstractAdapter) do
63
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
64
+ def log_with_remnant(sql, name, &block)
65
+ ::Remnant::Database.record(sql, Kernel.caller) do
66
+ log_without_remnant(sql, name, &block)
67
+ end
68
+ end
69
+
70
+ alias_method_chain :log, :remnant
71
+ end
72
+ end
73
+ end
74
+
41
75
  # last hook into request cycle for sending results
42
76
  ::ActionController::Dispatcher.class_eval do
43
77
  def call_with_remnant_discovery(*args, &block) #:nodoc:
@@ -0,0 +1,42 @@
1
+ class Remnant
2
+ class Template
3
+ class Rendering
4
+ attr_accessor :name
5
+ attr_accessor :start_time
6
+ attr_accessor :end_time
7
+ attr_accessor :parent
8
+ attr_accessor :children
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ @children = []
13
+ end
14
+
15
+ def add(rendering)
16
+ @children << rendering
17
+ rendering.parent = self
18
+ end
19
+
20
+ def time
21
+ @end_time - @start_time
22
+ end
23
+
24
+ def exclusive_time
25
+ time - child_time
26
+ end
27
+
28
+ def child_time
29
+ children.inject(0.0) {|memo, c| memo + c.time}
30
+ end
31
+
32
+ def results
33
+ @results ||= {name.to_s => {
34
+ 'time' => time * 1000.0,
35
+ 'exclusive' => exclusive_time * 1000.0,
36
+ 'children' => children.map(&:results)
37
+ }
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,49 @@
1
+ # -*- coding: utf-8 -*-
2
+ class Remnant
3
+ class Template
4
+ class Trace
5
+ def start(template_name)
6
+ rendering = Remnant::Template::Rendering.new(template_name)
7
+ rendering.start_time = Time.now
8
+ @current.add(rendering)
9
+ @current = rendering
10
+ end
11
+
12
+ def finished(template_name)
13
+ @current.end_time = Time.now
14
+ @current = @current.parent
15
+ end
16
+
17
+ def initialize
18
+ @current = root
19
+ end
20
+
21
+ def total_time
22
+ root.child_time
23
+ end
24
+
25
+ def root
26
+ @root ||= Remnant::Template::Rendering.new('root')
27
+ end
28
+
29
+ def log(logger, rendering, depth = 0)
30
+ rendering.results.map do |key, result|
31
+
32
+ #
33
+ line = Remnant.color
34
+ line += "#{' ' * depth}#{depth != 0 ? '└ ' : ''}"
35
+ line += "#{result['time'].to_i}ms (#{result['exclusive'].to_i}ms)"
36
+ line += Remnant.color(true)
37
+ line += ' ' * ((line.size >= 50 ? 10 : 50 - line.size) - (depth == 0 ? 2 : 0))
38
+ line += "#{key}"
39
+
40
+ logger.info line
41
+
42
+ rendering.children.map do |child|
43
+ log(logger, child, depth + 1)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ class Remnant
2
+ class Template
3
+
4
+ module ClassMethods
5
+ def disable!
6
+ @enabled = false
7
+ end
8
+
9
+ def enable!
10
+ @enabled = true
11
+ end
12
+
13
+ def enabled?
14
+ @enabled
15
+ end
16
+
17
+ def record(template)
18
+ return yield unless Remnant::Template.enabled?
19
+
20
+ trace.start(template)
21
+ begin
22
+ result = yield
23
+ ensure
24
+ trace.finished(template)
25
+ end
26
+ return result
27
+ end
28
+
29
+ def reset
30
+ Thread.current['remnant.template.trace'] = Remnant::Template::Trace.new
31
+ end
32
+
33
+ def trace
34
+ Thread.current['remnant.template.trace'] ||= Remnant::Template::Trace.new
35
+ end
36
+ end
37
+ extend ClassMethods
38
+ end
39
+ end
@@ -1,3 +1,3 @@
1
1
  class Remnant
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/remnant.rb CHANGED
@@ -3,6 +3,14 @@ require 'statsd'
3
3
  require 'remnant/base'
4
4
  require 'remnant/configuration'
5
5
  require 'remnant/discover'
6
+
7
+ require 'remnant/template'
8
+ require 'remnant/template/trace'
9
+ require 'remnant/template/rendering'
10
+
11
+ require 'remnant/database'
12
+ require 'remnant/database/query'
13
+
6
14
  require 'remnant/rails'
7
15
  require 'remnant/version'
8
16
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remnant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-07 00:00:00.000000000 Z
12
+ date: 2013-01-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: statsd-ruby
@@ -140,9 +140,14 @@ files:
140
140
  - lib/remnant.rb
141
141
  - lib/remnant/base.rb
142
142
  - lib/remnant/configuration.rb
143
+ - lib/remnant/database.rb
144
+ - lib/remnant/database/query.rb
143
145
  - lib/remnant/discover.rb
144
146
  - lib/remnant/rails.rb
145
147
  - lib/remnant/railtie.rb
148
+ - lib/remnant/template.rb
149
+ - lib/remnant/template/rendering.rb
150
+ - lib/remnant/template/trace.rb
146
151
  - lib/remnant/version.rb
147
152
  - remnant.gemspec
148
153
  - spec/app/some/klass.rb