influxdb-rails 1.0.0 → 1.0.1.beta1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +11 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +1 -1
  5. data/.travis.yml +4 -7
  6. data/CHANGELOG.md +17 -0
  7. data/README.md +47 -5
  8. data/Rakefile +0 -6
  9. data/gemfiles/Gemfile.rails-5.0.x +2 -0
  10. data/gemfiles/Gemfile.rails-6.0.x +10 -0
  11. data/influxdb-rails.gemspec +5 -3
  12. data/lib/influxdb-rails.rb +11 -0
  13. data/lib/influxdb/rails/configuration.rb +8 -12
  14. data/lib/influxdb/rails/context.rb +6 -40
  15. data/lib/influxdb/rails/helpers/rspec_matchers.rb +48 -0
  16. data/lib/influxdb/rails/metric.rb +39 -0
  17. data/lib/influxdb/rails/middleware/active_job_subscriber.rb +67 -0
  18. data/lib/influxdb/rails/middleware/active_record_subscriber.rb +26 -0
  19. data/lib/influxdb/rails/middleware/block_instrumentation_subscriber.rb +24 -0
  20. data/lib/influxdb/rails/middleware/render_subscriber.rb +15 -16
  21. data/lib/influxdb/rails/middleware/request_subscriber.rb +16 -21
  22. data/lib/influxdb/rails/middleware/sql_subscriber.rb +18 -18
  23. data/lib/influxdb/rails/middleware/subscriber.rb +40 -27
  24. data/lib/influxdb/rails/railtie.rb +15 -18
  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/sample-dashboard/README.md +1 -1
  30. data/spec/requests/action_controller_metrics_spec.rb +83 -0
  31. data/spec/requests/action_view_collection_metrics_spec.rb +66 -0
  32. data/spec/requests/action_view_partial_metrics_spec.rb +62 -0
  33. data/spec/requests/action_view_template_metrics_spec.rb +62 -0
  34. data/spec/requests/active_job_enqueue_metrics_spec.rb +65 -0
  35. data/spec/requests/active_job_perform_metrics_spec.rb +68 -0
  36. data/spec/requests/active_job_perform_start_metrics_spec.rb +68 -0
  37. data/spec/requests/active_record_instantiation_metrics_spec.rb +65 -0
  38. data/spec/requests/active_record_sql_metrics_spec.rb +103 -0
  39. data/spec/requests/block_inistrumentation_spec.rb +64 -0
  40. data/spec/requests/context_spec.rb +27 -0
  41. data/spec/requests/logger_spec.rb +10 -0
  42. data/spec/spec_helper.rb +10 -4
  43. data/spec/support/broken_client.rb +11 -0
  44. data/spec/support/rails5/app.rb +32 -10
  45. data/spec/support/rails6/app.rb +70 -0
  46. data/spec/support/views/{widgets → metrics}/_item.html.erb +0 -0
  47. data/spec/support/views/{widgets → metrics}/index.html.erb +0 -0
  48. data/spec/support/views/metrics/show.html.erb +4 -0
  49. data/spec/unit/block_instrumentation_spec.rb +18 -0
  50. metadata +87 -37
  51. data/gemfiles/Gemfile.rails-4.2.x +0 -7
  52. data/lib/influxdb/rails/instrumentation.rb +0 -34
  53. data/lib/influxdb/rails/middleware/simple_subscriber.rb +0 -33
  54. data/spec/controllers/widgets_controller_spec.rb +0 -15
  55. data/spec/integration/integration_helper.rb +0 -1
  56. data/spec/integration/metrics_spec.rb +0 -27
  57. data/spec/shared_examples/data.rb +0 -61
  58. data/spec/support/rails4/app.rb +0 -48
  59. data/spec/unit/context_spec.rb +0 -40
  60. data/spec/unit/middleware/render_subscriber_spec.rb +0 -96
  61. data/spec/unit/middleware/request_subscriber_spec.rb +0 -103
  62. data/spec/unit/middleware/sql_subscriber_spec.rb +0 -108
