Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Prepare setup per request.

  • Loading branch information...
commit f928b59d75cf80f3b194e1c458ba592fd79a8b62 1 parent 3866c34
@josevalim josevalim authored
View
2  Gemfile
@@ -6,4 +6,4 @@ gem "webrat", "0.7.0"
if RUBY_VERSION < '1.9'
gem "ruby-debug", ">= 0.10.3"
-end
+end
View
3  Rakefile
@@ -6,9 +6,10 @@ require "rake/rdoctask"
require "fileutils"
require File.expand_path("../lib/rails_metrics/version", __FILE__)
-desc "Default: run unit tests."
+desc "Default: run unit tests"
task :default => :test
+desc "Prepare environment for tests"
task :prepare do
FileUtils.cd File.expand_path("../test/dummy", __FILE__)
system("rake db:create:all")
View
8 lib/rails_metrics.rb
@@ -3,6 +3,7 @@
module RailsMetrics
autoload :AsyncConsumer, 'rails_metrics/async_consumer'
+ autoload :Middleware, 'rails_metrics/middleware'
autoload :Mute, 'rails_metrics/mute'
autoload :PayloadParser, 'rails_metrics/payload_parser'
autoload :Store, 'rails_metrics/store'
@@ -28,11 +29,6 @@ def self.set_store(&block)
# Place holder for the store
def self.store; end
- # Instantiate the store and call store!
- def self.store!(args)
- self.store.new.store!(args)
- end
-
# Allow you to specify a condition to ignore a notification based
# on its name and/or payload. For example, if you want to ignore
# all notifications with empty payload, one can do:
@@ -63,7 +59,7 @@ def self.ignore_patterns
# Holds the queue which store stuff in the database.
def self.async_consumer
- @@async_consumer ||= AsyncConsumer.new { |args| RailsMetrics.store!(args) }
+ @@async_consumer ||= AsyncConsumer.new { |args| RailsMetrics.store.new.store!(args) }
end
# Wait until the async queue is consumed.
View
2  lib/rails_metrics/engine.rb
@@ -3,7 +3,7 @@ class Engine < ::Rails::Engine
engine_name :rails_metrics
# Add middleware
- config.middleware.use RailsMetrics::Mute::Middleware
+ config.middleware.use RailsMetrics::Middleware
# Initialize configure parameters
config.rails_metrics.ignore_lambdas = {}
View
22 lib/rails_metrics/middleware.rb
@@ -0,0 +1,22 @@
+module RailsMetrics
+ class Middleware
+ include Mute
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ if env["PATH_INFO"] =~ /^\/rails_metrics/
+ mute_metrics! do
+ @app.call(env)
+ end
+ else
+ ActiveSupport::Notifications.instrument "rails_metrics.request",
+ :path => env["PATH_INFO"], :method => env["REQUEST_METHOD"] do
+ @app.call(env)
+ end
+ end
+ end
+ end
+end
View
18 lib/rails_metrics/mute.rb
@@ -34,23 +34,5 @@ def self.mute_class_method!(object, method)
def self.blacklist
Thread.current[:rails_metrics_blacklist] ||= []
end
-
- class Middleware
- include Mute
-
- def initialize(app)
- @app = app
- end
-
- def call(env)
- if env["PATH_INFO"] =~ /^\/rails_metrics/
- mute_metrics! do
- @app.call(env)
- end
- else
- @app.call(env)
- end
- end
- end
end
end
View
65 lib/rails_metrics/payload_parser.rb
@@ -1,40 +1,36 @@
module RailsMetrics
- # Usually the payload for a given notification contains a lot of information,
- # as backtrace, controllers, response bodies and so on, and we don't need to
- # store all this data in the database.
+ # ActiveSupport::Notifications usually comes with extra information as the
+ # SQL query, response status and many others. This information is called payload.
#
- # So, by default, RailsMetrics does not store any payload in the database, unless
- # you configure it. To do that, you simply need to call +add+:
+ # By default, RailsMetrics stores the whole payload in the database but it allows
+ # you to manipulate it or even ignore some through the add and ignore methods.
#
- # RailsMetrics::PayloadParser.add "active_record.sql"
+ # For example, "activerecord.sql" has as paylaod a hash with :name (like "Product
+ # Load"), the :sql to be performed and the :connection_id. We can remove the connection
+ # from the hash by simply providing :except:
#
- # "activerecord.sql" has as paylaod the :name (like "Product Load") and the :sql
- # to be performed. And now both of them will be stored in the database. You can
- # also select or remove any information from the hash through :slice and :except
- # options:
- #
- # RailsMetrics::PayloadParser.add "active_record.sql", :slice => :sql
+ # RailsMetrics::PayloadParser.add "active_record.sql", :except => :name
#
- # Or:
+ # Or, we could also:
#
- # RailsMetrics::PayloadParser.add "active_record.sql", :except => :name
+ # RailsMetrics::PayloadParser.add "active_record.sql", :slice => [:name, :sql]
#
# Finally, in some cases manipulating the hash is not enough and you might need
- # to customize it further, as in "action_controller.process_action". In such
- # cases, you can pass a block which will receive the payload as argument:
+ # to customize it further, as in "action_view.render_template". You can do
+ # that by giving a block which will receive the payload as argument:
#
- # RailsMetrics::PayloadParser.add "action_controler.process_action" do |payload|
- # { :method => payload[:controller].request.method }
+ # RailsMetrics::PayloadParser.add "action_view.render_template" do |payload|
+ # payload = payload.dup
+ # payload[:template] = payload[:template].gsub("RAILS_ROOT", Rails.root)
+ # payload
# end
#
# ATTENTION: if you need to modify the payload or any of its values, be sure to
- # .dup if first.
+ # .dup if first, as in the example above.
#
- # RailsMetrics all come with default parsers (defined below), but if you want to gather
- # some info for other libraries (for example, paperclip) you need to define the parser
- # on your own. You can remove any parser whenever you want:
+ # If you want to ignore any payload, you can use the ignore method:
#
- # RailsMetrics::PayloadParser.delete "active_record.sql"
+ # RailsMetrics::PayloadParser.ignore "active_record.sql"
#
module PayloadParser
# Holds the parsers used by RailsMetrics.
@@ -57,14 +53,14 @@ def self.add(*names, &block)
elsif options.present?
options.to_a.flatten
else
- :all
+ true
end
end
end
# Delete a previous parser
- def self.delete(*names)
- names.each { |name| parsers.delete(name.to_s) }
+ def self.ignore(*names)
+ names.each { |name| parsers[name.to_s] = false }
end
# Filter the given payload based on the name given and configured parsers
@@ -75,8 +71,10 @@ def self.filter(name, payload)
payload.send(*parser)
when Proc
parser.call(payload)
- when :all
+ when TrueClass, NilClass
payload
+ when FalseClass
+ nil
end
end
@@ -97,19 +95,11 @@ def self.prune_path(raw_path)
end if defined?(Gem)
# ActiveRecord
- add "active_record.sql"
-
- # ActionController - cache
- add "action_controller.write_fragment", "action_controller.read_fragment",
- "action_controller.exist_fragment?", "action_controller.expire_fragment",
- "action_controller.expire_page", "action_controller.write_page"
+ add "active_record.sql", :except => :connection_id
# ActionController - process action
add "action_controller.process_action", :except => :params
- add "action_controller.redirect_to", "action_controller.send_data",
- "action_controller.send_file"
-
# ActionView
add "action_view.render_template", "action_view.render_partial",
"action_view.render_collection" do |payload|
@@ -128,8 +118,5 @@ def self.prune_path(raw_path)
# ActionMailer
add "action_mailer.deliver", "action_mailer.receive", :except => :mail
-
- # ActiveResource
- add "active_resource.request"
end
end
View
4 test/dummy/db/migrate/20100106152343_create_metrics.rb
@@ -1,8 +1,4 @@
class CreateMetrics < ActiveRecord::Migration
- def self.connection
- Metric.connection
- end
-
def self.up
create_table :metrics do |t|
t.string :name
View
16 test/integration/all_metrics_test.rb
@@ -18,11 +18,23 @@ class AllMetricsTest < ActionController::IntegrationTest
assert_match /INSERT INTO/, metric.payload[:sql]
end
+ test "rails metrics middleware with instrumentation" do
+ get "/users"
+ wait!
+
+ request = Metric.last
+
+ assert_equal "rails_metrics.request", request.name
+ assert (request.duration >= 0)
+ assert_kind_of Time, request.started_at
+ assert_equal Hash[:path => "/users", :method => "GET"], request.payload
+ end
+
test "processed actions are added to RailsMetrics" do
get "/users"
wait!
- assert_equal 3, Metric.count
+ assert_equal 4, Metric.count
sql, template, action = Metric.all
assert_equal "action_view.render_template", template.name
@@ -69,7 +81,7 @@ class AllMetricsTest < ActionController::IntegrationTest
get "users/new"
wait!
- assert_equal 5, Metric.count
+ assert_equal 6, Metric.count
partial, exist, write, = Metric.all
assert_equal "action_view.render_partial", partial.name
View
14 test/payload_parser_test.rb
@@ -9,10 +9,9 @@ class PayloadParserTest < ActiveSupport::TestCase
RailsMetrics::PayloadParser.parsers.replace @_previous_parsers
end
- delegate :add, :delete, :filter, :to => RailsMetrics::PayloadParser
+ delegate :add, :ignore, :filter, :to => RailsMetrics::PayloadParser
- test "a parser without parameters returns payload as is" do
- add "rails_metrics.something"
+ test "a non registered parser returns payload as is" do
assert_equal Hash[:some => :info], filter("rails_metrics.something", :some => :info)
end
@@ -30,13 +29,8 @@ class PayloadParserTest < ActiveSupport::TestCase
assert_equal Hash[:foo => :bar], filter("rails_metrics.something", :some => :info)
end
- test "a non registered parser simply returns nil" do
- assert_nil filter("rails_metrics.something", :some => :info)
- end
-
- test "a parser can be deleted" do
- add "rails_metrics.something"
- delete "rails_metrics.something"
+ test "a parser can be ignored" do
+ ignore "rails_metrics.something"
assert_nil filter("rails_metrics.something", :some => :info)
end
end
View
9 test/store_test.rb
@@ -11,15 +11,6 @@ def store!(args=sample_args)
Metric.new.store!(args)
end
- setup do
- RailsMetrics::PayloadParser.add "rails_metrics.example"
- wait
- end
-
- teardown do
- RailsMetrics::PayloadParser.delete "rails_metrics.example"
- end
-
test "sets the name" do
assert_equal "rails_metrics.example", store!.name
end
Please sign in to comment.
Something went wrong with that request. Please try again.