influxdb-rails 1.0.0.beta2 → 1.0.1.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +11 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +6 -1
  5. data/.travis.yml +5 -12
  6. data/CHANGELOG.md +47 -12
  7. data/README.md +299 -140
  8. data/gemfiles/Gemfile.rails-6.0.x +10 -0
  9. data/influxdb-rails.gemspec +18 -9
  10. data/lib/influxdb-rails.rb +33 -77
  11. data/lib/influxdb/rails/configuration.rb +99 -194
  12. data/lib/influxdb/rails/context.rb +26 -0
  13. data/lib/influxdb/rails/helpers/rspec_matchers.rb +48 -0
  14. data/lib/influxdb/rails/metric.rb +39 -0
  15. data/lib/influxdb/rails/middleware/action_mailer_subscriber.rb +22 -0
  16. data/lib/influxdb/rails/middleware/active_job_subscriber.rb +67 -0
  17. data/lib/influxdb/rails/middleware/active_record_subscriber.rb +26 -0
  18. data/lib/influxdb/rails/middleware/block_instrumentation_subscriber.rb +24 -0
  19. data/lib/influxdb/rails/middleware/render_subscriber.rb +18 -6
  20. data/lib/influxdb/rails/middleware/request_subscriber.rb +24 -31
  21. data/lib/influxdb/rails/middleware/sql_subscriber.rb +18 -13
  22. data/lib/influxdb/rails/middleware/subscriber.rb +45 -15
  23. data/lib/influxdb/rails/railtie.rb +31 -35
  24. data/lib/influxdb/rails/sql/query.rb +5 -3
  25. data/lib/influxdb/rails/tags.rb +33 -0
  26. data/lib/influxdb/rails/test_client.rb +13 -0
  27. data/lib/influxdb/rails/values.rb +24 -0
  28. data/lib/influxdb/rails/version.rb +1 -1
  29. data/lib/rails/generators/influxdb/influxdb_generator.rb +1 -1
  30. data/lib/rails/generators/influxdb/templates/initializer.rb +39 -9
  31. data/sample-dashboard/Dockerfile +24 -0
  32. data/sample-dashboard/README.md +74 -0
  33. data/sample-dashboard/Rakefile +9 -0
  34. data/sample-dashboard/Ruby On Rails Performance (per Action).json +1576 -0
  35. data/sample-dashboard/Ruby On Rails Performance (per Request).json +1053 -0
  36. data/sample-dashboard/Ruby On Rails Performance.json +2041 -0
  37. data/sample-dashboard/docker-compose.yml +34 -0
  38. data/sample-dashboard/provisioning/grafana-dashboards.yml +12 -0
  39. data/sample-dashboard/provisioning/grafana-datasource.yml +10 -0
  40. data/sample-dashboard/provisioning/performance-action.json +1576 -0
  41. data/sample-dashboard/provisioning/performance-request.json +1053 -0
  42. data/sample-dashboard/provisioning/performance.json +2041 -0
  43. data/spec/requests/action_controller_metrics_spec.rb +83 -0
  44. data/spec/requests/action_mailer_deliver_metrics_spec.rb +49 -0
  45. data/spec/requests/action_view_collection_metrics_spec.rb +66 -0
  46. data/spec/requests/action_view_partial_metrics_spec.rb +62 -0
  47. data/spec/requests/action_view_template_metrics_spec.rb +62 -0
  48. data/spec/requests/active_job_enqueue_metrics_spec.rb +65 -0
  49. data/spec/requests/active_job_perform_metrics_spec.rb +68 -0
  50. data/spec/requests/active_job_perform_start_metrics_spec.rb +68 -0
  51. data/spec/requests/active_record_instantiation_metrics_spec.rb +65 -0
  52. data/spec/requests/active_record_sql_metrics_spec.rb +103 -0
  53. data/spec/requests/block_inistrumentation_spec.rb +64 -0
  54. data/spec/requests/context_spec.rb +27 -0
  55. data/spec/requests/logger_spec.rb +10 -0
  56. data/spec/spec_helper.rb +13 -4
  57. data/spec/support/broken_client.rb +11 -0
  58. data/spec/support/rails5/app.rb +49 -9
  59. data/spec/support/rails6/app.rb +84 -0
  60. data/spec/support/views/layouts/mailer.txt.erb +1 -0
  61. data/spec/support/views/{widgets → metrics}/_item.html.erb +0 -0
  62. data/spec/support/views/{widgets → metrics}/index.html.erb +0 -0
  63. data/spec/support/views/metrics/show.html.erb +4 -0
  64. data/spec/unit/block_instrumentation_spec.rb +18 -0
  65. data/spec/unit/configuration_spec.rb +47 -65
  66. data/spec/unit/sql/query_spec.rb +1 -0
  67. metadata +142 -57
  68. data/gemfiles/Gemfile.rails-4.2.x +0 -7
  69. data/gemfiles/Gemfile.rails-5.0.x +0 -7
  70. data/gemfiles/Gemfile.rails-5.1.x +0 -7
  71. data/lib/influxdb/rails/air_traffic_controller.rb +0 -41
  72. data/lib/influxdb/rails/backtrace.rb +0 -44
  73. data/lib/influxdb/rails/exception_presenter.rb +0 -94
  74. data/lib/influxdb/rails/instrumentation.rb +0 -34
  75. data/lib/influxdb/rails/logger.rb +0 -16
  76. data/lib/influxdb/rails/middleware/hijack_render_exception.rb +0 -16
  77. data/lib/influxdb/rails/middleware/hijack_rescue_action_everywhere.rb +0 -31
  78. data/lib/influxdb/rails/middleware/simple_subscriber.rb +0 -46
  79. data/lib/influxdb/rails/rack.rb +0 -24
  80. data/spec/controllers/widgets_controller_spec.rb +0 -15
  81. data/spec/integration/exceptions_spec.rb +0 -37
  82. data/spec/integration/integration_helper.rb +0 -1
  83. data/spec/integration/metrics_spec.rb +0 -28
  84. data/spec/support/rails4/app.rb +0 -44
  85. data/spec/unit/backtrace_spec.rb +0 -85
  86. data/spec/unit/exception_presenter_spec.rb +0 -23
  87. data/spec/unit/influxdb_rails_spec.rb +0 -78
  88. data/spec/unit/middleware/render_subscriber_spec.rb +0 -90
  89. data/spec/unit/middleware/request_subscriber_spec.rb +0 -106
  90. data/spec/unit/middleware/sql_subscriber_spec.rb +0 -79