@@ -1,61 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.shared_examples_for "with additional data" do
4
- context "values" do
5
- let(:additional_values) do
6
- { another: :value }
7
- end
8
-
9
- after do
10
- InfluxDB::Rails.current.reset
11
- end
12
-
13
- it "does include the tags" do
14
- InfluxDB::Rails.current.values = additional_values
15
-
16
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(config.measurement_name, hash_including(values: hash_including(another: :value)))
17
-
18
- subject.call("unused", start, finish, "unused", payload)
19
- end
20
- end
21
-
22
- context "tags" do
23
- context "when tags_middleware is overwritten" do
24
- before do
25
- allow(config).to receive(:tags_middleware).and_return(tags_middleware)
26
- end
27
-
28
- let(:tags_middleware) { ->(tags) { tags.merge(static: "value", nil: nil, empty: "") } }
29
-
30
- it "processes tags throught the middleware" do
31
- tags = data[:tags].merge(static: "value")
32
-
33
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(config.measurement_name, include(tags: tags))
34
-
35
- subject.call("unused", start, finish, "unused", payload)
36
- end
37
- end
38
-
39
- context "when tags are set in the current context" do
40
- let(:input) do
41
- { another: :value, nil: nil, empty: "" }
42
- end
43
- let(:output) do
44
- { another: :value }
45
- end
46
-
47
- after do
48
- InfluxDB::Rails.current.reset
49
- end
50
-
51
- it "does include the tags" do
52
- InfluxDB::Rails.current.tags = input
53
- tags = data[:tags].merge(output)
54
-
55
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(config.measurement_name, include(tags: tags))
56
-
57
- subject.call("unused", start, finish, "unused", payload)
58
- end
59
- end
60
- end
61
- end
@@ -1,48 +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
- before_action do
36
- InfluxDB::Rails.current.values = { key: :value }
37
- end
38
-
39
- def index
40
- Widget.create!(title: "test")
41
- end
42
-
43
- def new
44
- 1 / 0
45
- end
46
- end
47
-
48
- Object.const_set(:ApplicationHelper, Module.new)
@@ -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,96 +0,0 @@
1
- require "spec_helper"
2
- require "shared_examples/data"
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.client).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(:hook_name) { "render_partial.action_view" }
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
- hook: "render_partial",
30
- },
31
- timestamp: 1_517_567_370_000
32
- }
33
- end
34
-
35
- subject { described_class.new(config, hook_name) }
36
-
37
- before do
38
- InfluxDB::Rails.current.controller = "Foo"
39
- InfluxDB::Rails.current.action = "bar"
40
- end
41
-
42
- after do
43
- InfluxDB::Rails.current.reset
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
- config.measurement_name, data
50
- )
51
- subject.call("name", start, finish, "id", payload)
52
- end
53
-
54
- it_behaves_like "with additional data"
55
-
56
- context "with an empty value" do
57
- before do
58
- payload[:count] = nil
59
- data[:values].delete(:count)
60
- end
61
-
62
- it "does not write empty value" do
63
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
64
- config.measurement_name, data
65
- )
66
- subject.call("name", start, finish, "id", payload)
67
- end
68
- end
69
-
70
- context "disabled" do
71
- before do
72
- allow(config).to receive(:ignored_hooks).and_return(["render_partial.action_view"])
73
- end
74
-
75
- subject { described_class.new(config, nil) }
76
-
77
- it "does not write a data point" do
78
- expect_any_instance_of(InfluxDB::Client).not_to receive(:write_point)
79
- subject.call("name", start, finish, "id", payload)
80
- end
81
- end
82
- end
83
-
84
- context "unsuccessfully" do
85
- before do
86
- InfluxDB::Rails.configuration = config
87
- end
88
-
89
- it "does log exceptions" do
90
- allow_any_instance_of(InfluxDB::Client).to receive(:write_point).and_raise("boom")
91
- expect(::Rails.logger).to receive(:error).with(/boom/)
92
- subject.call("name", start, finish, "id", payload)
93
- end
94
- end
95
- end
96
- end
@@ -1,103 +0,0 @@
1
- require "spec_helper"
2
- require "shared_examples/data"
3
-
4
- RSpec.describe InfluxDB::Rails::Middleware::RequestSubscriber do
5
- let(:config) { InfluxDB::Rails::Configuration.new }
6
-
7
- before do
8
- allow(config.client).to receive(:time_precision).and_return("ms")
9
- allow(config).to receive(:environment).and_return("production")
10
- end
11
-
12
- subject { described_class.new(config, "process_action.action_controller") }
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(:payload) { { view_runtime: 2, db_runtime: 2, controller: "MyController", action: "show", method: "GET", format: "*/*", status: 200 } }
18
- let(:data) do
19
- {
20
- values: {
21
- controller: 2,
22
- started: InfluxDB.convert_timestamp(start.utc, config.client.time_precision),
23
- },
24
- tags: {
25
- method: "MyController#show",
26
- hook: "process_action",
27
- status: 200,
28
- format: "*/*",
29
- http_method: "GET",
30
- server: Socket.gethostname,
31
- app_name: "my-rails-app",
32
- },
33
- timestamp: 1_517_567_370_000
34
- }
35
- end
36
-
37
- context "application_name is set" do
38
- before do
39
- allow(config).to receive(:application_name).and_return("my-rails-app")
40
- end
41
-
42
- it "sends metrics with taggings and timestamps" do
43
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
44
- config.measurement_name, data.deep_merge(values: { controller: 2000, db: 2, view: 2 })
45
- )
46
-
47
- subject.call("unused", start, finish, "unused", payload)
48
- end
49
-
50
- it_behaves_like "with additional data", ["requests"]
51
- end
52
-
53
- context "application_name is nil" do
54
- let(:tags) do
55
- {
56
- method: "MyController#show",
57
- hook: "process_action",
58
- status: 200,
59
- format: "*/*",
60
- http_method: "GET",
61
- server: Socket.gethostname,
62
- }
63
- end
64
-
65
- before do
66
- allow(config).to receive(:application_name).and_return(nil)
67
- end
68
-
69
- it "does not add the app_name tag to metrics" do
70
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
71
- config.measurement_name, data.merge(tags: tags).deep_merge(values: { controller: 2000, db: 2, view: 2 })
72
- )
73
-
74
- subject.call("unused", start, finish, "unused", payload)
75
- end
76
- end
77
-
78
- context "not successfull" do
79
- before do
80
- InfluxDB::Rails.configuration = config
81
- end
82
-
83
- it "does log an error" do
84
- allow_any_instance_of(InfluxDB::Client).to receive(:write_point).and_raise("boom")
85
- expect(::Rails.logger).to receive(:error).with(/boom/)
86
- subject.call("name", start, finish, "id", payload)
87
- end
88
- end
89
-
90
- context "disabled" do
91
- before do
92
- allow(config).to receive(:ignored_hooks).and_return(["process_action.action_controller"])
93
- end
94
-
95
- subject { described_class.new(config, "process_action.action_controller") }
96
-
97
- it "does not write a data point" do
98
- expect_any_instance_of(InfluxDB::Client).not_to receive(:write_point)
99
- subject.call("name", start, finish, "id", payload)
100
- end
101
- end
102
- end
103
- end
@@ -1,108 +0,0 @@
1
- require "spec_helper"
2
- require "shared_examples/data"
3
-
4
- RSpec.describe InfluxDB::Rails::Middleware::SqlSubscriber 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.client).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(:hook_name) { "sql.active_record" }
18
- let(:payload) { { sql: "SELECT * FROM POSTS WHERE id = 1", name: "Post Load", binds: %w[1 2 3] } }
19
- let(:data) do
20
- {
21
- values: {
22
- value: 2000,
23
- sql: "SELECT * FROM POSTS WHERE id = xxx"
24
- },
25
- tags: {
26
- location: "Foo#bar",
27
- operation: "SELECT",
28
- class_name: "Post",
29
- hook: "sql",
30
- name: "Post Load",
31
- },
32
- timestamp: 1_517_567_370_000
33
- }
34
- end
35
-
36
- subject { described_class.new(config, hook_name) }
37
-
38
- before do
39
- InfluxDB::Rails.current.controller = "Foo"
40
- InfluxDB::Rails.current.action = "bar"
41
- end
42
-
43
- after do
44
- InfluxDB::Rails.current.reset
45
- end
46
-
47
- context "successfully" do
48
- it "writes to InfluxDB" do
49
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
50
- config.measurement_name, data
51
- )
52
- subject.call("name", start, finish, "id", payload)
53
- end
54
-
55
- context "with not relevant queries" do
56
- before do
57
- payload[:sql] = "SHOW FULL FIELDS FROM `users`"
58
- end
59
-
60
- it "does not write to InfluxDB" do
61
- expect_any_instance_of(InfluxDB::Client).not_to receive(:write_point)
62
- subject.call("name", start, finish, "id", payload)
63
- end
64
- end
65
-
66
- it_behaves_like "with additional data", ["sql"]
67
-
68
- context "without location" do
69
- before do
70
- InfluxDB::Rails.current.reset
71
- end
72
-
73
- it "does use the default location" do
74
- data[:tags] = data[:tags].merge(location: :raw)
75
- expect_any_instance_of(InfluxDB::Client).to receive(:write_point).with(
76
- config.measurement_name, data
77
- )
78
- subject.call("name", start, finish, "id", payload)
79
- end
80
- end
81
- end
82
-
83
- context "unsuccessfully" do
84
- before do
85
- InfluxDB::Rails.configuration = config
86
- end
87
-
88
- it "does log exceptions" do
89
- allow_any_instance_of(InfluxDB::Client).to receive(:write_point).and_raise("boom")
90
- expect(::Rails.logger).to receive(:error).with(/boom/)
91
- subject.call("name", start, finish, "id", payload)
92
- end
93
- end
94
-
95
- context "disabled" do
96
- before do
97
- allow(config).to receive(:ignored_hooks).and_return(["sql.active_record"])
98
- end
99
-
100
- subject { described_class.new(config, "sql.active_record") }
101
-
102
- it "does not write a data point" do
103
- expect_any_instance_of(InfluxDB::Client).not_to receive(:write_point)
104
- subject.call("name", start, finish, "id", payload)
105
- end
106
- end
107
- end
108
- end