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
@@ -0,0 +1,68 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ RSpec.describe "ActiveJob start metrics", type: :request do
4
+ let(:tags_middleware) do
5
+ lambda do |tags|
6
+ tags.merge(tags_middleware: :tags_middleware)
7
+ end
8
+ end
9
+ before do
10
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_environments).and_return(%w[development])
11
+ allow_any_instance_of(ActionDispatch::Request).to receive(:request_id).and_return(:request_id)
12
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:application_name).and_return(:app_name)
13
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:tags_middleware).and_return(tags_middleware)
14
+ end
15
+
16
+ it "writes metric" do
17
+ perform_enqueued_jobs do
18
+ get "/metrics"
19
+ end
20
+
21
+ expect_metric(
22
+ tags: a_hash_including(
23
+ location: "MetricsController#index",
24
+ hook: "perform_start",
25
+ state: "running",
26
+ job: "MetricJob",
27
+ queue: "default",
28
+ server: Socket.gethostname,
29
+ app_name: :app_name,
30
+ tags_middleware: :tags_middleware
31
+ ),
32
+ values: a_hash_including(
33
+ value: 1
34
+ )
35
+ )
36
+ end
37
+
38
+ it "includes correct timestamps" do
39
+ travel_to Time.zone.local(2018, 1, 1, 9, 0, 0)
40
+
41
+ perform_enqueued_jobs do
42
+ get "/metrics"
43
+ end
44
+
45
+ expect_metric(
46
+ tags: a_hash_including(
47
+ location: "MetricsController#index",
48
+ hook: "perform_start"
49
+ ),
50
+ timestamp: 1_514_797_200
51
+ )
52
+ end
53
+
54
+ it "does not write metric when hook is ignored" do
55
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_hooks).and_return(["perform_start.active_job"])
56
+
57
+ perform_enqueued_jobs do
58
+ get "/metrics"
59
+ end
60
+
61
+ expect_no_metric(
62
+ tags: a_hash_including(
63
+ location: "MetricsController#index",
64
+ hook: "perform_start"
65
+ )
66
+ )
67
+ end
68
+ end
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ RSpec.describe "ActiveRecord instantiation metrics", type: :request do
4
+ let(:tags_middleware) do
5
+ lambda do |tags|
6
+ tags.merge(tags_middleware: :tags_middleware)
7
+ end
8
+ end
9
+ let(:metric) { Metric.create!(name: "name") }
10
+ before do
11
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_environments).and_return(%w[development])
12
+ allow_any_instance_of(ActionDispatch::Request).to receive(:request_id).and_return(:request_id)
13
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:application_name).and_return(:app_name)
14
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:tags_middleware).and_return(tags_middleware)
15
+ end
16
+
17
+ it "writes metric" do
18
+ get metric_path(metric)
19
+
20
+ expect_metric(
21
+ tags: a_hash_including(
22
+ location: "MetricsController#show",
23
+ hook: "instantiation",
24
+ class_name: "Metric",
25
+ additional_tag: :value,
26
+ server: Socket.gethostname,
27
+ app_name: :app_name,
28
+ tags_middleware: :tags_middleware
29
+ ),
30
+ values: a_hash_including(
31
+ additional_value: :value,
32
+ request_id: :request_id,
33
+ value: be_between(1, 30),
34
+ record_count: 1
35
+ )
36
+ )
37
+ end
38
+
39
+ it "includes correct timestamps" do
40
+ travel_to Time.zone.local(2018, 1, 1, 9, 0, 0)
41
+
42
+ get metric_path(metric)
43
+
44
+ expect_metric(
45
+ tags: a_hash_including(
46
+ location: "MetricsController#show",
47
+ hook: "instantiation"
48
+ ),
49
+ timestamp: 1_514_797_200
50
+ )
51
+ end
52
+
53
+ it "does not write metric when hook is ignored" do
54
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_hooks).and_return(["instantiation.active_record"])
55
+
56
+ get metric_path(metric)
57
+
58
+ expect_no_metric(
59
+ tags: a_hash_including(
60
+ location: "MetricsController#show",
61
+ hook: "instantiation"
62
+ )
63
+ )
64
+ end
65
+ end
@@ -0,0 +1,103 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ RSpec.describe "ActiveRecord SQL metrics", type: :request do
4
+ let(:tags_middleware) do
5
+ lambda do |tags|
6
+ tags.merge(tags_middleware: :tags_middleware)
7
+ end
8
+ end
9
+ before do
10
+ allow_any_instance_of(ActionDispatch::Request).to receive(:request_id).and_return(:request_id)
11
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:application_name).and_return(:app_name)
12
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:tags_middleware).and_return(tags_middleware)
13
+ end
14
+
15
+ it "writes metric" do
16
+ skip("https://github.com/rails/rails/issues/30586") unless payload_names_fixed_in_rails?
17
+
18
+ get "/metrics"
19
+
20
+ expect_metric(
21
+ tags: a_hash_including(
22
+ location: "MetricsController#index",
23
+ hook: "sql",
24
+ name: "Metric Create",
25
+ class_name: "Metric",
26
+ operation: "INSERT",
27
+ additional_tag: :value,
28
+ server: Socket.gethostname,
29
+ app_name: :app_name,
30
+ tags_middleware: :tags_middleware
31
+ ),
32
+ values: a_hash_including(
33
+ additional_value: :value,
34
+ request_id: :request_id,
35
+ value: be_between(1, 30),
36
+ sql: "INSERT INTO \"metrics\" (\"name\", \"created_at\", \"updated_at\") VALUES (xxx)"
37
+ )
38
+ )
39
+ end
40
+
41
+ it "writes metric" do
42
+ skip("https://github.com/rails/rails/issues/30586") if payload_names_fixed_in_rails?
43
+
44
+ get "/metrics"
45
+
46
+ expect_metric(
47
+ tags: a_hash_including(
48
+ location: "MetricsController#index",
49
+ hook: "sql",
50
+ name: "SQL",
51
+ class_name: "SQL",
52
+ operation: "INSERT",
53
+ additional_tag: :value,
54
+ server: Socket.gethostname,
55
+ app_name: :app_name,
56
+ tags_middleware: :tags_middleware
57
+ ),
58
+ values: a_hash_including(
59
+ additional_value: :value,
60
+ request_id: :request_id,
61
+ value: be_between(1, 30),
62
+ sql: "INSERT INTO \"metrics\" (\"name\", \"created_at\", \"updated_at\") VALUES (xxx)"
63
+ )
64
+ )
65
+ end
66
+
67
+ it "includes correct timestamps" do
68
+ travel_to Time.zone.local(2018, 1, 1, 9, 0, 0)
69
+
70
+ get "/metrics"
71
+
72
+ expect_metric(
73
+ tags: a_hash_including(
74
+ location: "MetricsController#index",
75
+ hook: "sql"
76
+ ),
77
+ timestamp: 1_514_797_200
78
+ )
79
+ end
80
+
81
+ it "does not write metric when hook is ignored" do
82
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_hooks).and_return(["sql.active_record"])
83
+
84
+ get "/metrics"
85
+
86
+ expect_no_metric(
87
+ tags: a_hash_including(
88
+ location: "MetricsController#index",
89
+ hook: "sql"
90
+ )
91
+ )
92
+ end
93
+
94
+ def payload_names_fixed_in_rails?
95
+ Rails::VERSION::MAJOR > 5 ||
96
+ rails_after_5_1?
97
+ end
98
+
99
+ def rails_after_5_1?
100
+ Rails::VERSION::MAJOR == 5 &&
101
+ Rails::VERSION::MINOR > 1
102
+ end
103
+ end
@@ -0,0 +1,64 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ RSpec.describe "BlockInstrumentation metrics", type: :request do
4
+ let(:tags_middleware) do
5
+ lambda do |tags|
6
+ tags.merge(tags_middleware: :tags_middleware)
7
+ end
8
+ end
9
+ before do
10
+ allow_any_instance_of(ActionDispatch::Request).to receive(:request_id).and_return(:request_id)
11
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:application_name).and_return(:app_name)
12
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:tags_middleware).and_return(tags_middleware)
13
+ end
14
+
15
+ it "writes metric" do
16
+ get "/metrics"
17
+
18
+ expect_metric(
19
+ tags: a_hash_including(
20
+ location: "MetricsController#index",
21
+ hook: "block_instrumentation",
22
+ additional_tag: :value,
23
+ server: Socket.gethostname,
24
+ app_name: :app_name,
25
+ tags_middleware: :tags_middleware,
26
+ block_tag: :block_tag,
27
+ name: "name"
28
+ ),
29
+ values: a_hash_including(
30
+ additional_value: :value,
31
+ request_id: :request_id,
32
+ block_value: :block_value,
33
+ value: be_between(1, 30)
34
+ )
35
+ )
36
+ end
37
+
38
+ it "includes correct timestamps" do
39
+ travel_to Time.zone.local(2018, 1, 1, 9, 0, 0)
40
+
41
+ get "/metrics"
42
+
43
+ expect_metric(
44
+ tags: a_hash_including(
45
+ location: "MetricsController#index",
46
+ hook: "block_instrumentation"
47
+ ),
48
+ timestamp: 1_514_797_200
49
+ )
50
+ end
51
+
52
+ it "does not write metric when hook is ignored" do
53
+ allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_hooks).and_return(["block_instrumentation.influxdb_rails"])
54
+
55
+ get "/metrics"
56
+
57
+ expect_no_metric(
58
+ tags: a_hash_including(
59
+ location: "MetricsController#index",
60
+ hook: "block_instrumentation"
61
+ )
62
+ )
63
+ end
64
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ RSpec.describe "Context", type: :request do
4
+ it "resets the context after a request" do
5
+ get "/metrics"
6
+
7
+ expect_metric(
8
+ tags: a_hash_including(
9
+ location: "MetricsController#index",
10
+ hook: "sql"
11
+ )
12
+ )
13
+
14
+ expect(InfluxDB::Rails.current.tags).to be_empty
15
+ expect(InfluxDB::Rails.current.values).to be_empty
16
+ end
17
+
18
+ it "resets the context after a request when exceptioni occurs" do
19
+ setup_broken_client
20
+
21
+ get "/metrics"
22
+
23
+ expect_no_metric(hook: "process_action")
24
+ expect(InfluxDB::Rails.current.tags).to be_empty
25
+ expect(InfluxDB::Rails.current.values).to be_empty
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ RSpec.describe "Logger", type: :request do
4
+ it "logs exception" do
5
+ setup_broken_client
6
+ expect(Rails.logger).to receive(:error).with(/message/).at_least(:once)
7
+
8
+ get "/metrics"
9
+ end
10
+ end
@@ -1,5 +1,9 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require "active_support"
4
+ require_relative "../lib/influxdb/rails/helpers/rspec_matchers"
5
+ require File.expand_path(File.dirname(__FILE__) + "/support/broken_client")
6
+
3
7
  ENV["RAILS_ENV"] ||= "test"
