influxdb-rails 1.0.0.beta3 → 1.0.1.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/rubocop.yml +18 -0
  4. data/.github/workflows/spec.yml +31 -0
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +40 -7
  7. data/CHANGELOG.md +42 -12
  8. data/README.md +277 -164
  9. data/Rakefile +0 -6
  10. data/gemfiles/Gemfile.rails-6.0.x +9 -0
  11. data/gemfiles/Gemfile.rails-6.1.x +9 -0
  12. data/influxdb-rails.gemspec +18 -9
  13. data/lib/influxdb-rails.rb +31 -81
  14. data/lib/influxdb/rails/configuration.rb +99 -194
  15. data/lib/influxdb/rails/context.rb +12 -28
  16. data/lib/influxdb/rails/helpers/rspec_matchers.rb +48 -0
  17. data/lib/influxdb/rails/metric.rb +39 -0
  18. data/lib/influxdb/rails/middleware/action_mailer_subscriber.rb +22 -0
  19. data/lib/influxdb/rails/middleware/active_job_subscriber.rb +67 -0
  20. data/lib/influxdb/rails/middleware/active_record_subscriber.rb +26 -0
  21. data/lib/influxdb/rails/middleware/block_instrumentation_subscriber.rb +24 -0
  22. data/lib/influxdb/rails/middleware/render_subscriber.rb +16 -10
  23. data/lib/influxdb/rails/middleware/request_subscriber.rb +23 -30
  24. data/lib/influxdb/rails/middleware/sql_subscriber.rb +19 -15
  25. data/lib/influxdb/rails/middleware/subscriber.rb +44 -20
  26. data/lib/influxdb/rails/railtie.rb +29 -35
  27. data/lib/influxdb/rails/sql/normalizer.rb +3 -3
  28. data/lib/influxdb/rails/tags.rb +33 -0
  29. data/lib/influxdb/rails/test_client.rb +13 -0
  30. data/lib/influxdb/rails/values.rb +24 -0
  31. data/lib/influxdb/rails/version.rb +1 -1
  32. data/lib/rails/generators/influxdb/influxdb_generator.rb +1 -1
  33. data/lib/rails/generators/influxdb/templates/initializer.rb +43 -9
  34. data/sample-dashboard/Dockerfile +24 -0
  35. data/sample-dashboard/README.md +74 -0
  36. data/sample-dashboard/Rakefile +9 -0
  37. data/sample-dashboard/Ruby On Rails Performance (per Action).json +1576 -0
  38. data/sample-dashboard/Ruby On Rails Performance (per Request).json +1053 -0
  39. data/sample-dashboard/Ruby On Rails Performance.json +2041 -0
  40. data/sample-dashboard/docker-compose.yml +34 -0
  41. data/sample-dashboard/provisioning/grafana-dashboards.yml +12 -0
  42. data/sample-dashboard/provisioning/grafana-datasource.yml +10 -0
  43. data/sample-dashboard/provisioning/performance-action.json +1576 -0
  44. data/sample-dashboard/provisioning/performance-request.json +1053 -0
  45. data/sample-dashboard/provisioning/performance.json +2041 -0
  46. data/spec/requests/action_controller_metrics_spec.rb +83 -0
  47. data/spec/requests/action_mailer_deliver_metrics_spec.rb +49 -0
  48. data/spec/requests/action_view_collection_metrics_spec.rb +66 -0
  49. data/spec/requests/action_view_partial_metrics_spec.rb +62 -0
  50. data/spec/requests/action_view_template_metrics_spec.rb +62 -0
  51. data/spec/requests/active_job_enqueue_metrics_spec.rb +65 -0
  52. data/spec/requests/active_job_perform_metrics_spec.rb +68 -0
  53. data/spec/requests/active_record_instantiation_metrics_spec.rb +65 -0
  54. data/spec/requests/active_record_sql_metrics_spec.rb +103 -0
  55. data/spec/requests/block_inistrumentation_spec.rb +64 -0
  56. data/spec/requests/context_spec.rb +27 -0
  57. data/spec/requests/logger_spec.rb +10 -0
  58. data/spec/spec_helper.rb +14 -4
  59. data/spec/support/broken_client.rb +11 -0
  60. data/spec/support/rails5/app.rb +51 -12
  61. data/spec/support/rails6/app.rb +83 -0
  62. data/spec/support/views/layouts/mailer.txt.erb +1 -0
  63. data/spec/support/views/{widgets → metrics}/_item.html.erb +0 -0
  64. data/spec/support/views/{widgets → metrics}/index.html.erb +0 -0
  65. data/spec/support/views/metrics/show.html.erb +4 -0
  66. data/spec/unit/block_instrumentation_spec.rb +18 -0
  67. data/spec/unit/configuration_spec.rb +47 -65
  68. metadata +141 -61
  69. data/.travis.yml +0 -37
  70. data/gemfiles/Gemfile.rails-4.2.x +0 -7
  71. data/gemfiles/Gemfile.rails-5.0.x +0 -7
  72. data/gemfiles/Gemfile.rails-5.1.x +0 -7
  73. data/lib/influxdb/rails/air_traffic_controller.rb +0 -41
  74. data/lib/influxdb/rails/backtrace.rb +0 -44
  75. data/lib/influxdb/rails/exception_presenter.rb +0 -94
  76. data/lib/influxdb/rails/instrumentation.rb +0 -34
  77. data/lib/influxdb/rails/logger.rb +0 -16
  78. data/lib/influxdb/rails/middleware/hijack_render_exception.rb +0 -16
  79. data/lib/influxdb/rails/middleware/hijack_rescue_action_everywhere.rb +0 -31
  80. data/lib/influxdb/rails/middleware/simple_subscriber.rb +0 -46
  81. data/lib/influxdb/rails/rack.rb +0 -24
  82. data/spec/controllers/widgets_controller_spec.rb +0 -15
  83. data/spec/integration/exceptions_spec.rb +0 -37
  84. data/spec/integration/integration_helper.rb +0 -1
  85. data/spec/integration/metrics_spec.rb +0 -28
  86. data/spec/shared_examples/tags.rb +0 -42
  87. data/spec/support/rails4/app.rb +0 -44
  88. data/spec/unit/backtrace_spec.rb +0 -85
  89. data/spec/unit/context_spec.rb +0 -40
  90. data/spec/unit/exception_presenter_spec.rb +0 -23
  91. data/spec/unit/influxdb_rails_spec.rb +0 -78
  92. data/spec/unit/middleware/render_subscriber_spec.rb +0 -92
  93. data/spec/unit/middleware/request_subscriber_spec.rb +0 -91
  94. data/spec/unit/middleware/sql_subscriber_spec.rb +0 -81
