librato-rails 1.4.2 → 2.0.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.
Files changed (36) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG.md +3 -0
  3. data/README.md +52 -73
  4. data/lib/librato/rails/configuration.rb +22 -3
  5. data/lib/librato/rails/railtie.rb +1 -2
  6. data/lib/librato/rails/subscribers/cache.rb +5 -3
  7. data/lib/librato/rails/subscribers/controller.rb +15 -12
  8. data/lib/librato/rails/subscribers/job.rb +17 -8
  9. data/lib/librato/rails/subscribers/mail.rb +11 -8
  10. data/lib/librato/rails/subscribers/method.rb +7 -9
  11. data/lib/librato/rails/subscribers/render.rb +13 -9
  12. data/lib/librato/rails/subscribers/sql.rb +11 -11
  13. data/lib/librato/rails/subscribers/status.rb +7 -9
  14. data/lib/librato/rails/tracker.rb +1 -1
  15. data/lib/librato/rails/version.rb +1 -1
  16. data/test/dummy/app/controllers/instrument_action_controller.rb +4 -0
  17. data/test/dummy/app/mailers/user_mailer.rb +5 -1
  18. data/test/dummy/config/routes.rb +1 -0
  19. data/test/fixtures/config/empty.yml +1 -1
  20. data/test/fixtures/config/librato.yml +4 -3
  21. data/test/fixtures/config/simple.yml +0 -2
  22. data/test/integration/cache_test.rb +5 -5
  23. data/test/integration/custom_test.rb +4 -4
  24. data/test/integration/instrument_action_test.rb +71 -23
  25. data/test/integration/job_test.rb +13 -3
  26. data/test/integration/mail_test.rb +9 -1
  27. data/test/integration/render_test.rb +12 -12
  28. data/test/integration/request_test.rb +40 -25
  29. data/test/integration/sql_test.rb +17 -7
  30. data/test/support/integration_case.rb +5 -1
  31. data/test/unit/configuration_test.rb +16 -11
  32. metadata +80 -55
  33. metadata.gz.sig +0 -0
  34. checksums.yaml +0 -7
  35. checksums.yaml.gz.sig +0 -0
  36. data/lib/librato/rails/subscribers/action.rb +0 -39
@@ -4,21 +4,21 @@ module Librato
4
4
 
5
5
  # SQL
6
6
 
7
- ActiveSupport::Notifications.subscribe 'sql.active_record' do |*args|
7
+ ActiveSupport::Notifications.subscribe "sql.active_record" do |*args|
8
+
8
9
  payload = args.last
10
+ sql = payload[:sql].strip
9
11
 
10
12
  collector.group "rails.sql" do |s|
11
- # puts (payload[:name] || 'nil') + ":" + payload[:sql] + "\n\n"
12
- s.increment 'queries'
13
+ s.increment "queries"
14
+ s.increment "selects" if sql.starts_with?("SELECT")
15
+ s.increment "inserts" if sql.starts_with?("INSERT")
16
+ s.increment "updates" if sql.starts_with?("UPDATE")
17
+ s.increment "deletes" if sql.starts_with?("DELETE")
18
+ end # end group
13
19
 
14
- sql = payload[:sql].strip
15
- s.increment 'selects' if sql.starts_with?('SELECT')
16
- s.increment 'inserts' if sql.starts_with?('INSERT')
17
- s.increment 'updates' if sql.starts_with?('UPDATE')
18
- s.increment 'deletes' if sql.starts_with?('DELETE')
19
- end
20
- end
20
+ end # end subscribe
21
21
 
22
22
  end
23
23
  end
24
- end
24
+ end
@@ -2,19 +2,17 @@ module Librato
2
2
  module Rails
3
3
  module Subscribers
4
4
 
5
- # Controller Status
5
+ # ActionController Status
6
6
 
7
- ActiveSupport::Notifications.subscribe 'process_action.action_controller' do |*args|
7
+ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
8
8
 
