remnant 0.2.4 → 0.3.0

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/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