@@ -1 +0,0 @@
1
- require File.dirname(__FILE__) + "/../spec_helper"
@@ -1,28 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + "/integration_helper")
2
-
3
- RSpec.describe WidgetsController, type: :controller do
4
- render_views
5
-
6
- before do
7
- allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_environments).and_return(%w[development])
8
- end
9
-
10
- describe "in a normal request" do
11
- it "should result in attempts to write metrics via the client" do
12
- expect(InfluxDB::Rails.client).to receive(:write_point).exactly(6).times
13
- get :index
14
- end
15
-
16
- context "with sql reports enabled" do
17
- before do
18
- allow_any_instance_of(InfluxDB::Rails::Middleware::SqlSubscriber).to receive(:series_name).and_return("rails.sql")
19
- get :index # to not count ActiveRecord initialization
20
- end
21
-
22
- it "should result in attempts to write metrics via the client" do
23
- expect(InfluxDB::Rails.client).to receive(:write_point).exactly(7).times
24
- get :index
25
- end
26
- end
27
- end
28
- end
@@ -1,42 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.shared_examples_for "with additional tags" do |series_names|
4
- context "when tags_middleware is overwritten" do
5
- before do
6
- allow(config).to receive(:tags_middleware).and_return(tags_middleware)
7
- end
8
-
9
- let(:tags_middleware) { ->(tags) { tags.merge(static: "value") } }
10
-
11
- it "processes tags throught the middleware" do
12
- tags = data[:tags].merge(static: "value")
13
-
14
- series_names.each do |series_name|
15
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(series_name, include(tags: tags))
16
- end
17
-
18
- subject.call("unused", start, finish, "unused", payload)
19
- end
20
- end
21
-
22
- context "when tags are set in the current context" do
23
- let(:additional_tags) do
24
- { another: :value }
25
- end
26
-
27
- after do
28
- InfluxDB::Rails.current.reset
29
- end
30
-
31
- it "does include the tags" do
32
- InfluxDB::Rails.current.tags = additional_tags
33
- tags = data[:tags].merge(additional_tags)
34
-
35
- series_names.each do |series_name|
36
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(series_name, include(tags: tags))
37
- end
38
-
39
- subject.call("unused", start, finish, "unused", payload)
40
- end
41
- end
42
- end
@@ -1,44 +0,0 @@
1
- require "action_controller/railtie"
2
- require "active_record"
3
-
4
- app = Class.new(Rails::Application)
5
- app.config.secret_key_base = "1234567890abcdef1234567890abcdef"
6
- app.config.secret_token = "1234567890abcdef1234567890abcdef"
7
- app.config.session_store :cookie_store, key: "_myapp_session"
8
- app.config.active_support.deprecation = :log
9
- app.config.eager_load = false
10
- app.config.root = __dir__
11
- Rails.backtrace_cleaner.remove_silencers!
12
- app.initialize!
13
-
14
- app.routes.draw do
15
- resources :widgets
16
- end
17
-
18
- InfluxDB::Rails.configure do |config|
19
- end
20
-
21
- ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
22
- ActiveRecord::Schema.define do
23
- create_table :widgets, force: true do |t|
24
- t.string :title
25
-
26
- t.timestamps
27
- end
28
- end
29
-
30
- class Widget < ActiveRecord::Base; end
31
- class ApplicationController < ActionController::Base; end
32
- class WidgetsController < ApplicationController
33
- prepend_view_path File.join(__dir__, "..", "views")
34
-
35
- def index
36
- Widget.create!(title: "test")
37
- end
38
-
39
- def new
40
- 1 / 0
41
- end
42
- end
43
-
44
- Object.const_set(:ApplicationHelper, Module.new)
@@ -1,85 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe InfluxDB::Rails::Backtrace do
4
- before do
5
- @raw_backtrace = [
6
- "/var/www/current/app/models/foo.rb:10:in `bar'",
7
- "/var/www/current/app/models/foo.rb:19:in `baz'",
8
- "/var/www/current/app/models/foo.rb:32:in `<main>'"
9
- ]
10
-
11
- @backtrace = InfluxDB::Rails::Backtrace.new(@raw_backtrace)
12
- end
13
-
14
- it "should accept an exception into the initializer" do
15
- expect(@backtrace.lines).not_to be_empty
16
- expect(@backtrace.lines.count).to eq(3)
17
- end
18
-
19
- it "should correctly parse lines into their elements" do
20
- line = @backtrace.lines.first
21
-
22
- expect(line.file).to eq("/var/www/current/app/models/foo.rb")
23
- expect(line.number).to eq("10")
24
- expect(line.method).to eq("bar")
25
- end
26
-
27
- describe "#to_a" do
28
- it "should return an array of lines" do
29
- expect(@backtrace.to_a.is_a?(Array)).to be_truthy
30
- end
31
- end
32
-
33
- context "nil backtrace" do
34
- before do
35
- @raw_backtrace = nil
36
- @backtrace = InfluxDB::Rails::Backtrace.new(@raw_backtrace)
37
- end
38
-
39
- it "should accept an exception into the initializer" do
40
- expect(@backtrace.lines).to be_empty
41
- expect(@backtrace.lines.count).to eq(0)
42
- end
43
-
44
- describe "#to_a" do
45
- it "should return an array of lines" do
46
- expect(@backtrace.to_a.is_a?(Array)).to be_truthy
47
- end
48
- end
49
- end
50
-
51
- describe "backtrace filters" do
52
- before do
53
- InfluxDB::Rails.configure do |config|
54
- config.application_root = "/var/www/current"
55
- end
56
- end
57
-
58
- it "should apply a single default backtrace filter correctly" do
59
- filtered_backtrace = InfluxDB::Rails::Backtrace.new(@raw_backtrace)
60
-
61
- line = filtered_backtrace.lines.first
62
- expect(line.file).to eq("[APP_ROOT]/app/models/foo.rb")
63
- end
64
-
65
- it "should all default backtrace filters correctly" do
66
- extended_backtrace = @raw_backtrace.dup
67
- extended_backtrace << "#{Gem.path.first}/lib/foo_gem.rb:1:in `blah'"
68
-
69
- filtered_backtrace = InfluxDB::Rails::Backtrace.new(extended_backtrace)
70
- expect(filtered_backtrace.lines.first.file).to eq("[APP_ROOT]/app/models/foo.rb")
71
- expect(filtered_backtrace.lines.last.file).to eq("[GEM_ROOT]/lib/foo_gem.rb")
72
- end
73
-
74
- it "should allow the addition of custom backtrace filters" do
75
- InfluxDB::Rails.configure do |config|
76
- config.backtrace_filters << ->(line) { line.gsub(/foo/, "F00") }
77
- end
78
-
79
- filtered_backtrace = InfluxDB::Rails::Backtrace.new(@raw_backtrace)
80
-
81
- line = filtered_backtrace.lines.first
82
- expect(line.file).to eq("[APP_ROOT]/app/models/F00.rb")
83
- end
84
- end
85
- end
@@ -1,40 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe InfluxDB::Rails::Context do
4
- subject { described_class.new }
5
-
6
- describe "#controller" do
7
- it "does set and get" do
8
- subject.controller = "Controller"
9
- expect(subject.controller).to eq("Controller")
10
- end
11
- end
12
-
13
- describe "#action" do
14
- it "does get and set" do
15
- subject.action = "action"
16
- expect(subject.action).to eq("action")
17
- end
18
- end
19
-
20
- describe "#location" do
21
- before do
22
- subject.controller = "Controller"
23
- subject.action = "action"
24
- end
25
-
26
- it { expect(subject.location).to eq("Controller#action") }
27
- end
28
-
29
- describe "#reset" do
30
- before do
31
- subject.controller = "Controller"
32
- subject.action = "action"
33
- end
34
-
35
- it "does reset the location" do
36
- subject.reset
37
- expect(subject.location).to be_empty
38
- end
39
- end
40
- end
@@ -1,23 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe InfluxDB::Rails::ExceptionPresenter do
4
- before do
5
- begin
6
- 1 / 0
7
- rescue ZeroDivisionError => e
8
- @exception = e
9
- end
10
- end
11
-
12
- describe ".new" do
13
- it "should create a new ExceptionPresenter" do
14
- exception_presenter = InfluxDB::Rails::ExceptionPresenter.new(@exception)
15
- expect(exception_presenter).to be_a(InfluxDB::Rails::ExceptionPresenter)
16
- end
17
-
18
- it "should accept an exception as a parameter" do
19
- exception_presenter = InfluxDB::Rails::ExceptionPresenter.new(@exception)
20
- expect(exception_presenter).not_to be_nil
21
- end
22
- end
23
- end
@@ -1,78 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe InfluxDB::Rails do
4
- before do
5
- InfluxDB::Rails.configure do |config|
6
- config.application_name = "my-rails-app"
7
- config.ignored_environments = []
8
- config.time_precision = "ms"
9
- end
10
- end
11
-
12
- describe ".current_timestamp" do
13
- let(:timestamp) { 1_513_009_229_111 }
14
-
15
- it "should return the current timestamp in the configured precision" do
16
- expect(Process).to receive(:clock_gettime)
17
- .with(Process::CLOCK_REALTIME, :millisecond)
18
- .and_return(timestamp)
19
-
20
- expect(InfluxDB::Rails.current_timestamp).to eq(timestamp)
21
- end
22
- end
23
-
24
- describe ".ignorable_exception?" do
25
- it "should be true for exception types specified in the configuration" do
26
- class DummyException < RuntimeError; end
27
- exception = DummyException.new
28
-
29
- InfluxDB::Rails.configure do |config|
30
- config.ignored_exceptions << "DummyException"
31
- end
32
-
33
- expect(InfluxDB::Rails.ignorable_exception?(exception)).to be_truthy
34
- end
35
-
36
- it "should be true for exception types specified in the configuration" do
37
- exception = ActionController::RoutingError.new("foo")
38
- expect(InfluxDB::Rails.ignorable_exception?(exception)).to be_truthy
39
- end
40
-
41
- it "should be false for valid exceptions" do
42
- exception = ZeroDivisionError.new
43
- expect(InfluxDB::Rails.ignorable_exception?(exception)).to be_falsey
44
- end
45
- end
46
-
47
- describe "rescue" do
48
- it "should transmit an exception when passed" do
49
- expect(InfluxDB::Rails.client).to receive(:write_point)
50
-
51
- InfluxDB::Rails.rescue do
52
- raise ArgumentError, "wrong"
53
- end
54
- end
55
-
56
- it "should also raise the exception when in an ignored environment" do
57
- InfluxDB::Rails.configure do |config|
58
- config.ignored_environments = %w[development test]
59
- end
60
-
61
- expect do
62
- InfluxDB::Rails.rescue do
63
- raise ArgumentError, "wrong"
64
- end
65
- end.to raise_error(ArgumentError)
66
- end
67
- end
68
-
69
- describe "rescue_and_reraise" do
70
- it "should transmit an exception when passed" do
71
- expect(InfluxDB::Rails.client).to receive(:write_point)
72
-
73
- expect do
74
- InfluxDB::Rails.rescue_and_reraise { raise ArgumentError, "wrong" }
75
- end.to raise_error(ArgumentError)
76
- end
77
- end
78
- end
@@ -1,92 +0,0 @@
1
- require "spec_helper"
2
- require "shared_examples/tags"
3
-
4
- RSpec.describe InfluxDB::Rails::Middleware::RenderSubscriber do
5
- let(:config) { InfluxDB::Rails::Configuration.new }
6
- let(:logger) { double(:logger) }
7
-
8
- before do
9
- allow(config).to receive(:application_name).and_return("my-rails-app")
10
- allow(config).to receive(:ignored_environments).and_return([])
11
- allow(config).to receive(:time_precision).and_return("ms")
12
- end
13
-
14
- describe ".call" do
15
- let(:start) { Time.at(1_517_567_368) }
16
- let(:finish) { Time.at(1_517_567_370) }
17
- let(:series_name) { "series_name" }
18
- let(:payload) { { identifier: "index.html", count: 43, cache_hits: 42 } }
19
- let(:data) do
20
- {
21
- values: {
22
- value: 2000,
23
- count: 43,
24
- cache_hits: 42
25
- },
26
- tags: {
27
- filename: "index.html",
28
- location: "Foo#bar",
29
- },
30
- timestamp: 1_517_567_370_000
31
- }
32
- end
33
-
34
- subject { described_class.new(config, series_name) }
35
-
36
- before do
37
- InfluxDB::Rails.current.controller = "Foo"
38
- InfluxDB::Rails.current.action = "bar"
39
- end
40
-
41
- after do
42
- InfluxDB::Rails.current.reset
43
- end
44
-
45
- context "successfully" do
46
- it "writes to InfluxDB" do
47
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
48
- series_name, data
49
- )
50
- subject.call("name", start, finish, "id", payload)
51
- end
52
-
53
- it_behaves_like "with additional tags", ["series_name"]
54
-
55
- context "with an empty value" do
56
- before do
57
- payload[:count] = nil
58
- data[:values].delete(:count)
59
- end
60
-
61
- it "does not write empty value" do
62
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
63
- series_name, data
64
- )
65
- subject.call("name", start, finish, "id", payload)
66
- end
67
- end
68
-
69
- context "disabled" do
70
- subject { described_class.new(config, nil) }
71
-
72
- it "does not write a data point" do
73
- expect_any_instance_of(InfluxDB::Client).not_to receive(:write_point)
74
- subject.call("name", start, finish, "id", payload)
75
- end
76
- end
77
- end
78
-
79
- context "unsuccessfully" do
80
- before do
81
- allow(config).to receive(:logger).and_return(logger)
82
- InfluxDB::Rails.configuration = config
83
- end
84
-
85
- it "does log exceptions" do
86
- allow_any_instance_of(InfluxDB::Client).to receive(:write_point).and_raise("boom")
87
- expect(logger).to receive(:error).with(/boom/)
88
- subject.call("name", start, finish, "id", payload)
89
- end
90
- end
91
- end
92
- end
@@ -1,91 +0,0 @@
1
- require "spec_helper"
2
- require "shared_examples/tags"
3
-
4
- RSpec.describe InfluxDB::Rails::Middleware::RequestSubscriber do
5
- let(:config) { InfluxDB::Rails::Configuration.new }
6
-
7
- before do
8
- allow(config).to receive(:time_precision).and_return("ms")
9
- end
10
-
11
- subject { described_class.new(config) }
12
-
13
- describe "#call" do
14
- let(:start) { Time.at(1_517_567_368) }
15
- let(:finish) { Time.at(1_517_567_370) }
16
- let(:payload) { { view_runtime: 2, db_runtime: 2, controller: "MyController", action: "show", method: "GET", format: "*/*", status: 200 } }
17
- let(:data) do
18
- {
19
- values: {
20
- value: 2
21
- },
22
- tags: {
23
- method: "MyController#show",
24
- status: 200,
25
- format: "*/*",
26
- http_method: "GET",
27
- server: Socket.gethostname,
28
- app_name: "my-rails-app",
29
- },
30
- timestamp: 1_517_567_370_000
31
- }
32
- end
33
-
34
- context "application_name is set" do
35
- before do
36
- allow(config).to receive(:application_name).and_return("my-rails-app")
37
- end
38
-
39
- it "sends metrics with taggings and timestamps" do
40
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
41
- "rails.controller", data.merge(values: { value: 2000 })
42
- )
43
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.view", data)
44
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.db", data)
45
-
46
- subject.call("unused", start, finish, "unused", payload)
47
- end
48
-
49
- it_behaves_like "with additional tags", ["rails.controller", "rails.view", "rails.db"]
50
- end
51
-
52
- context "application_name is nil" do
53
- before do
54
- allow(config).to receive(:application_name).and_return(nil)
55
- end
56
-
57
- it "does not add the app_name tag to metrics" do
58
- tags = {
59
- method: "MyController#show",
60
- status: 200,
61
- format: "*/*",
62
- http_method: "GET",
63
- server: Socket.gethostname,
64
- }
65
-
66
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
67
- "rails.controller", data.merge(values: { value: 2000 }, tags: tags)
68
- )
69
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.view", data.merge(tags: tags))
70
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.db", data.merge(tags: tags))
71
-
72
- subject.call("unused", start, finish, "unused", payload)
73
- end
74
- end
75
-
76
- context "not successfull" do
77
- let(:logger) { double(:logger) }
78
-
79
- before do
80
- allow(config).to receive(:logger).and_return(logger)
81
- InfluxDB::Rails.configuration = config
82
- end
83
-
84
- it "does log an error" do
85
- allow_any_instance_of(InfluxDB::Client).to receive(:write_point).and_raise("boom")
86
- expect(logger).to receive(:error).with(/boom/)
87
- subject.call("name", start, finish, "id", payload)
88
- end
89
- end
90
- end
91
- end