9
9
  event = ActiveSupport::Notifications::Event.new(*args)
10
- status = event.payload[:status]
10
+ tags = { status: event.payload[:status] }
11
11
 
12
- unless status.blank?
13
- collector.group "rails.request.status" do |s|
14
- s.increment status
15
- s.increment "#{status.to_s[0]}xx"
16
- s.timing "#{status}.time", event.duration
17
- s.timing "#{status.to_s[0]}xx.time", event.duration
12
+ unless tags[:status].blank?
13
+ collector.group "rails.request" do |s|
14
+ s.increment "status", tags: tags, inherit_tags: true
15
+ s.timing "status.time", event.duration, tags: tags, inherit_tags: true
18
16
  end # end group
19
17
  end
20
18
 
@@ -10,4 +10,4 @@ module Librato
10
10
 
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -1,5 +1,5 @@
1
1
  module Librato
2
2
  module Rails
3
- VERSION = "1.4.2"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -14,6 +14,10 @@ class InstrumentActionController < ApplicationController
14
14
  render nothing: true
15
15
  end
16
16
 
17
+ def invalid_format
18
+ head :ok
19
+ end
20
+
17
21
  private
18
22
 
19
23
  def before
@@ -1,8 +1,12 @@
1
1
  class UserMailer < ActionMailer::Base
2
2
  default from: "from@librato-rails.com"
3
-
3
+
4
4
  def welcome_email(user)
5
5
  @user = user
6
6
  mail(:to => user.email, :subject => "Why Howdy!")
7
7
  end
8
+
9
+ def receive(email)
10
+ email
11
+ end
8
12
  end
@@ -19,6 +19,7 @@ Dummy::Application.routes.draw do
19
19
 
20
20
  get 'instrument/inst' => 'instrument_action#inst', :as => :instrument_action
21
21
  get 'instrument/not' => 'instrument_action#not', :as => :not_instrumented
22
+ get '/invalid_format' => 'instrument_action#invalid_format'
22
23
 
23
24
  get 'base/action_1' => 'base#action_1', :as => :base_action_1
24
25
  get 'base/action_2' => 'base#action_2', :as => :base_action_2
@@ -1,4 +1,4 @@
1
1
  test:
2
2
  user: 'test@bar.com'
3
3
  token: 'test key'
4
- log_level: ''
4
+ log_level: ''
@@ -3,11 +3,12 @@ test:
3
3
  token: <%= 'test api key' %>
4
4
  prefix: 'rails-test'
5
5
  flush_interval: 30
6
- source: 'custom-1'
7
- source_pids: false
6
+ tags:
7
+ region: "us-east-1"
8
+ az: "b"
8
9
  proxy: 'http://localhost:8080'
9
10
  suites: all
10
-
11
+
11
12
  production:
12
13
  user: 'live@bar.com'
13
14
  token: 'live api key'
@@ -1,5 +1,3 @@
1
1
  test:
2
2
  user: 'test@bar.com'
3
3
  token: <%= 'test api key' %>
4
-
5
-
@@ -5,35 +5,35 @@ class CacheTest < ActiveSupport::IntegrationCase
5
5
  test 'cache read' do
6
6
  visit cache_read_path
7
7
 
8
- assert_equal 1, counters["rails.cache.read"]
8
+ assert_equal 1, counters["rails.cache.read"][:value]
9
9
  assert_equal 1, aggregate["rails.cache.read.time"][:count]
10
10
  end
11
11
 
12
12
  test 'cache write' do
13
13
  visit cache_write_path
14
14
 
15
- assert_equal 1, counters["rails.cache.write"]
15
+ assert_equal 1, counters["rails.cache.write"][:value]
16
16
  assert_equal 1, aggregate["rails.cache.write.time"][:count]
17
17
  end
18
18
 
19
19
  test 'cache fetch_hit' do
20
20
  visit cache_fetch_hit_path
21
21
 