4
8
 
5
9
  require "rails"
@@ -25,9 +29,11 @@ RSpec.configure do |config|
25
29
  # use expect syntax
26
30
  config.disable_monkey_patching!
27
31
 
28
- # reset configuration for each spec
29
- config.before :each do
30
- InfluxDB::Rails.instance_variable_set :@configuration, nil
31
- InfluxDB::Rails.configure
32
+ config.after(:each) do
33
+ travel_back
32
34
  end
35
+
36
+ config.include ActiveSupport::Testing::TimeHelpers
37
+ config.include ActiveJob::TestHelper
38
+ config.include InfluxDB::Rails::BrokenClient
33
39
  end
@@ -0,0 +1,11 @@
1
+ module InfluxDB
2
+ module Rails
3
+ module BrokenClient
4
+ def setup_broken_client
5
+ client = double
6
+ allow(client).to receive(:write_point).and_raise("message")
7
+ allow(InfluxDB::Rails).to receive(:client).and_return(client)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,5 +1,6 @@
1
1
  require "action_controller/railtie"
2
- require "active_record"
2
+ require "active_record/railtie"
3
+ require "active_job"
3
4
 
4
5
  app = Class.new(Rails::Application)
5
6
  app.config.secret_key_base = "1234567890abcdef1234567890abcdef"