@@ -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,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,90 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe InfluxDB::Rails::Middleware::RenderSubscriber do
4
- let(:config) { InfluxDB::Rails::Configuration.new }
5
- let(:logger) { double(:logger) }
6
-
7
- before do
8
- allow(config).to receive(:application_name).and_return("my-rails-app")
9
- allow(config).to receive(:ignored_environments).and_return([])
10
- allow(config).to receive(:time_precision).and_return("ms")
11
- end
12
-
13
- describe ".call" do
14
- let(:start_time) { Time.at(1_517_567_368) }
15
- let(:finish_time) { Time.at(1_517_567_370) }
16
- let(:series_name) { "series_name" }
17
- let(:payload) { { identifier: "index.html", count: 43, cache_hits: 42 } }
18
- let(:result) do
19
- {
20
- values: {
21
- value: 2000
22
- },
23
- tags: {
24
- filename: "index.html",
25
- location: "Foo#bar",
26
- count: 43,
27
- cache_hits: 42
28
- },
29
- timestamp: 1_517_567_370_000
30
- }
31
- end
32
-
33
- subject { described_class.new(config, series_name) }
34
-
35
- before do
36
- Thread.current[:_influxdb_rails_controller] = "Foo"
37
- Thread.current[:_influxdb_rails_action] = "bar"
38
- end
39
-
40
- after do
41
- Thread.current[:_influxdb_rails_action] = nil
42
- Thread.current[:_influxdb_rails_controller] = nil
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, result
49
- )
50
- subject.call("name", start_time, finish_time, "id", payload)
51
- end
52
-
53
- context "with empty tags" do
54
- before do
55
- payload[:count] = nil
56
- result[:tags].delete(:count)
57
- end
58
-
59
- it "does not write empty tags" do
60
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
61
- series_name, result
62
- )
63
- subject.call("name", start_time, finish_time, "id", payload)
64
- end
65
- end
66
-
67
- context "disabled" do
68
- subject { described_class.new(config, nil) }
69
-
70
- it "does not write a data point" do
71
- expect_any_instance_of(InfluxDB::Client).not_to receive(:write_point)
72
- subject.call("name", start_time, finish_time, "id", payload)
73
- end
74
- end
75
- end
76
-
77
- context "unsuccessfully" do
78
- before do
79
- allow(config).to receive(:logger).and_return(logger)
80
- InfluxDB::Rails.configuration = config
81
- end
82
-
83
- it "does log exceptions" do
84
- allow_any_instance_of(InfluxDB::Client).to receive(:write_point).and_raise("boom")
85
- expect(logger).to receive(:error).with(/boom/)
86
- subject.call("name", start_time, finish_time, "id", payload)
87
- end
88
- end
89
- end
90
- end
@@ -1,106 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe InfluxDB::Rails::Middleware::RequestSubscriber do
4
- let(:config) { InfluxDB::Rails::Configuration.new }
5
-
6
- before do
7
- allow(config).to receive(:time_precision).and_return("ms")
8
- end
9
-
10
- subject { described_class.new(config) }
11
-
12
- describe "#call" do
13
- let(:start) { Time.at(1_517_567_368) }
14
- let(:finish) { Time.at(1_517_567_370) }
15
- let(:payload) { { view_runtime: 2, db_runtime: 2, controller: "MyController", action: "show", method: "GET", format: "*/*", status: 200 } }
16
- let(:data) do
17
- {
18
- values: {
19
- value: 2
20
- },
21
- tags: {
22
- method: "MyController#show",
23
- status: 200,
24
- format: "*/*",
25
- http_method: "GET",
26
- server: Socket.gethostname,
27
- app_name: "my-rails-app",
28
- },
29
- timestamp: 1_517_567_370_000
30
- }
31
- end
32
-
33
- context "application_name is set" do
34
- before do
35
- allow(config).to receive(:application_name).and_return("my-rails-app")
36
- end
37
-
38
- it "sends metrics with taggings and timestamps" do
39
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
40
- "rails.controller", data.merge(values: { value: 2000 })
41
- )
42
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.view", data)
43
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.db", data)
44
-
45
- subject.call("unused", start, finish, "unused", payload)
46
- end
47
-
48
- context "when tags_middleware is overwritten" do
49
- before do
50
- allow(config).to receive(:tags_middleware).and_return(tags_middleware)
51
- end
52
-
53
- let(:tags_middleware) { ->(tags) { tags.merge(static: "value") } }
54
-
55
- it "processes tags throught the middleware" do
56
- tags = data[:tags].merge(static: "value")
57
-
58
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.controller", include(tags: tags))
59
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.view", include(tags: tags))
60
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.db", include(tags: tags))
61
-
62
- subject.call("unused", start, finish, "unused", payload)
63
- end
64
- end
65
- end
66
-
67
- context "application_name is nil" do
68
- before do
69
- allow(config).to receive(:application_name).and_return(nil)
70
- end
71
-
72
- it "does not add the app_name tag to metrics" do
73
- tags = {
74
- method: "MyController#show",
75
- status: 200,
76
- format: "*/*",
77
- http_method: "GET",
78
- server: Socket.gethostname,
79
- }
80
-
81
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
82
- "rails.controller", data.merge(values: { value: 2000 }, tags: tags)
83
- )
84
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.view", data.merge(tags: tags))
85
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with("rails.db", data.merge(tags: tags))
86
-
87
- subject.call("unused", start, finish, "unused", payload)
88
- end
89
- end
90
-
91
- context "not successfull" do
92
- let(:logger) { double(:logger) }
93
-
94
- before do
95
- allow(config).to receive(:logger).and_return(logger)
96
- InfluxDB::Rails.configuration = config
97
- end
98
-
99
- it "does log an error" do
100
- allow_any_instance_of(InfluxDB::Client).to receive(:write_point).and_raise("boom")
101
- expect(logger).to receive(:error).with(/boom/)
102
- subject.call("name", start, finish, "id", payload)
103
- end
104
- end
105
- end
106
- end
@@ -1,79 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe InfluxDB::Rails::Middleware::SqlSubscriber do
4
- let(:config) { InfluxDB::Rails::Configuration.new }
5
- let(:logger) { double(:logger) }
6
-
7
- before do
8
- allow(config).to receive(:application_name).and_return("my-rails-app")
9
- allow(config).to receive(:ignored_environments).and_return([])
10
- allow(config).to receive(:time_precision).and_return("ms")
11
- end
12
-
13
- describe ".call" do
14
- let(:start_time) { Time.at(1_517_567_368) }
15
- let(:finish_time) { Time.at(1_517_567_370) }
16
- let(:series_name) { "series_name" }
17
- let(:payload) { { sql: "SELECT * FROM POSTS WHERE id = 1", name: "Post Load", binds: %w[1 2 3] } }
18
- let(:result) do
19
- {
20
- values: {
21
- value: 2000,
22
- sql: "SELECT * FROM POSTS WHERE id = xxx"
23
- },
24
- tags: {
25
- location: "Foo#bar",
26
- operation: "SELECT",
27
- class_name: "Post",
28
- name: "Post Load",
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
- Thread.current[:_influxdb_rails_controller] = "Foo"
38
- Thread.current[:_influxdb_rails_action] = "bar"
39
- end
40
-
41
- after do
42
- Thread.current[:_influxdb_rails_action] = nil
43
- Thread.current[:_influxdb_rails_controller] = nil
44
- end
45
-
46
- context "successfully" do
47
- it "writes to InfluxDB" do
48
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
49
- series_name, result
50
- )
51
- subject.call("name", start_time, finish_time, "id", payload)
52
- end
53
-
54
- context "with not relevant queries" do
55
- before do
56
- payload[:sql] = "SHOW FULL FIELDS FROM `users`"
57
- end
58
-
59
- it "does not write to InfluxDB" do
60
- expect_any_instance_of(InfluxDB::Client).not_to receive(:write_point)
61
- subject.call("name", start_time, finish_time, "id", payload)
62
- end
63
- end
64
- end
65
-
66
- context "unsuccessfully" do
67
- before do
68
- allow(config).to receive(:logger).and_return(logger)
69
- InfluxDB::Rails.configuration = config
70
- end
71
-
72
- it "does log exceptions" do
73
- allow_any_instance_of(InfluxDB::Client).to receive(:write_point).and_raise("boom")
74
- expect(logger).to receive(:error).with(/boom/)
75
- subject.call("name", start_time, finish_time, "id", payload)
76
- end
77
- end
78
- end
79
- end