22
- assert_equal 1, counters["rails.cache.fetch_hit"]
22
+ assert_equal 1, counters["rails.cache.fetch_hit"][:value]
23
23
  assert_equal 1, aggregate["rails.cache.fetch_hit.time"][:count]
24
24
  end
25
25
 
26
26
  test 'cache generate' do
27
27
  visit cache_generate_path
28
28
 
29
- assert_equal 1, counters["rails.cache.generate"]
29
+ assert_equal 1, counters["rails.cache.generate"][:value]
30
30
  assert_equal 1, aggregate["rails.cache.generate.time"][:count]
31
31
  end
32
32
 
33
33
  test 'cache delete' do
34
34
  visit cache_delete_path
35
35
 
36
- assert_equal 1, counters["rails.cache.delete"]
36
+ assert_equal 1, counters["rails.cache.delete"][:value]
37
37
  assert_equal 1, aggregate["rails.cache.delete.time"][:count]
38
38
  end
39
39
 
@@ -5,8 +5,8 @@ class CustomTest < ActiveSupport::IntegrationCase
5
5
  test 'controller access' do
6
6
  visit custom_path
7
7
 
8
- assert_equal 1, counters['custom.visits']
9
- assert_equal 3, counters['custom.events']
8
+ assert_equal 1, counters['custom.visits'][:value]
9
+ assert_equal 3, counters['custom.events'][:value]
10
10
 
11
11
  assert_equal 12, aggregate['custom.timing'][:sum]
12
12
  assert_equal 2, aggregate['custom.timing'][:count]
@@ -15,7 +15,7 @@ class CustomTest < ActiveSupport::IntegrationCase
15
15
  test 'model class access' do
16
16
  visit custom_path
17
17
 
18
- assert_equal 3, counters['custom.model.lookups']
18
+ assert_equal 3, counters['custom.model.lookups'][:value]
19
19
  assert_equal 19.0, aggregate['custom.model.search'][:sum]
20
20
  assert_equal 2, aggregate['custom.model.search'][:count]
21
21
  end
@@ -23,7 +23,7 @@ class CustomTest < ActiveSupport::IntegrationCase
23
23
  test 'model instance access' do
24
24
  visit custom_path
25
25
 
26
- assert_equal 1, counters['custom.model.touch']
26
+ assert_equal 1, counters['custom.model.touch'][:value]
27
27
  end
28
28
 
29
29
  end
@@ -2,51 +2,99 @@ require 'test_helper'
2
2
 
3
3
  class InstrumentActionTest < ActiveSupport::IntegrationCase
4
4
 
5
- test 'instrument controller action' do
6
- visit instrument_action_path
7
-
8
- # puts aggregate.instance_variable_get(:@cache).queued.inspect
9
- # puts counters.instance_variable_get(:@cache).inspect
5
+ test "instrument controller action" do
6
+ tags = {
7
+ controller: "InstrumentActionController",
8
+ action: "inst",
9
+ format: "html"
10
+ }.merge(default_tags)
10
11
 
11
- source = 'InstrumentActionController.inst.html'
12
+ visit instrument_action_path
12
13
 
13
- base = 'rails.action.request'
14
+ base = "rails.request"
14
15
  timings = %w{time time.db time.view}
15
16
  timings.each do |t|
16
- assert_equal 1, aggregate.fetch("#{base}.#{t}", source: source)[:count]
17
+ assert_equal 1, aggregate.fetch("#{base}.#{t}", tags: tags)[:count]
17
18
  end
18
19
 
19
- assert_equal 1, counters.fetch("#{base}.total", source: source)
20
+ assert_equal 1, counters.fetch("#{base}.total", tags: tags)[:value]
20
21
  end
21
22
 
22
- test 'instrument all controller actions' do
23
+ test "instrument all controller actions" do
23
24
  visit base_action_1_path
24
25
  visit base_action_2_path
25
26
 
