fiveruns-dash-rails 0.7.8 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -8,11 +8,11 @@ You'll need a Dash account before using this library.
8
8
 
9
9
  This library is released as a gem from the official repository at http://github.com/fiveruns/dash-rails
10
10
 
11
- sudo gem install fiveruns-dash-rails --source 'http://gems.github.com'
11
+ sudo gem install fiveruns-dash-rails --source http://gems.github.com
12
12
 
13
13
  == Usage
14
14
 
15
- See the Ruby Language Guide http://dash.fiveruns.com/help/ruby.html for information on how to use this library.
15
+ See the Dash Ruby support pages http://support.fiveruns.com/faqs/dash/ruby for information on how to use this library.
16
16
 
17
17
  == Authors
18
18
 
@@ -20,7 +20,8 @@ The FiveRuns Development Team & Dash community
20
20
 
21
21
  == Dependencies
22
22
 
23
- * The fiveruns-dash-ruby gem (see http://github.com/fiveruns/dash-ruby)
23
+ * The fiveruns-dash-activerecord gem (http://github.com/fiveruns/dash-activerecord)
24
+ * The fiveruns-dash-ruby gem (http://github.com/fiveruns/dash-ruby)
24
25
  * The json gem (as a dependency for fiveruns-dash-ruby)
25
26
 
26
27
  == Verifying your setup
@@ -53,7 +54,7 @@ The best way to contribute is by sending pull requests via GitHub. The official
53
54
 
54
55
  Please join the dash-users Google group, http://groups.google.com/group/dash-users
55
56
 
56
- You can also contact us via Twitter, Campfire, or email; see the main help page, http://dash.fiveruns.com/help, for details.
57
+ You can also contact us via Twitter, Campfire, or email; see the main help page, http://support.fiveruns.com, for details.
57
58
 
58
59
  == License
59
60
 
data/Rakefile CHANGED
@@ -20,19 +20,14 @@ begin
20
20
  s.homepage = "http://github.com/fiveruns/dash-rails"
21
21
  s.description = "Provides an API to send metrics from Rails applications to the FiveRuns Dash service"
22
22
  s.authors = ["FiveRuns Development Team"]
23
- s.files = FileList['README.rdoc', 'Rakefile', 'version.yml', 'init.rb', "{lib,rails,test}/**/*", ]
24
- s.add_dependency 'fiveruns-dash-ruby', '>= 0.7.1'
23
+ s.files = FileList['README.rdoc', 'Rakefile', 'VERSION.yml', 'init.rb', "{lib,rails,test}/**/*", ]
24
+ s.add_dependency 'fiveruns-dash-ruby', '>= 0.8.1'
25
+ s.add_dependency 'fiveruns-dash-activerecord', '>= 0.8.1'
25
26
  end
26
27
  rescue LoadError
27
28
  puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
28
29
  end
29
30
 
30
- NAME = "dash-rails"
31
- AUTHOR = "FiveRuns Development Team"
32
- EMAIL = "dev@fiveruns.com"
33
- HOMEPAGE = "http://dash.fiveruns.com/"
34
- SUMMARY = "FiveRuns Dash library for Ruby on Rails"
35
-
36
31
  task :coverage do
37
32
  rm_f "coverage"
38
33
  rm_f "coverage.data"
@@ -0,0 +1,44 @@
1
+ module Fiveruns::Dash::Rails::Context
2
+
3
+ module Action
4
+
5
+ def self.included(base)
6
+ base.send(:include, InstanceMethods)
7
+ base.alias_method_chain :perform_action, :fiveruns_dash_context
8
+ base.extend(ClassMethods)
9
+ (class << base; self; end).alias_method_chain :process, :fiveruns_dash_tracing
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ def process_with_fiveruns_dash_tracing(*args, &block)
15
+ operation = lambda { process_without_fiveruns_dash_tracing(*args, &block) }
16
+ params = args.first.parameters
17
+ # TODO/FIXME: For now, we simply look for a 'trace' parameter to select requests to trace; in the
18
+ # future, we need a more advanced sampling mechanism (some operation in a recipe a
19
+ # request must pass, or selection criteria returned in a response from the service)
20
+ trace_context = ['action', "#{params['controller'].camelize}Controller##{params['action']}"]
21
+ if ::Fiveruns::Dash.trace_contexts.include?(trace_context)
22
+ ::Fiveruns::Dash.session.trace(trace_context) do
23
+ operation.call
24
+ end
25
+ else
26
+ operation.call
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ module InstanceMethods
33
+
34
+ def perform_action_with_fiveruns_dash_context(*args, &block)
35
+ action_name = (request.parameters['action'] || 'index').to_s
36
+ Fiveruns::Dash::Context.set ['action', %(#{self.class.name}##{action_name})]
37
+ perform_action_without_fiveruns_dash_context(*args, &block)
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,62 @@
1
+ module Fiveruns::Dash::Rails::Context
2
+
3
+ module ActiveRecord
4
+
5
+ def self.included(base)
6
+ class << base
7
+ Fiveruns::Dash::ActiveRecord::CLASS_METHODS.each do |meth|
8
+ head = meth
9
+ tail = ''
10
+ head, tail = meth[0..(meth.length-2)], meth[-1..-1] if %w(? !).include? meth[-1..-1]
11
+ self.class_eval <<-EOM
12
+ def #{head}_with_dash_context#{tail}(*args, &block)
13
+ Fiveruns::Dash::Rails::Context::ActiveRecord.with_model_context(self.name) do
14
+ #{head}_without_dash_context#{tail}(*args, &block)
15
+ end
16
+ end
17
+ EOM
18
+ alias_method_chain(meth.to_sym, :dash_context)
19
+ end
20
+ end
21
+
22
+ Fiveruns::Dash::ActiveRecord::INSTANCE_METHODS.each do |meth|
23
+ head = meth
24
+ tail = ''
25
+ head, tail = meth[0..meth.length-2], meth[-1..-1] if %w(? !).include? meth[-1..-1]
26
+ base.class_eval <<-EOM
27
+ def #{head}_with_dash_context#{tail}(*args, &block)
28
+ Fiveruns::Dash::Rails::Context::ActiveRecord.with_model_context(self.class.name) do
29
+ #{head}_without_dash_context#{tail}(*args, &block)
30
+ end
31
+ end
32
+ EOM
33
+ base.alias_method_chain(meth.to_sym, :dash_context)
34
+ end
35
+ end
36
+
37
+ def self.with_model_context(model_name)
38
+ context = Fiveruns::Dash::Context.context
39
+ # don't change context if model context has already been set.
40
+ if context.size > 0 && context[-2] == 'model' && context[-1] == model_name
41
+ return yield
42
+ end
43
+
44
+ original_context = Fiveruns::Dash::Context.context.dup
45
+ begin
46
+ if context[-2] == 'model'
47
+ # Some models will internally load other models.
48
+ Fiveruns::Dash::Context.context.pop
49
+ Fiveruns::Dash::Context.context << model_name
50
+ else
51
+ Fiveruns::Dash::Context.context << 'model'
52
+ Fiveruns::Dash::Context.context << model_name
53
+ end
54
+ return yield
55
+ ensure
56
+ Fiveruns::Dash::Context.set original_context
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,57 @@
1
+ module Fiveruns::Dash::Rails::Context
2
+
3
+ module Template
4
+
5
+ def self.included(base)
6
+ base.send(:include, InstanceMethods)
7
+ base.alias_method_chain(:render, :fiveruns_dash_context)
8
+ end
9
+
10
+ RAILS_ROOT_RE = /\A#{Regexp.quote RAILS_ROOT}/
11
+
12
+ GEM_REs = Gem.path.map do |path|
13
+ /\A#{Regexp.quote path}\/gems/
14
+ end
15
+
16
+ def self.sanitize_view_path(path)
17
+ path = if path[0..0] == '/'
18
+ if path =~ RAILS_ROOT_RE
19
+ trimmed = path.sub(RAILS_ROOT_RE, 'RAILS_ROOT')
20
+ trimmed
21
+ elsif (re = GEM_REs.find { |re| path =~ re })
22
+ trimmed = path.sub(re, 'GEMS')
23
+ else
24
+ path
25
+ end
26
+ else
27
+ path
28
+ end
29
+ # Remove extensions, if any
30
+ path.sub(/\.[^\/\\]*$/, '')
31
+ end
32
+
33
+ module InstanceMethods
34
+
35
+ def render_with_fiveruns_dash_context(*args, &block)
36
+ original_context = Fiveruns::Dash::Context.context.dup
37
+
38
+ begin
39
+ Fiveruns::Dash::Context.context << 'view'
40
+ if respond_to?(:path)
41
+ Fiveruns::Dash::Context.context << Fiveruns::Dash::Rails::Context::Template.sanitize_view_path(path)
42
+ else
43
+ Fiveruns::Dash::Context.context << '(inline)'
44
+ end
45
+ result = render_without_fiveruns_dash_context(*args, &block)
46
+ ensure
47
+ Fiveruns::Dash::Context.set original_context
48
+ end
49
+
50
+ result
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,17 @@
1
+ module Fiveruns::Dash::Rails::Initializer
2
+
3
+ def self.included(base)
4
+ base.send(:include, InstanceMethods)
5
+ base.alias_method_chain :prepare_dispatcher, :dash
6
+ end
7
+
8
+ module InstanceMethods
9
+
10
+ def prepare_dispatcher_with_dash
11
+ prepare_dispatcher_without_dash
12
+ Fiveruns::Dash::Rails.dash_start_block.call
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -1,4 +1,3 @@
1
- require File.dirname(__FILE__) << "/rails/version"
2
1
  require File.dirname(__FILE__) << "/rails/startup"
3
2
 
4
3
  if START_FIVERUNS_DASH_RAILS
@@ -7,10 +6,29 @@ if START_FIVERUNS_DASH_RAILS
7
6
  module Dash
8
7
 
9
8
  module Rails
9
+
10
+ version_file = File.dirname(__FILE__) << "/../../../VERSION.yml"
11
+ version = YAML.load(version_file)
12
+ VERSION = [
13
+ version[:major],
14
+ version[:minor],
15
+ version[:patch]
16
+ ].map(&:to_s).join('.')
10
17
 
11
18
  class << self
12
19
  attr_accessor :server
13
20
  end
21
+
22
+ def self.clean_hash(obj = {})
23
+ (obj || {}).keys.inject({}) do |all, key|
24
+ val = obj[key]
25
+ if val.is_a?(Hash)
26
+ val = clean(val)
27
+ end
28
+ all[key.to_s] = val
29
+ all
30
+ end
31
+ end
14
32
 
15
33
  def self.queue_size
16
34
  return 0 unless server_type
@@ -50,7 +68,6 @@ if START_FIVERUNS_DASH_RAILS
50
68
  store_dash_start_block do
51
69
  configure(tokens, &block) unless tokens.empty?
52
70
  if Fiveruns::Dash.configuration.ready?
53
- RAILS_DEFAULT_LOGGER.info "Starting Dash"
54
71
  Fiveruns::Dash.session.start
55
72
  else
56
73
  log_error unless env == 'development'
@@ -79,14 +96,14 @@ if START_FIVERUNS_DASH_RAILS
79
96
  def self.log_error
80
97
  # TODO: Add URL for help
81
98
  message =<<-EOM
82
- FiveRuns Dash [Rails] (v#{Version::STRING}) Application token missing
99
+ FiveRuns Dash [Rails] (v#{VERSION}) Application token missing
83
100
  ===
84
- In config/initializers/dash.rb or at the bottom of config/environment.rb, please add:
101
+ In config/initializers/dash.rb please add:
85
102
 
86
- Fiveruns::Dash::Rails.configure :#{env} => 'YOUR-#{env.upcase}-ENV-APP-TOKEN-HERE'
103
+ Fiveruns::Dash::Rails.start :#{env} => '#{env.upcase}-APP-TOKEN'
87
104
 
88
105
  You can also set app tokens for other environments (eg, staging), at the same time.
89
- See http://todo/path/to/help for more information
106
+ See http://support.fiveruns.com/faqs/dash/rails for more information
90
107
  ===
91
108
  EOM
92
109
  RAILS_DEFAULT_LOGGER.warn(message.strip)
@@ -157,65 +174,6 @@ if START_FIVERUNS_DASH_RAILS
157
174
  end
158
175
  end
159
176
 
160
- module ActionContext
161
-
162
- def self.included(base)
163
- base.send(:include, InstanceMethods)
164
- base.alias_method_chain :perform_action, :fiveruns_dash_context
165
- base.extend(ClassMethods)
166
- (class << base; self; end).alias_method_chain :process, :fiveruns_dash_tracing
167
- end
168
-
169
- module ClassMethods
170
-
171
- def process_with_fiveruns_dash_tracing(*args, &block)
172
- operation = lambda { process_without_fiveruns_dash_tracing(*args, &block) }
173
- params = args.first.parameters
174
- # TODO/FIXME: For now, we simply look for a 'trace' parameter to select requests to trace; in the
175
- # future, we need a more advanced sampling mechanism (some operation in a recipe a
176
- # request must pass, or selection criteria returned in a response from the service)
177
- trace_context = ['action', "#{params['controller'].camelize}Controller##{params['action']}"]
178
- if ::Fiveruns::Dash.trace_contexts.include?(trace_context)
179
- ::Fiveruns::Dash.session.trace(trace_context) do
180
- operation.call
181
- end
182
- else
183
- operation.call
184
- end
185
- end
186
-
187
- end
188
-
189
- module InstanceMethods
190
-
191
- def perform_action_with_fiveruns_dash_context(*args, &block)
192
- action_name = (request.parameters['action'] || 'index').to_s
193
- Fiveruns::Dash::Context.set ['action', %(#{self.class.name}##{action_name})]
194
- perform_action_without_fiveruns_dash_context(*args, &block)
195
- end
196
-
197
- end
198
-
199
- end
200
-
201
- module Initializer
202
-
203
- def self.included(base)
204
- base.send(:include, InstanceMethods)
205
- base.alias_method_chain :prepare_dispatcher, :dash
206
- end
207
-
208
- module InstanceMethods
209
-
210
- def prepare_dispatcher_with_dash
211
- prepare_dispatcher_without_dash
212
- Fiveruns::Dash::Rails.dash_start_block.call
213
- end
214
-
215
- end
216
-
217
- end
218
-
219
177
  end
220
178
 
221
179
  end
@@ -0,0 +1,15 @@
1
+ Fiveruns::Dash.register_recipe :actionpack, :url => 'http://dash.fiveruns.com' do |recipe|
2
+
3
+ recipe.time :response_time, :method => 'ActionController::Base#perform_action', :mark => true
4
+ recipe.counter :requests, 'Requests', :incremented_by => 'ActionController::Base#perform_action'
5
+
6
+ targets = []
7
+ targets << 'ActionView::Template#render' if defined?(ActionView::Template)
8
+ targets << 'ActionView::PartialTemplate#render' if defined?(ActionView::PartialTemplate)
9
+ if !targets.empty?
10
+ recipe.time :render_time, :method => targets
11
+ else
12
+ Fiveruns::Dash.logger.warn 'Collection of "render_time" unsupported for this version of Rails'
13
+ end
14
+
15
+ end
@@ -1,36 +1,17 @@
1
- module Fiveruns::Dash::Rails::Hash
1
+ # Rails #######################################################################
2
+ Fiveruns::Dash.register_recipe :rails, :url => 'http://dash.fiveruns.com' do |recipe|
2
3
 
3
- def self.clean(extended_hash = {})
4
- (extended_hash || {}).keys.inject({}) do |all, key|
5
- val = extended_hash[key]
6
- if val.kind_of? Hash
7
- val = clean(val)
4
+ recipe.add_recipe :activerecord, :url => 'http://dash.fiveruns.com',
5
+ :total_time => 'response_time'
6
+ recipe.modify :recipe_name => :activerecord, :recipe_url => 'http://dash.fiveruns.com' do |metric|
7
+ metric.find_context_with do |obj, *args|
8
+ if Fiveruns::Dash::Context.context == []
9
+ []
10
+ else
11
+ [[], Fiveruns::Dash::Context.context]
8
12
  end
9
- all[key.to_s] = val
10
- all
11
13
  end
12
14
  end
13
-
14
- end
15
-
16
- # ActionPack ##################################################################
17
- Fiveruns::Dash.register_recipe :actionpack, :url => 'http://dash.fiveruns.com' do |recipe|
18
- recipe.time :response_time, :method => 'ActionController::Base#perform_action', :mark => true
19
- recipe.counter :requests, 'Requests', :incremented_by => 'ActionController::Base#perform_action'
20
-
21
- targets = []
22
- targets << 'ActionView::Template#render' if defined?(ActionView::Template)
23
- targets << 'ActionView::PartialTemplate#render' if defined?(ActionView::PartialTemplate)
24
- if !targets.empty?
25
- recipe.time :render_time, :method => targets
26
- else
27
- Fiveruns::Dash.logger.warn 'Collection of "render_time" unsupported for this version of Rails'
28
- end
29
- end
30
-
31
- # Rails #######################################################################
32
- Fiveruns::Dash.register_recipe :rails, :url => 'http://dash.fiveruns.com' do |recipe|
33
- recipe.add_recipe :activerecord, :url => 'http://dash.fiveruns.com'
34
15
 
35
16
  recipe.add_recipe :actionpack, :url => 'http://dash.fiveruns.com'
36
17
  recipe.modify :recipe_name => :actionpack, :recipe_url => 'http://dash.fiveruns.com' do |metric|
@@ -49,21 +30,21 @@ Fiveruns::Dash.register_recipe :rails, :url => 'http://dash.fiveruns.com' do |re
49
30
  info = {:name => "#{ex.class.name} in #{controller.class.name}##{controller.params[:action]}"}
50
31
  begin
51
32
  session_data = controller.request.session.instance_variable_get("@data")
52
- info[:session] = Fiveruns::Dash::Rails::Hash.clean(session_data).to_json
33
+ info[:session] = Fiveruns::Dash::Rails.clean_hash(session_data).to_json
53
34
  rescue Exception => e
54
35
  Fiveruns::Dash.logger.warn "Could not dump session data for exception: #{e.message}"
55
36
  nil
56
37
  end
57
38
  begin
58
39
  request_data = { :url => controller.request.url, :params => controller.params.inspect }
59
- info[:request] = Fiveruns::Dash::Rails::Hash.clean(request_data).to_json
40
+ info[:request] = Fiveruns::Dash::Rails.clean_hash(request_data).to_json
60
41
  rescue Exception => e
61
42
  Fiveruns::Dash.logger.error "Could not dump request data for exception: #{e.message}"
62
43
  nil
63
44
  end
64
45
  begin
65
46
  header_data = controller.request.headers
66
- info[:headers] = Fiveruns::Dash::Rails::Hash.clean(header_data).to_json
47
+ info[:headers] = Fiveruns::Dash::Rails.clean_hash(header_data).to_json
67
48
  rescue Exception => e
68
49
  Fiveruns::Dash.logger.error "Could not dump header data for exception: #{e.message}"
69
50
  nil
@@ -72,17 +53,21 @@ Fiveruns::Dash.register_recipe :rails, :url => 'http://dash.fiveruns.com' do |re
72
53
  end
73
54
 
74
55
  # Same classes as the exception_notification plugin
75
- IGNORE = [ActiveRecord::RecordNotFound, ActionController::RoutingError, ActionController::UnknownController, ActionController::UnknownAction]
76
-
77
- recipe.ignore_exceptions do |exc|
78
- IGNORE.include? exc.class
56
+ recipe.ignore_exceptions do |exception|
57
+ [ ActiveRecord::RecordNotFound,
58
+ ActionController::RoutingError,
59
+ ActionController::UnknownController,
60
+ ActionController::UnknownAction
61
+ ].include?(exception.class)
79
62
  end
80
63
 
81
64
  recipe.added do
82
- ActionController::Base.send(:include, Fiveruns::Dash::Rails::ActionContext)
83
- ActionView::Template.send(:include, Fiveruns::Dash::Rails::TemplateContext) if defined?(ActionView::Template)
84
- ActionView::InlineTemplate.send(:include, Fiveruns::Dash::Rails::TemplateContext) if defined?(ActionView::InlineTemplate)
85
- ActionView::PartialTemplate.send(:include, Fiveruns::Dash::Rails::TemplateContext) if defined?(ActionView::PartialTemplate)
65
+
66
+ ActiveRecord::Base.send(:include, Fiveruns::Dash::Rails::Context::ActiveRecord)
67
+ ActionController::Base.send(:include, Fiveruns::Dash::Rails::Context::Action)
68
+ ActionView::Template.send(:include, Fiveruns::Dash::Rails::Context::Template) if defined?(ActionView::Template)
69
+ ActionView::InlineTemplate.send(:include, Fiveruns::Dash::Rails::Context::Template) if defined?(ActionView::InlineTemplate)
70
+ ActionView::PartialTemplate.send(:include, Fiveruns::Dash::Rails::Context::Template) if defined?(ActionView::PartialTemplate)
86
71
 
87
72
  begin
88
73
  if defined?(Mongrel)
@@ -105,19 +90,23 @@ Fiveruns::Dash.register_recipe :rails, :url => 'http://dash.fiveruns.com' do |re
105
90
  end
106
91
  end
107
92
 
108
- # Passenger forks the Rails processes, which has the side effect of
109
- # killing our reporter thread. We need to revive the thread.
110
- class ActionController::Base
111
- def perform_action_with_dash_startup(*args, &block)
93
+ if defined?(Passenger)
94
+ # Passenger forks the Rails processes, which has the side effect of
95
+ # killing our reporter thread. We need to revive the thread.
96
+ class ActionController::Base
97
+ def perform_action_with_dash_startup(*args, &block)
98
+ Fiveruns::Dash.session.reporter.revive!
99
+ perform_action_without_dash_startup(*args, &block)
100
+ end
101
+
102
+ alias_method_chain :perform_action, :dash_startup
103
+ end
104
+ elsif defined?(PhusionPassenger)
105
+ # Passenger 2.1+ has an event to handle this gracefully
106
+ PhusionPassenger.on_event(:starting_worker_process) do
112
107
  Fiveruns::Dash.session.reporter.revive!
113
- perform_action_without_dash_startup(*args, &block)
114
108
  end
115
-
116
- alias_method_chain :perform_action, :dash_startup
117
109
  end
118
110
  end
119
111
 
120
- recipe.absolute :queue_size do
121
- Fiveruns::Dash::Rails.queue_size || 0
122
- end
123
112
  end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) << "/fiveruns/dash/rails/startup"
2
+
3
+ if START_FIVERUNS_DASH_RAILS
4
+ gem 'fiveruns-dash-ruby' # Put its path first
5
+ require 'fiveruns/dash'
6
+ begin
7
+ require 'fiveruns/dash/activerecord'
8
+ rescue LoadError
9
+ abort "Missing the `activerecord' recipe. Please install the fiveruns-dash-activerecord gem"
10
+ end
11
+ require 'fiveruns/dash/rails'
12
+ require 'fiveruns/dash/rails/initializer'
13
+ require 'fiveruns/dash/rails/context/action'
14
+ require 'fiveruns/dash/rails/context/active_record'
15
+ require 'fiveruns/dash/rails/context/template'
16
+ require File.dirname(__FILE__) << "/../rails/init"
17
+ end
@@ -1,9 +1,2 @@
1
- require File.dirname(__FILE__) << "/fiveruns/dash/rails/startup"
2
-
3
- if START_FIVERUNS_DASH_RAILS
4
- gem 'fiveruns-dash-ruby' # Put its path first
5
- require 'fiveruns/dash'
6
- require 'fiveruns/dash/rails'
7
- require 'fiveruns/dash/template_context'
8
- require File.dirname(__FILE__) << "/../rails/init"
9
- end
1
+ # Stub for backwards compatibility
2
+ require File.dirname(__FILE__) << "/fiveruns-dash-rails"
data/rails/init.rb CHANGED
@@ -20,7 +20,7 @@ end
20
20
 
21
21
  if START_FIVERUNS_DASH_RAILS
22
22
 
23
- require 'fiveruns_dash_rails'
23
+ require 'fiveruns-dash-rails'
24
24
  Fiveruns::Dash.logger = RAILS_DEFAULT_LOGGER
25
25
  Fiveruns::Dash::Rails.load_recipes
26
26
  Fiveruns::Dash.configure do |config|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiveruns-dash-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.8
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - FiveRuns Development Team
@@ -9,17 +9,28 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-11 00:00:00 -08:00
12
+ date: 2009-02-20 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: fiveruns-dash-ruby
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
20
21
  - - ">="
21
22
  - !ruby/object:Gem::Version
22
- version: 0.7.1
23
+ version: 0.8.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: fiveruns-dash-activerecord
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.1
23
34
  version:
24
35
  description: Provides an API to send metrics from Rails applications to the FiveRuns Dash service
25
36
  email: dev@fiveruns.com
@@ -32,22 +43,24 @@ extra_rdoc_files: []
32
43
  files:
33
44
  - README.rdoc
34
45
  - Rakefile
35
- - version.yml
46
+ - VERSION.yml
36
47
  - init.rb
37
48
  - lib/fiveruns
38
49
  - lib/fiveruns/dash
39
50
  - lib/fiveruns/dash/rails
51
+ - lib/fiveruns/dash/rails/context
52
+ - lib/fiveruns/dash/rails/context/action.rb
53
+ - lib/fiveruns/dash/rails/context/active_record.rb
54
+ - lib/fiveruns/dash/rails/context/template.rb
55
+ - lib/fiveruns/dash/rails/initializer.rb
40
56
  - lib/fiveruns/dash/rails/startup.rb
41
- - lib/fiveruns/dash/rails/version.rb
42
57
  - lib/fiveruns/dash/rails.rb
43
58
  - lib/fiveruns/dash/recipes
44
- - lib/fiveruns/dash/recipes/activerecord.rb
59
+ - lib/fiveruns/dash/recipes/actionpack.rb
45
60
  - lib/fiveruns/dash/recipes/rails.rb
46
- - lib/fiveruns/dash/template_context.rb
61
+ - lib/fiveruns-dash-rails.rb
47
62
  - lib/fiveruns_dash_rails.rb
48
63
  - rails/init.rb
49
- - test/activerecord_test.rb
50
- - test/test_helper.rb
51
64
  has_rdoc: true
52
65
  homepage: http://github.com/fiveruns/dash-rails
53
66
  post_install_message:
@@ -1,97 +0,0 @@
1
- # (The MIT License)
2
- #
3
- # Copyright (c) 2008 Jamis Buck <jamis@37signals.com>,
4
- # with modifications by Bruce Williams <bruce@fiveruns.com>
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining
7
- # a copy of this software and associated documentation files (the
8
- # 'Software'), to deal in the Software without restriction, including
9
- # without limitation the rights to use, copy, modify, merge, publish,
10
- # distribute, sublicense, and/or sell copies of the Software, and to
11
- # permit persons to whom the Software is furnished to do so, subject to
12
- # the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be
15
- # included in all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
- module Fiveruns
25
-
26
- module Dash
27
-
28
- module Rails
29
-
30
- # A class for describing the current version of a library. The version
31
- # consists of three parts: the +major+ number, the +minor+ number, and the
32
- # +tiny+ (or +patch+) number.
33
- class Version
34
-
35
- include Comparable
36
-
37
- # A convenience method for instantiating a new Version instance with the
38
- # given +major+, +minor+, and +tiny+ components.
39
- def self.[](major, minor, tiny)
40
- new(major, minor, tiny)
41
- end
42
-
43
- # Borrowed from TuneUp
44
- def self.rails
45
- @rails ||= begin
46
- # handle ::Rails::VERSION not being set
47
- Version.new(::Rails::VERSION::MAJOR, ::Rails::VERSION::MINOR, ::Rails::VERSION::TINY) rescue Version.new(0,0,0)
48
- end
49
- end
50
-
51
-
52
- attr_reader :major, :minor, :tiny
53
-
54
- # Create a new Version object with the given components.
55
- def initialize(major, minor, tiny)
56
- @major, @minor, @tiny = major, minor, tiny
57
- end
58
-
59
- # Compare this version to the given +version+ object.
60
- def <=>(version)
61
- to_i <=> version.to_i
62
- end
63
-
64
- # Converts this version object to a string, where each of the three
65
- # version components are joined by the '.' character. E.g., 2.0.0.
66
- def to_s
67
- @to_s ||= [@major, @minor, @tiny].join(".")
68
- end
69
-
70
- # Converts this version to a canonical integer that may be compared
71
- # against other version objects.
72
- def to_i
73
- @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
74
- end
75
-
76
- def to_a
77
- [@major, @minor, @tiny]
78
- end
79
-
80
- PARSED = YAML.load(File.read(File.dirname(__FILE__) << "/../../../../version.yml"))
81
-
82
- MAJOR = PARSED[:major]
83
- MINOR = PARSED[:minor]
84
- TINY = PARSED[:patch]
85
-
86
- # The current version as a Version instance
87
- CURRENT = new(MAJOR, MINOR, TINY)
88
- # The current version as a String
89
- STRING = CURRENT.to_s
90
-
91
- end
92
-
93
- end
94
-
95
- end
96
-
97
- end
@@ -1,96 +0,0 @@
1
- module Fiveruns::Dash::ActiveRecordContext
2
- CLASS_METHODS = %w(find find_by_sql calculate create create! update_all destroy destroy_all delete delete_all)
3
- INSTANCE_METHODS = %w(update save save! destroy)
4
-
5
- def self.included(base)
6
- class << base
7
- CLASS_METHODS.each do |meth|
8
- head = meth
9
- tail = ''
10
- head, tail = meth[0..(meth.length-2)], meth[-1..-1] if %w(? !).include? meth[-1..-1]
11
- self.class_eval <<-EOM
12
- def #{head}_with_dash_context#{tail}(*args, &block)
13
- Fiveruns::Dash::ActiveRecordContext.with_model_context(self.name) do
14
- #{head}_without_dash_context#{tail}(*args, &block)
15
- end
16
- end
17
- EOM
18
- alias_method_chain(meth.to_sym, :dash_context)
19
- end
20
- end
21
-
22
- INSTANCE_METHODS.each do |meth|
23
- head = meth
24
- tail = ''
25
- head, tail = meth[0..meth.length-2], meth[-1..-1] if %w(? !).include? meth[-1..-1]
26
- base.class_eval <<-EOM
27
- def #{head}_with_dash_context#{tail}(*args, &block)
28
- Fiveruns::Dash::ActiveRecordContext.with_model_context(self.class.name) do
29
- #{head}_without_dash_context#{tail}(*args, &block)
30
- end
31
- end
32
- EOM
33
- base.alias_method_chain(meth.to_sym, :dash_context)
34
- end
35
- end
36
-
37
- def self.with_model_context(model_name)
38
- ctx = Fiveruns::Dash::Context.context
39
- # don't change context if model context has already been set.
40
- return yield if ctx.size > 0 && ctx[-2] == 'model' && ctx[-1] == model_name
41
-
42
- original_context = Fiveruns::Dash::Context.context.dup
43
- begin
44
- if ctx[-2] == 'model'
45
- # Some models will internally load other models.
46
- Fiveruns::Dash::Context.context.pop
47
- Fiveruns::Dash::Context.context << model_name
48
- else
49
- Fiveruns::Dash::Context.context << 'model'
50
- Fiveruns::Dash::Context.context << model_name
51
- end
52
- return yield
53
- ensure
54
- Fiveruns::Dash::Context.set original_context
55
- end
56
- end
57
-
58
- def self.all_methods
59
- CLASS_METHODS.map { |m| "ActiveRecord::Base.#{m}" } + INSTANCE_METHODS.map { |m| "ActiveRecord::Base##{m}"}
60
- end
61
-
62
- end
63
-
64
- # ActiveRecord ################################################################
65
-
66
- Fiveruns::Dash.register_recipe :activerecord, :url => 'http://dash.fiveruns.com' do |recipe|
67
- # We need a way to get the total time for a request/operation so that we can
68
- # calculate the relative percentage used by AR/DB. Default to "response_time" for the Rails
69
- # recipe but daemons can set this constant to provide their own total time metric.
70
- total_time = recipe.options[:ar_total_time] ? recipe.options[:ar_total_time] : "response_time"
71
-
72
- recipe.time :ar_time, 'ActiveRecord Time', :methods => Fiveruns::Dash::ActiveRecordContext.all_methods, :reentrant => true, :only_within => total_time
73
- recipe.time :db_time, 'Database Time', :methods => %w(ActiveRecord::ConnectionAdapters::AbstractAdapter#log), :only_within => total_time
74
-
75
- recipe.percentage :ar_util, 'ActiveRecord Utilization', :sources => ["ar_time", total_time] do |ar_time, all_time|
76
- all_time == 0 ? 0 : (ar_time / all_time) * 100.0
77
- end
78
- recipe.percentage :db_util, 'Database Utilization', :sources => ["db_time", total_time] do |db_time, all_time|
79
- all_time == 0 ? 0 : (db_time / all_time) * 100.0
80
- end
81
-
82
- recipe.modify :recipe_name => :activerecord, :recipe_url => 'http://dash.fiveruns.com' do |metric|
83
- metric.find_context_with do |obj, *args|
84
- if Fiveruns::Dash::Context.context == []
85
- []
86
- else
87
- [[], Fiveruns::Dash::Context.context]
88
- end
89
- end
90
- end
91
-
92
- recipe.added do
93
- ActiveRecord::Base.send(:include, Fiveruns::Dash::ActiveRecordContext)
94
- end
95
- end
96
-
@@ -1,54 +0,0 @@
1
-
2
- module Fiveruns::Dash::Rails::TemplateContext
3
-
4
- def self.included(base)
5
- base.send(:include, InstanceMethods)
6
- base.alias_method_chain(:render, :fiveruns_dash_context)
7
- end
8
-
9
- RAILS_ROOT_RE = /\A#{Regexp.quote RAILS_ROOT}/
10
-
11
- GEM_REs = Gem.path.map do |path|
12
- /\A#{Regexp.quote path}\/gems/
13
- end
14
-
15
- def self.sanitize_view_path(path)
16
- path = if path[0..0] == '/'
17
- if path =~ RAILS_ROOT_RE
18
- trimmed = path.sub(RAILS_ROOT_RE, 'RAILS_ROOT')
19
- trimmed
20
- elsif (re = GEM_REs.find { |re| path =~ re })
21
- trimmed = path.sub(re, 'GEMS')
22
- else
23
- path
24
- end
25
- else
26
- path
27
- end
28
- # Remove extensions, if any
29
- path.sub(/\.[^\/\\]*$/, '')
30
- end
31
-
32
- module InstanceMethods
33
-
34
- def render_with_fiveruns_dash_context(*args, &block)
35
- original_context = Fiveruns::Dash::Context.context.dup
36
-
37
- begin
38
- Fiveruns::Dash::Context.context << 'view'
39
- if respond_to?(:path)
40
- Fiveruns::Dash::Context.context << Fiveruns::Dash::Rails::TemplateContext.sanitize_view_path(path)
41
- else
42
- Fiveruns::Dash::Context.context << '(inline)'
43
- end
44
- result = render_without_fiveruns_dash_context(*args, &block)
45
- ensure
46
- Fiveruns::Dash::Context.set original_context
47
- end
48
-
49
- result
50
- end
51
-
52
- end
53
-
54
- end
@@ -1,113 +0,0 @@
1
- require File.dirname(__FILE__) << "/test_helper"
2
-
3
- class ActiverecordTest < Test::Unit::TestCase
4
-
5
- class TestModel < ActiveRecord::Base
6
- end
7
-
8
- class TestEngine
9
- def doit
10
- sleep 1
11
- 2.times do
12
- t = TestModel.create!(:name => 'foo')
13
- t.destroy
14
- end
15
- end
16
-
17
- def conn
18
- TestModel.connection.execute("select sleep(1)")
19
- end
20
-
21
- def entry(meth)
22
- send(meth)
23
- end
24
- end
25
-
26
-
27
- context "Metric" do
28
-
29
- setup do
30
- ActiveRecord::Base.configurations = { 'test' => { 'database' => 'test', 'adapter' => 'mysql', 'user' => 'root', 'hostname' => 'localhost' }}
31
- ActiveRecord::Base.establish_connection
32
- ActiveRecord::Base.connection.execute("create table if not exists test_models (id integer PRIMARY KEY, name varchar(32) not null)")
33
- ActiveRecord::Base.connection.execute("delete from test_models")
34
- end
35
-
36
- should "collect basic AR metrics" do
37
- ar_scenario do
38
- TestEngine.new.entry(:doit)
39
-
40
- data = Fiveruns::Dash.session.data
41
- # data.each do |hsh|
42
- # puts "#{hsh[:name]}: #{hsh[:values].inspect}"
43
- # end
44
-
45
- assert metric('test_time', data) > 1.0
46
- assert metric('ar_util', data) > metric('db_util', data)
47
- assert metric('db_util', data) < 5
48
- end
49
- end
50
-
51
- should "collect DB metrics" do
52
- ar_scenario do
53
- TestEngine.new.entry(:conn)
54
-
55
- data = Fiveruns::Dash.session.data
56
- # data.each do |hsh|
57
- # puts "#{hsh[:name]}: #{hsh[:values].inspect}"
58
- # end
59
-
60
- assert metric('test_time', data) > 1.0
61
- assert metric('test_time', data) < 1.1
62
- assert metric('db_time', data) > 1.0
63
- assert metric('db_time', data) < 1.1
64
- assert metric('db_util', data) > 90.0
65
- assert metric('db_util', data) < 100.0
66
- end
67
- end
68
- end
69
-
70
- def ar_scenario(&block)
71
- child = fork do
72
- mock_activerecord!
73
- yield
74
- end
75
- Process.wait
76
- assert_equal 0, $?.exitstatus
77
- end
78
-
79
- def metric(metric, data, in_ctx=[])
80
- hsh = data.detect { |hsh| hsh[:name] == metric }
81
- assert hsh, "No metric named #{metric} was found in metrics payload"
82
- vals = hsh[:values]
83
- assert vals, "No values found for #{metric} in metrics payload"
84
- val = vals.detect { |val| val[:context] == in_ctx }
85
- assert val, "No value for #{metric} found for context #{in_ctx.inspect}"
86
- val[:value]
87
- end
88
-
89
- def mock_activerecord!
90
- require 'fiveruns/dash'
91
- require 'fiveruns/dash/recipes/activerecord'
92
-
93
- eval <<-MOCK
94
- module Fiveruns::Dash
95
- class Reporter
96
- private
97
- def run
98
- end
99
- end
100
- end
101
- MOCK
102
-
103
- Fiveruns::Dash.register_recipe :tester, :url => 'http://dash.fiveruns.com' do |recipe|
104
- recipe.time :test_time, 'Test Time', :method => 'ActiverecordTest::TestEngine#entry'
105
- end
106
- Fiveruns::Dash.configure :app => '666', :ar_total_time => 'test_time' do |config|
107
- config.add_recipe :ruby
108
- config.add_recipe :activerecord
109
- config.add_recipe :tester
110
- end
111
- Fiveruns::Dash.session.start(true)
112
- end
113
- end
data/test/test_helper.rb DELETED
@@ -1,30 +0,0 @@
1
- RAILS_ENV='test'
2
- RAILS_ROOT=File.dirname(__FILE__)
3
- require 'test/unit'
4
- require 'logger'
5
- require 'rubygems'
6
-
7
- begin
8
- require 'shoulda'
9
- require 'flexmock/test_unit'
10
- require 'fake_web'
11
- rescue
12
- puts "Please install the Shoulda, FakeWeb and flexmock gems to run the Dash plugin tests."
13
- end
14
-
15
- require 'shoulda'
16
- require 'flexmock/test_unit'
17
-
18
- RAILS_DEFAULT_LOGGER=Logger.new(STDOUT)
19
- require 'active_record'
20
- require 'action_controller'
21
- require 'action_controller/test_process'
22
- require 'action_controller/test_case'
23
- require 'action_view'
24
-
25
- $:.unshift(File.dirname(__FILE__) << '/../lib')
26
- $:.unshift(File.dirname(__FILE__) << '/../../fiveruns_dash/lib')
27
-
28
- class Test::Unit::TestCase
29
-
30
- end
data/version.yml DELETED
@@ -1,4 +0,0 @@
1
- ---
2
- :major: 0
3
- :minor: 7
4
- :patch: 8