rails_metrics 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/CHANGELOG.rdoc +3 -0
  2. data/Gemfile +9 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +58 -0
  5. data/Rakefile +58 -0
  6. data/TODO.rdoc +1 -0
  7. data/app/controllers/rails_metrics_controller.rb +78 -0
  8. data/app/helpers/rails_metrics_helper.rb +161 -0
  9. data/app/views/layouts/rails_metrics.html.erb +21 -0
  10. data/app/views/rails_metrics/_request.html.erb +21 -0
  11. data/app/views/rails_metrics/_row.html.erb +23 -0
  12. data/app/views/rails_metrics/all.html.erb +25 -0
  13. data/app/views/rails_metrics/chart.html.erb +49 -0
  14. data/app/views/rails_metrics/index.html.erb +21 -0
  15. data/app/views/rails_metrics/show.html.erb +41 -0
  16. data/config/routes.rb +7 -0
  17. data/lib/generators/rails_metrics_generator.rb +40 -0
  18. data/lib/rails_metrics.rb +112 -0
  19. data/lib/rails_metrics/async_consumer.rb +54 -0
  20. data/lib/rails_metrics/engine.rb +29 -0
  21. data/lib/rails_metrics/middleware.rb +27 -0
  22. data/lib/rails_metrics/orm/active_record.rb +66 -0
  23. data/lib/rails_metrics/payload_parser.rb +131 -0
  24. data/lib/rails_metrics/store.rb +132 -0
  25. data/lib/rails_metrics/version.rb +3 -0
  26. data/public/images/rails_metrics/arrow_down.png +0 -0
  27. data/public/images/rails_metrics/arrow_up.png +0 -0
  28. data/public/images/rails_metrics/cancel.png +0 -0
  29. data/public/images/rails_metrics/chart_pie.png +0 -0
  30. data/public/images/rails_metrics/page_white_delete.png +0 -0
  31. data/public/images/rails_metrics/page_white_go.png +0 -0
  32. data/public/images/rails_metrics/tick.png +0 -0
  33. data/public/javascripts/rails_metrics/g.pie-min.js +6 -0
  34. data/public/javascripts/rails_metrics/g.raphael-min.js +5 -0
  35. data/public/javascripts/rails_metrics/raphael-min.js +5 -0
  36. data/public/stylesheets/rails_metrics.css +135 -0
  37. data/test/dummy/app/controllers/application_controller.rb +4 -0
  38. data/test/dummy/app/controllers/users_controller.rb +43 -0
  39. data/test/dummy/app/helpers/application_helper.rb +2 -0
  40. data/test/dummy/app/models/metric.rb +3 -0
  41. data/test/dummy/app/models/notification.rb +7 -0
  42. data/test/dummy/app/models/user.rb +2 -0
  43. data/test/dummy/config/application.rb +52 -0
  44. data/test/dummy/config/boot.rb +9 -0
  45. data/test/dummy/config/environment.rb +5 -0
  46. data/test/dummy/config/environments/development.rb +19 -0
  47. data/test/dummy/config/environments/production.rb +33 -0
  48. data/test/dummy/config/environments/test.rb +29 -0
  49. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  50. data/test/dummy/config/initializers/cookie_verification_secret.rb +7 -0
  51. data/test/dummy/config/initializers/session_store.rb +15 -0
  52. data/test/dummy/config/routes.rb +60 -0
  53. data/test/dummy/db/migrate/20100106152343_create_metrics.rb +17 -0
  54. data/test/dummy/db/migrate/20100108120821_create_users.rb +13 -0
  55. data/test/integration/instrumentation_test.rb +100 -0
  56. data/test/integration/navigation_test.rb +103 -0
  57. data/test/orm/active_record_test.rb +51 -0
  58. data/test/payload_parser_test.rb +36 -0
  59. data/test/rails_metrics_test.rb +43 -0
  60. data/test/store_test.rb +81 -0
  61. data/test/support/helpers.rb +16 -0
  62. data/test/support/instrumentation.rb +18 -0
  63. data/test/support/mock_store.rb +34 -0
  64. data/test/support/webrat/integrations/rails.rb +31 -0
  65. data/test/test_helper.rb +32 -0
  66. metadata +118 -0
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ class ActiveRecordTest < ActiveSupport::TestCase
4
+ setup do
5
+ Metric.delete_all
6
+ end
7
+
8
+ test "does not store own queries as notifications" do
9
+ Metric.all
10
+ wait
11
+ assert Metric.all.empty?
12
+ end
13
+
14
+ test "does not store queries other than SELECT, INSERT, UPDATE and DELETE" do
15
+ User.connection.send(:select, "SHOW tables;")
16
+ wait
17
+ assert Metric.all.empty?
18
+ end
19
+
20
+ test "serializes payload" do
21
+ metric = Metric.new
22
+ metric.configure(["metric", Time.now, Time.now, "id", {:foo => :bar}])
23
+ metric.save!
24
+ assert_equal Hash[:foo => :bar], metric.payload
25
+ end
26
+
27
+ test "is invalid when name is blank" do
28
+ metric = Metric.new
29
+ assert metric.invalid?
30
+ assert "can't be blank", metric.errors["name"].join
31
+ end
32
+
33
+ test "is invalid when started_at is blank" do
34
+ metric = Metric.new
35
+ assert metric.invalid?
36
+ assert "can't be blank", metric.errors["started_at"].join
37
+ end
38
+
39
+ test "is invalid when duration is blank" do
40
+ metric = Metric.new
41
+ assert metric.invalid?
42
+ assert "can't be blank", metric.errors["duration"].join
43
+ end
44
+
45
+ test "responds to all required named scopes" do
46
+ [ :by_name, :by_request_id, :latest,
47
+ :earliest, :slowest, :fastest, :requests ].each do |method|
48
+ assert_respond_to Metric, method
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ class PayloadParserTest < ActiveSupport::TestCase
4
+ setup do
5
+ @_previous_parsers = RailsMetrics::PayloadParser.parsers.dup
6
+ end
7
+
8
+ teardown do
9
+ RailsMetrics::PayloadParser.parsers.replace @_previous_parsers
10
+ end
11
+
12
+ delegate :add, :ignore, :filter, :to => RailsMetrics::PayloadParser
13
+
14
+ test "a non registered parser returns payload as is" do
15
+ assert_equal Hash[:some => :info], filter("rails_metrics.something", :some => :info)
16
+ end
17
+
18
+ test "a parser with hash converts into method calls" do
19
+ add "rails_metrics.something", :except => [:foo, :bar]
20
+ assert_equal Hash[:some => :info], filter("rails_metrics.something", :some => :info,
21
+ :foo => :baz, :bar => :baz)
22
+ end
23
+
24
+ test "a parser with a block calls the block with payload" do
25
+ add "rails_metrics.something" do |payload|
26
+ assert_equal Hash[:some => :info], payload
27
+ { :foo => :bar }
28
+ end
29
+ assert_equal Hash[:foo => :bar], filter("rails_metrics.something", :some => :info)
30
+ end
31
+
32
+ test "a parser can be ignored" do
33
+ ignore "rails_metrics.something"
34
+ assert_nil filter("rails_metrics.something", :some => :info)
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+ require 'test_helper'
2
+
3
+ class RailsMetricsTest < ActiveSupport::TestCase
4
+ setup do
5
+ RailsMetrics.set_store { MockStore }
6
+ MockStore.instances.clear
7
+ end
8
+
9
+ test "send instrumentation event to the specified store" do
10
+ instrument "rails_metrics.something"
11
+ wait
12
+
13
+ assert_equal 2, MockStore.instances.size
14
+ assert_equal "rails_metrics.something", MockStore.instances.first.name
15
+ end
16
+
17
+ test "does not send an event to the store if it matches an ignored pattern" do
18
+ RailsMetrics.ignore_patterns << /rails_metrics/
19
+
20
+ begin
21
+ instrument "rails_metrics.something"
22
+ wait
23
+ assert MockStore.instances.none? { |m| m.name == "rails_metrics.something" }
24
+ ensure
25
+ RailsMetrics.ignore_patterns.pop
26
+ end
27
+ end
28
+
29
+ test "does not send an event to the store if it was generated inside it" do
30
+ instrument "rails_metrics.kicker"
31
+ wait
32
+
33
+ assert_equal 2, MockStore.instances.size
34
+ assert MockStore.instances.first.kicked?
35
+ assert_equal "rails_metrics.kicker", MockStore.instances.first.name
36
+ end
37
+
38
+ test "does not send an event if not listening" do
39
+ ActiveSupport::Notifications.instrument "rails_metrics.kicker"
40
+ wait
41
+ assert_equal 0, MockStore.instances.size
42
+ end
43
+ end
@@ -0,0 +1,81 @@
1
+ require 'test_helper'
2
+
3
+ class StoreTest < ActiveSupport::TestCase
4
+ setup do
5
+ RailsMetrics.set_store { MockStore }
6
+ MockStore.instances.clear
7
+ end
8
+
9
+ def sample_args
10
+ time = Time.now
11
+ ["rails_metrics.example", time, time + 1, 1, { :some => :info }]
12
+ end
13
+
14
+ def store!(args=sample_args)
15
+ metric = Metric.new
16
+ metric.configure(args)
17
+ metric
18
+ end
19
+
20
+ test "sets the name" do
21
+ assert_equal "rails_metrics.example", store!.name
22
+ end
23
+
24
+ test "sets the duration" do
25
+ assert_equal 1000000, store!.duration
26
+ assert_equal 1000000, store!.duration_in_us
27
+ assert_equal 1000, store!.duration_in_ms
28
+ end
29
+
30
+ test "sets started at" do
31
+ assert_kind_of Time, store!.started_at
32
+ end
33
+
34
+ test "sets the payload" do
35
+ assert_equal Hash[:some => :info], store!.payload
36
+ end
37
+
38
+ test "nested instrumentations are saved nested" do
39
+ instrument "rails_metrics.parent" do
40
+ instrument "rails_metrics.child" do
41
+ end
42
+ end
43
+
44
+ instrument "rails_metrics.another"
45
+
46
+ assert_equal 5, MockStore.instances.size
47
+ child, parent, request, another, another_request = MockStore.instances
48
+
49
+ assert_equal request.id, request.request_id
50
+ assert_equal request.id, parent.request_id
51
+ assert_equal request.id, parent.parent_id
52
+ assert_equal request.id, child.request_id
53
+ assert_equal parent.id, child.parent_id
54
+
55
+ assert parent.parent_of?(child)
56
+ assert child.child_of?(parent)
57
+
58
+ assert !parent.parent_of?(another)
59
+ assert !another.parent_of?(parent)
60
+ assert !parent.child_of?(another)
61
+ assert !another.child_of?(parent)
62
+ end
63
+
64
+ test "tree can be created from nested instrumentations" do
65
+ instrument "rails_metrics.parent" do
66
+ instrument "rails_metrics.child" do
67
+ end
68
+ end
69
+
70
+ child, parent, request = MockStore.instances
71
+ root = RailsMetrics.store.mount_tree(MockStore.instances)
72
+
73
+ assert_equal "rails_metrics.child", child.name
74
+ assert_equal "rails_metrics.parent", parent.name
75
+ assert_equal "rack.request", request.name
76
+
77
+ assert root.rack_request?
78
+ assert [parent], root.children
79
+ assert [child], parent.children
80
+ end
81
+ end
@@ -0,0 +1,16 @@
1
+ class ActiveSupport::TestCase
2
+ # Execute the block setting the given values and restoring old values after
3
+ # the block is executed.
4
+ def swap(object, new_values)
5
+ old_values = {}
6
+ new_values.each do |key, value|
7
+ old_values[key] = object.send key
8
+ object.send :"#{key}=", value
9
+ end
10
+ yield
11
+ ensure
12
+ old_values.each do |key, value|
13
+ object.send :"#{key}=", value
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ class ActiveSupport::TestCase
2
+ def wait
3
+ RailsMetrics.wait
4
+ end
5
+
6
+ # Fake a request instrumentation.
7
+ def instrument(*args, &block)
8
+ if RailsMetrics.listening?
9
+ ActiveSupport::Notifications.instrument(*args, &block)
10
+ else
11
+ RailsMetrics.listen_request do
12
+ ActiveSupport::Notifications.instrument "rack.request" do
13
+ ActiveSupport::Notifications.instrument(*args, &block)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ class ActiveSupport::TestCase
2
+ class MockStore
3
+ include RailsMetrics::Store
4
+
5
+ attr_accessor :id, :name, :parent_id, :request_id, :started_at, :duration, :payload
6
+
7
+ def self.instances
8
+ @instances ||= []
9
+ end
10
+
11
+ def initialize
12
+ self.class.instances << self
13
+ end
14
+
15
+ def kicked?
16
+ @kicked || false
17
+ end
18
+
19
+ def new_record?
20
+ true
21
+ end
22
+
23
+ protected
24
+
25
+ def save_metric!
26
+ self.id ||= (rand * 1000).to_i
27
+
28
+ if self.name == "rails_metrics.kicker"
29
+ @kicked = true
30
+ ActiveSupport::Notifications.instrument("rails_metrics.inside_store")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ require 'webrat/core/elements/field'
2
+
3
+ module Webrat
4
+ Field.class_eval do
5
+ def parse_rails_request_params(params)
6
+ Rack::Utils.parse_nested_query(params)
7
+ end
8
+ end
9
+ end
10
+
11
+ module ActionController #:nodoc:
12
+ IntegrationTest.class_eval do
13
+ include Webrat::Methods
14
+ include Webrat::Matchers
15
+
16
+ # The Rails version of within supports passing in a model and Webrat
17
+ # will apply a scope based on Rails' dom_id for that model.
18
+ #
19
+ # Example:
20
+ # within User.last do
21
+ # click_link "Delete"
22
+ # end
23
+ def within(selector_or_object, &block)
24
+ if selector_or_object.is_a?(String)
25
+ super
26
+ else
27
+ super('#' + RecordIdentifier.dom_id(selector_or_object), &block)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ # Configure Rails Envinronment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ # To test RailsMetrics, you need to:
5
+ #
6
+ # 1) Install latest bundler with "gem install bundler"
7
+ # 2) bundle install
8
+ # 3) rake prepare
9
+ # 4) rake test
10
+ #
11
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
12
+ require "rails/test_help"
13
+
14
+ ActionMailer::Base.delivery_method = :test
15
+ ActionMailer::Base.perform_deliveries = true
16
+ ActionMailer::Base.default_url_options[:host] = "test.com"
17
+
18
+ Webrat.configure do |config|
19
+ config.mode = :rails
20
+ config.open_error_files = false
21
+ end
22
+
23
+ # Add support to load paths so we can overwrite broken webrat setup
24
+ $:.unshift File.expand_path('../support', __FILE__)
25
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
26
+
27
+ class ActiveSupport::TestCase
28
+ setup do
29
+ wait
30
+ RailsMetrics.set_store { Metric }
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_metrics
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - "Jos\xC3\xA9 Valim"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-15 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Metrics measurement for your app on top of ActiveSupport::Notifications
17
+ email: contact@engineyard.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - CHANGELOG.rdoc
26
+ - Gemfile
27
+ - MIT-LICENSE
28
+ - README.rdoc
29
+ - Rakefile
30
+ - TODO.rdoc
31
+ - app/controllers/rails_metrics_controller.rb
32
+ - app/helpers/rails_metrics_helper.rb
33
+ - app/views/layouts/rails_metrics.html.erb
34
+ - app/views/rails_metrics/_request.html.erb
35
+ - app/views/rails_metrics/_row.html.erb
36
+ - app/views/rails_metrics/all.html.erb
37
+ - app/views/rails_metrics/chart.html.erb
38
+ - app/views/rails_metrics/index.html.erb
39
+ - app/views/rails_metrics/show.html.erb
40
+ - config/routes.rb
41
+ - lib/generators/rails_metrics_generator.rb
42
+ - lib/rails_metrics.rb
43
+ - lib/rails_metrics/async_consumer.rb
44
+ - lib/rails_metrics/engine.rb
45
+ - lib/rails_metrics/middleware.rb
46
+ - lib/rails_metrics/orm/active_record.rb
47
+ - lib/rails_metrics/payload_parser.rb
48
+ - lib/rails_metrics/store.rb
49
+ - lib/rails_metrics/version.rb
50
+ - public/images/rails_metrics/arrow_down.png
51
+ - public/images/rails_metrics/arrow_up.png
52
+ - public/images/rails_metrics/cancel.png
53
+ - public/images/rails_metrics/chart_pie.png
54
+ - public/images/rails_metrics/page_white_delete.png
55
+ - public/images/rails_metrics/page_white_go.png
56
+ - public/images/rails_metrics/tick.png
57
+ - public/javascripts/rails_metrics/g.pie-min.js
58
+ - public/javascripts/rails_metrics/g.raphael-min.js
59
+ - public/javascripts/rails_metrics/raphael-min.js
60
+ - public/stylesheets/rails_metrics.css
61
+ has_rdoc: true
62
+ homepage: http://github.com/engineyard
63
+ licenses: []
64
+
65
+ post_install_message:
66
+ rdoc_options:
67
+ - --charset=UTF-8
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 1.3.5
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Metrics measurement for your app on top of ActiveSupport::Notifications
89
+ test_files:
90
+ - test/dummy/app/controllers/application_controller.rb
91
+ - test/dummy/app/controllers/users_controller.rb
92
+ - test/dummy/app/helpers/application_helper.rb
93
+ - test/dummy/app/models/metric.rb
94
+ - test/dummy/app/models/notification.rb
95
+ - test/dummy/app/models/user.rb
96
+ - test/dummy/config/application.rb
97
+ - test/dummy/config/boot.rb
98
+ - test/dummy/config/environment.rb
99
+ - test/dummy/config/environments/development.rb
100
+ - test/dummy/config/environments/production.rb
101
+ - test/dummy/config/environments/test.rb
102
+ - test/dummy/config/initializers/backtrace_silencers.rb
103
+ - test/dummy/config/initializers/cookie_verification_secret.rb
104
+ - test/dummy/config/initializers/session_store.rb
105
+ - test/dummy/config/routes.rb
106
+ - test/dummy/db/migrate/20100106152343_create_metrics.rb
107
+ - test/dummy/db/migrate/20100108120821_create_users.rb
108
+ - test/integration/instrumentation_test.rb
109
+ - test/integration/navigation_test.rb
110
+ - test/orm/active_record_test.rb
111
+ - test/payload_parser_test.rb
112
+ - test/rails_metrics_test.rb
113
+ - test/store_test.rb
114
+ - test/support/helpers.rb
115
+ - test/support/instrumentation.rb
116
+ - test/support/mock_store.rb
117
+ - test/support/webrat/integrations/rails.rb
118
+ - test/test_helper.rb