26
- metric = 'rails.action.request.time'
27
-
28
- assert_equal 1, aggregate.fetch(metric, source: 'BaseController.action_1.html')[:count]
29
- assert_equal 1, aggregate.fetch(metric, source: 'BaseController.action_2.html')[:count]
27
+ metric = "rails.request.time"
28
+
29
+ assert_equal 1, aggregate.fetch(metric,
30
+ tags: {
31
+ controller: "BaseController",
32
+ action: "action_1",
33
+ format: "html"
34
+ }.merge(default_tags))[:count]
35
+ assert_equal 1, aggregate.fetch(metric,
36
+ tags: {
37
+ controller: "BaseController",
38
+ action: "action_2",
39
+ format: "html"
40
+ }.merge(default_tags))[:count]
30
41
  end
31
42
 
32
- test 'instrument all controller actions for inherited controllers' do
43
+ test "instrument all controller actions for inherited controllers" do
33
44
  visit intermediate_action_1_path
34
45
  visit derived_action_1_path
35
46
  visit derived_action_2_path
36
47
 
37
- metric = 'rails.action.request.time'
38
-
39
- assert_equal 1, aggregate.fetch(metric, source: 'IntermediateController.action_1.html')[:count]
40
- assert_equal 1, aggregate.fetch(metric, source: 'DerivedController.action_1.html')[:count]
41
- assert_equal 1, aggregate.fetch(metric, source: 'DerivedController.action_2.html')[:count]
48
+ metric = "rails.request.time"
49
+
50
+ assert_equal 1, aggregate.fetch(metric,
51
+ tags: {
52
+ controller: "IntermediateController",
53
+ action: "action_1",
54
+ format: "html"
55
+ }.merge(default_tags))[:count]
56
+ assert_equal 1, aggregate.fetch(metric,
57
+ tags: {
58
+ controller: "DerivedController",
59
+ action: "action_1",
60
+ format: "html"
61
+ }.merge(default_tags))[:count]
62
+ assert_equal 1, aggregate.fetch(metric,
63
+ tags: {
64
+ controller: "DerivedController",
65
+ action: "action_2",
66
+ format: "html"
67
+ }.merge(default_tags))[:count]
42
68
  end
43
69
 
44
- test 'instrument all controller actions for all controllers' do
70
+ test "instrument all controller actions for all controllers" do
45
71
  visit not_instrumented_path
46
72
 
47
- metric = 'rails.action.request.time'
73
+ metric = "rails.request.time"
74
+
75
+ assert_equal 1, aggregate.fetch(metric,
76
+ tags: {
77
+ controller: "InstrumentActionController",
78
+ action: "not",
79
+ format: "html"
80
+ }.merge(default_tags))[:count]
81
+ end
82
+
83
+ test "instrument invalid format" do
84
+ Capybara.current_session.driver.header "Accept", "*/*"
85
+
86
+ visit "/invalid_format"
87
+
88
+ metric = "rails.request.time"
89
+
90
+ assert_equal 1, aggregate.fetch(metric,
91
+ tags: {
92
+ controller: "InstrumentActionController",
93
+ action: "invalid_format",
94
+ format: "all"
95
+ }.merge(default_tags))[:count]
48
96
 
49
- assert_equal 1, aggregate.fetch(metric, source: 'InstrumentActionController.not.html')[:count]
97
+ Capybara.current_session.driver.header "Accept", nil
50
98
  end
51
99
 
52
100
  end
@@ -3,16 +3,26 @@ require 'test_helper'
3
3
  class JobTest < ActiveSupport::IntegrationCase
4
4
  Librato::Rails::VersionSpecifier.supported(min: '4.2') do
5
5
  test 'jobs performed' do
6
+ tags = {
7
+ adapter: "inline_adapter",
8
+ job: "dummy_job"
9
+ }.merge(default_tags)
10
+
6
11
  DummyJob.perform_now
7
12
 