@@ -9,38 +10,59 @@ app.config.active_support.deprecation = :log
9
10
  app.config.eager_load = false
10
11
  app.config.root = __dir__
11
12
  Rails.backtrace_cleaner.remove_silencers!
13
+ ActiveJob::Base.logger = Rails.logger
12
14
  app.initialize!
13
15
 
14
16
  app.routes.draw do
15
- resources :widgets
17
+ resources :metrics, only: %i[index show]
18
+ resources :exceptions, only: :index
16
19
  end
17
20
 
18
21
  InfluxDB::Rails.configure do |config|
19
22
  end
20
23
 
21
- ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
24
+ ENV["DATABASE_URL"] = "sqlite3::memory:"
22
25
  ActiveRecord::Schema.define do
23
- create_table :widgets, force: true do |t|
24
- t.string :title
26
+ create_table :metrics, force: true do |t|
27
+ t.string :name
25
28
 
26
29
  t.timestamps
27
30
  end
28
31
  end
29
32
 
30
- class Widget < ActiveRecord::Base; end
33
+ class MetricJob < ActiveJob::Base
34
+ queue_as :default
35
+
36
+ def perform
37
+ # Do something later
38
+ end
39
+ end
40
+
41
+ class Metric < ActiveRecord::Base; end
31
42
  class ApplicationController < ActionController::Base; end
32
- class WidgetsController < ApplicationController
43
+ class MetricsController < ApplicationController
33
44
  prepend_view_path File.join(__dir__, "..", "views")
34
45
 
35
46
  before_action do
36
- InfluxDB::Rails.current.values = { key: :value }
47
+ InfluxDB::Rails.current.values = { additional_value: :value }
48
+ InfluxDB::Rails.current.tags = { additional_tag: :value }
37
49
  end
38
50
 
39
51
  def index
40
- Widget.create!(title: "test")
52
+ InfluxDB::Rails.instrument "name", tags: { block_tag: :block_tag }, values: { block_value: :block_value } do
53
+ 1 + 1
54
+ end
55
+ MetricJob.perform_later
56
+ Metric.create!(name: "name")
41
57
  end
42
58
 
43
- def new
59
+ def show
60
+ @metric = Metric.find_by(name: "name")
61
+ end
62
+ end
63
+
64
+ class ExceptionsController < ApplicationController
65
+ def index
44
66
  1 / 0
45
67
  end
46
68
  end