8
- assert_equal 1, counters['rails.job.perform']
9
- assert_equal 1, aggregate.fetch('rails.job.perform.time', source: 'DummyJob')[:count]
13
+ assert_equal 1, counters.fetch("rails.job.perform", tags: tags)[:value]
14
+ assert_equal 1, aggregate.fetch("rails.job.perform.time", tags: tags)[:count]
10
15
  end
11
16
 
12
17
  test 'jobs enqueued' do
18
+ tags = {
19
+ adapter: "inline_adapter",
20
+ job: "dummy_job"
21
+ }.merge(default_tags)
22
+
13
23
  DummyJob.perform_later
14
24
 
15
- assert_equal 1, counters['rails.job.enqueue']
25
+ assert_equal 1, counters.fetch("rails.job.enqueue", tags: tags)[:value]
16
26
  end
17
27
  end
18
28
  end
@@ -4,8 +4,16 @@ class MailTest < ActiveSupport::IntegrationCase
4
4
 
5
5
  test 'mail sent' do
6
6
  user = User.create!(:email => 'foo@foo.com', :password => 'wow')
7
+ tags = { mailer: "UserMailer" }.merge(default_tags)
7
8
  UserMailer.welcome_email(user).deliver
8
- assert_equal 1, counters["rails.mail.sent"]
9
+ assert_equal 1, counters.fetch("rails.mail.sent", tags: tags)[:value]
10
+ end
11
+
12
+ test "mail received" do
13
+ user = User.create!(email: "foo@foo.com", password: "foobar")
14
+ tags = { mailer: "UserMailer" }.merge(default_tags)
15
+ UserMailer.receive(user.email)
16
+ assert_equal 1, counters.fetch("rails.mail.received", tags: tags)[:value]
9
17
  end
10
18
 
11
19
  end
@@ -5,23 +5,23 @@ class RenderTest < ActiveSupport::IntegrationCase
5
5
  test 'render partial' do
6
6
  visit render_partial_path
7
7
 
8
- assert_equal 1, counters.fetch("rails.view.render_partial",
9
- source: 'render:first.html.erb')
10
- assert_equal 1, counters.fetch("rails.view.render_partial",
11
- source: 'render:second.html.erb')
12
- assert_equal 1, aggregate.fetch("rails.view.render_partial.time",
13
- source: 'render:first.html.erb')[:count]
14
- assert_equal 1, aggregate.fetch("rails.view.render_partial.time",
15
- source: 'render:second.html.erb')[:count]
8
+ assert_equal 1, counters.fetch("rails.view.render.partial",
9
+ tags: { partial: "render:first.html.erb" }.merge(default_tags))[:value]
10
+ assert_equal 1, counters.fetch("rails.view.render.partial",
11
+ tags: { partial: "render:second.html.erb" }.merge(default_tags))[:value]
12
+ assert_equal 1, aggregate.fetch("rails.view.render.partial.time",
13
+ tags: { partial: "render:first.html.erb" }.merge(default_tags))[:count]
14
+ assert_equal 1, aggregate.fetch("rails.view.render.partial.time",
15
+ tags: { partial: "render:second.html.erb" }.merge(default_tags))[:count]
16
16
  end
17
17
 
18
18
  test 'render template' do
19
19
  visit render_template_path
20
20
 
21
- assert_equal 1, counters.fetch("rails.view.render_template",
22
- source: 'render:template.html.erb')
23
- assert_equal 1, aggregate.fetch("rails.view.render_template.time",
24
- source: 'render:template.html.erb')[:count]
21
+ assert_equal 1, counters.fetch("rails.view.render.template",
22
+ tags: { template: "render:template.html.erb" }.merge(default_tags))[:value]
23
+ assert_equal 1, aggregate.fetch("rails.view.render.template.time",
24
+ tags: { template: "render:template.html.erb" }.merge(default_tags))[:count]
25
25
  end
26
26
 
27
27
  end
@@ -5,52 +5,67 @@ class RequestTest < ActiveSupport::IntegrationCase
5
5
  # Each request
6
6
 
7
7
  test 'increment total and status' do
8
+ tags_1 = {
9
+ controller: "HomeController",
10
+ action: "index",
11
+ format: "html"
12
+ }.merge(default_tags)
13
+
8
14
  visit root_path
9
15
 
10
- assert_equal 1, counters["rails.request.total"]
11
- assert_equal 1, counters["rails.request.status.200"]
12
- assert_equal 1, counters["rails.request.status.2xx"]
13
- assert_equal 1, counters["rails.request.method.get"]
16
+ assert_equal 1, counters.fetch("rails.request.total", tags: tags_1)[:value]
17
+ assert_equal 1, counters.fetch("rails.request.status", tags: { status: 200 }.merge(default_tags))[:value]
18
+ assert_equal 1, counters.fetch("rails.request.method", tags: { method: "get" }.merge(default_tags))[:value]
19
+
20
+ visit root_path
21
+
22
+ assert_equal 2, counters.fetch("rails.request.total", tags: tags_1)[:value]
23
+
24
+ tags_2 = {
25
+ controller: "StatusController",
26
+ action: "index",
27
+ format: "html"
28
+ }.merge(default_tags)
14
29
 
15
30
  visit '/status/204'
16
31
 
17
- assert_equal 2, counters["rails.request.total"]
18
- assert_equal 1, counters["rails.request.status.200"]
19
- assert_equal 1, counters["rails.request.status.204"]
20
- assert_equal 2, counters["rails.request.status.2xx"]
32
+ assert_equal 1, counters.fetch("rails.request.total", tags: tags_2)[:value]
33
+ assert_equal 1, counters.fetch("rails.request.status", tags: { status: 204 }.merge(default_tags))[:value]
21
34
  end
22
35
 
23
36
  test 'request times' do
37
+ tags = {
38
+ controller: "HomeController",
39
+ action: "index",
40
+ format: "html"
41
+ }.merge(default_tags)
42
+
24
43
  visit root_path
25
44
 
26
45
  # common for all paths
27
- assert_equal 1, aggregate["rails.request.time"][:count],
46
+ assert_equal 1, aggregate.fetch("rails.request.time", tags: tags)[:count],
28
47
  'should record total time'
29
- assert_equal 1, aggregate["rails.request.time.db"][:count],
48
+ assert_equal 1, aggregate.fetch("rails.request.time.db", tags: tags)[:count],
30
49
  'should record db time'
31
- assert_equal 1, aggregate["rails.request.time.view"][:count],
50
+ assert_equal 1, aggregate.fetch("rails.request.time.view", tags: tags)[:count],
32
51
  'should record view time'
33
52
 
34
53
  # status specific
35
- assert_equal 1, aggregate["rails.request.status.200.time"][:count]
36
- assert_equal 1, aggregate["rails.request.status.2xx.time"][:count]
54
+ assert_equal 1, aggregate.fetch("rails.request.status.time", tags: { status: 200 }.merge(default_tags))[:count]
37
55
 
38
56
  # http method specific
39
- assert_equal 1, aggregate["rails.request.method.get.time"][:count]
40
- end
41
-
42
- test 'track exceptions' do
43
- begin
44
- visit exception_path #rescue nil
45
- rescue RuntimeError => e
46
- raise unless e.message == 'test exception!'
47
- end
48
- assert_equal 1, counters["rails.request.exceptions"]
57
+ assert_equal 1, aggregate.fetch("rails.request.method.time", tags: { method: "get" }.merge(default_tags))[:count]
49
58
  end
50
59
 
51
60
  test 'track slow requests' do
61
+ tags = {
62
+ controller: "HomeController",
63
+ action: "slow",
64
+ format: "html"
65
+ }.merge(default_tags)
66
+
52
67
  visit slow_path
53
- assert_equal 1, counters["rails.request.slow"]
68
+ assert_equal 1, counters.fetch("rails.request.slow", tags: tags)[:value]
54
69
  end
55
70
 
56
- end
71
+ end