influxdb-rails 1.0.0.beta4 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) 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 +32 -0
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +35 -7
  7. data/CHANGELOG.md +40 -3
  8. data/README.md +125 -27
  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 +7 -4
  13. data/lib/influxdb-rails.rb +13 -2
  14. data/lib/influxdb/rails/configuration.rb +22 -13
  15. data/lib/influxdb/rails/context.rb +6 -40
  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 +15 -16
  23. data/lib/influxdb/rails/middleware/request_subscriber.rb +16 -21
  24. data/lib/influxdb/rails/middleware/sql_subscriber.rb +18 -18
  25. data/lib/influxdb/rails/middleware/subscriber.rb +40 -27
  26. data/lib/influxdb/rails/railtie.rb +15 -18
  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/templates/initializer.rb +4 -0
  33. data/sample-dashboard/Dockerfile +2 -3
  34. data/sample-dashboard/README.md +21 -28
  35. data/sample-dashboard/Rakefile +10 -4
  36. data/sample-dashboard/Ruby On Rails ActiveJob.json +600 -0
  37. data/sample-dashboard/Ruby On Rails Performance per Action.json +1330 -0
  38. data/sample-dashboard/{Ruby On Rails Performance (per Request).json → Ruby On Rails Performance per Request.json } +367 -217
  39. data/sample-dashboard/Ruby On Rails Performance.json +1348 -1110
  40. data/sample-dashboard/Ruby On Rails Requests.json +834 -0
  41. data/sample-dashboard/Ruby On Rails Slowlog by Action.json +278 -0
  42. data/sample-dashboard/Ruby On Rails Slowlog by Request.json +277 -0
  43. data/sample-dashboard/Ruby On Rails Slowlog by SQL.json +328 -0
  44. data/sample-dashboard/docker-compose.yml +7 -1
  45. data/sample-dashboard/provisioning/activejob.json +600 -0
  46. data/sample-dashboard/provisioning/performance-action.json +1330 -0
  47. data/sample-dashboard/provisioning/performance-request.json +361 -211
  48. data/sample-dashboard/provisioning/performance.json +1337 -1099
  49. data/sample-dashboard/provisioning/requests.json +834 -0
  50. data/sample-dashboard/provisioning/slowlog-action.json +278 -0
  51. data/sample-dashboard/provisioning/slowlog-requests.json +277 -0
  52. data/sample-dashboard/provisioning/slowlog-sql.json +328 -0
  53. data/spec/requests/action_controller_metrics_spec.rb +83 -0
  54. data/spec/requests/action_mailer_deliver_metrics_spec.rb +49 -0
  55. data/spec/requests/action_view_collection_metrics_spec.rb +66 -0
  56. data/spec/requests/action_view_partial_metrics_spec.rb +62 -0
  57. data/spec/requests/action_view_template_metrics_spec.rb +62 -0
  58. data/spec/requests/active_job_enqueue_metrics_spec.rb +65 -0
  59. data/spec/requests/active_job_perform_metrics_spec.rb +68 -0
  60. data/spec/requests/active_record_instantiation_metrics_spec.rb +65 -0
  61. data/spec/requests/active_record_sql_metrics_spec.rb +103 -0
  62. data/spec/requests/block_inistrumentation_spec.rb +64 -0
  63. data/spec/requests/context_spec.rb +27 -0
  64. data/spec/requests/logger_spec.rb +10 -0
  65. data/spec/spec_helper.rb +12 -4
  66. data/spec/support/broken_client.rb +11 -0
  67. data/spec/support/rails5/app.rb +48 -13
  68. data/spec/support/rails6/app.rb +83 -0
  69. data/spec/support/views/layouts/mailer.txt.erb +1 -0
  70. data/spec/support/views/{widgets → metrics}/_item.html.erb +0 -0
  71. data/spec/support/views/{widgets → metrics}/index.html.erb +0 -0
  72. data/spec/support/views/metrics/show.html.erb +4 -0
  73. data/spec/unit/block_instrumentation_spec.rb +18 -0
  74. metadata +124 -46
  75. data/.travis.yml +0 -37
  76. data/gemfiles/Gemfile.rails-4.2.x +0 -7
  77. data/gemfiles/Gemfile.rails-5.0.x +0 -7
  78. data/gemfiles/Gemfile.rails-5.1.x +0 -7
  79. data/lib/influxdb/rails/instrumentation.rb +0 -34
  80. data/lib/influxdb/rails/middleware/simple_subscriber.rb +0 -33
  81. data/spec/controllers/widgets_controller_spec.rb +0 -15
  82. data/spec/integration/integration_helper.rb +0 -1
  83. data/spec/integration/metrics_spec.rb +0 -27
  84. data/spec/shared_examples/data.rb +0 -61
  85. data/spec/support/rails4/app.rb +0 -48
  86. data/spec/unit/context_spec.rb +0 -40
  87. data/spec/unit/middleware/render_subscriber_spec.rb +0 -96
  88. data/spec/unit/middleware/request_subscriber_spec.rb +0 -103
  89. data/spec/unit/middleware/sql_subscriber_spec.rb +0 -108
data/Rakefile CHANGED
@@ -21,12 +21,6 @@ task default: %i[spec rubocop]
21
21
 
22
22
  task "test:all" => :default do
23
23
  Dir.glob("gemfiles/Gemfile.rails-*.x") do |gemfile|
24
- if RUBY_VERSION >= "2.6.0" && gemfile == "gemfiles/Gemfile.rails-4.2.x"
25
- msg = "ignore #{gemfile} on Ruby #{RUBY_VERSION}"
26
- puts RSpec::Core::Formatters::ConsoleCodes.wrap(msg, :yellow)
27
- next
28
- end
29
-
30
24
  puts RSpec::Core::Formatters::ConsoleCodes.wrap(gemfile, :cyan)
31
25
  sh({ "BUNDLE_GEMFILE" => gemfile }, "bundle", "install", "--quiet", "--retry=2", "--jobs=2")
32
26
  sh({ "BUNDLE_GEMFILE" => gemfile }, "bundle", "exec", "rspec")
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'actionpack', '~> 6.0.0'
4
+ gem 'activesupport', '~> 6.0.0'
5
+ gem 'activemodel', '~> 6.0.0'
6
+ gem 'sqlite3', '~> 1.4'
7
+ gem 'rspec-rails'
8
+
9
+ gemspec :path => '../'
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'actionpack', '~> 6.1.0'
4
+ gem 'activesupport', '~> 6.1.0'
5
+ gem 'activemodel', '~> 6.1.0'
6
+ gem 'sqlite3', '~> 1.4'
7
+ gem 'rspec-rails'
8
+
9
+ gemspec :path => '../'
@@ -22,20 +22,23 @@ Gem::Specification.new do |spec|
22
22
  spec.test_files = spec.files.grep(%r{^(test|spec|features|smoke)/})
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.required_ruby_version = ">= 2.3.0"
25
+ spec.required_ruby_version = ">= 2.4.0"
26
26
 
27
27
  spec.add_runtime_dependency "influxdb", "~> 0.6", ">= 0.6.4"
28
- spec.add_runtime_dependency "railties", ">= 4.2"
28
+ spec.add_runtime_dependency "railties", ">= 5.0"
29
29
 
30
+ spec.add_development_dependency "actionmailer"
31
+ spec.add_development_dependency "activejob"
30
32
  spec.add_development_dependency "activerecord"
31
33
  spec.add_development_dependency "bundler", ">= 1.0.0"
32
34
  spec.add_development_dependency "fakeweb"
35
+ spec.add_development_dependency "launchy"
33
36
  spec.add_development_dependency "pry"
34
37
  spec.add_development_dependency "rake"
35
38
  spec.add_development_dependency "rdoc"
36
39
  spec.add_development_dependency "rspec"
37
40
  spec.add_development_dependency "rspec-rails", ">= 3.0.0"
38
- spec.add_development_dependency "rubocop", "~> 0.61.1"
39
- spec.add_development_dependency "sqlite3", "1.3.13"
41
+ spec.add_development_dependency "rubocop", "~> 1.9.0"
42
+ spec.add_development_dependency "sqlite3"
40
43
  spec.add_development_dependency "tzinfo"
41
44
  end
@@ -2,9 +2,13 @@ require "net/http"
2
2
  require "net/https"
3
3
  require "rubygems"
4
4
  require "socket"
5
+ require "influxdb/rails/middleware/block_instrumentation_subscriber"
5
6
  require "influxdb/rails/middleware/render_subscriber"
6
7
  require "influxdb/rails/middleware/request_subscriber"
7
8
  require "influxdb/rails/middleware/sql_subscriber"
9
+ require "influxdb/rails/middleware/active_record_subscriber"
10
+ require "influxdb/rails/middleware/active_job_subscriber"
11
+ require "influxdb/rails/middleware/action_mailer_subscriber"
8
12
  require "influxdb/rails/sql/query"
9
13
  require "influxdb/rails/version"
10
14
  require "influxdb/rails/configuration"
@@ -17,8 +21,7 @@ module InfluxDB
17
21
  # InfluxDB and Rails. This is a singleton class.
18
22
  module Rails
19
23
  class << self
20
- attr_writer :configuration
21
- attr_writer :client
24
+ attr_writer :configuration, :client
22
25
 
23
26
  def configure
24
27
  return configuration unless block_given?
@@ -36,6 +39,7 @@ module InfluxDB
36
39
  database: cfg.database,
37
40
  username: cfg.username,
38
41
  password: cfg.password,
42
+ auth_method: cfg.auth_method,
39
43
  hosts: cfg.hosts,
40
44
  port: cfg.port,
41
45
  async: cfg.async,
@@ -57,6 +61,13 @@ module InfluxDB
57
61
  def current
58
62
  @current ||= InfluxDB::Rails::Context.new
59
63
  end
64
+
65
+ def instrument(name, options = {})
66
+ ActiveSupport::Notifications.instrument "block_instrumentation.influxdb_rails",
67
+ **options.merge(name: name) do
68
+ yield if block_given?
69
+ end
70
+ end
60
71
  end
61
72
  end
62
73
  end
@@ -34,6 +34,7 @@ module InfluxDB
34
34
  username: "root".freeze,
35
35
  password: "root".freeze,
36
36
  database: nil,
37
+ auth_method: "params".freeze,
37
38
  async: true,
38
39
  use_ssl: false,
39
40
  retry: nil,
@@ -53,14 +54,13 @@ module InfluxDB
53
54
  include Configurable
54
55
 
55
56
  set_defaults(
56
- measurement_name: "rails".freeze,
57
- ignored_hooks: [].freeze,
58
- tags_middleware: ->(tags) { tags },
59
- rails_app_name: nil,
60
- ignored_environments: %w[test cucumber selenium].freeze,
61
- environment: ::Rails.env,
62
- debug: false,
63
- instrumentation_enabled: true
57
+ measurement_name: "rails".freeze,
58
+ ignored_hooks: [].freeze,
59
+ tags_middleware: ->(tags) { tags },
60
+ rails_app_name: nil,
61
+ ignored_environments: %w[test cucumber selenium].freeze,
62
+ environment: ::Rails.env,
63
+ debug: false
64
64
  )
65
65
 
66
66
  # config option set after_initialize
@@ -83,8 +83,21 @@ module InfluxDB
83
83
  :ignored_exceptions,
84
84
  :ignored_exception_messages,
85
85
  :ignored_user_agents,
86
+ :application_root,
86
87
  :environment_variable_filters,
87
- :backtrace_filters
88
+ :backtrace_filters,
89
+ :influxdb_database,
90
+ :influxdb_username,
91
+ :influxdb_password,
92
+ :influxdb_hosts,
93
+ :influxdb_port,
94
+ :async,
95
+ :use_ssl,
96
+ :retry,
97
+ :open_timeout,
98
+ :read_timeout,
99
+ :max_delay,
100
+ :time_precision
88
101
 
89
102
  def initialize
90
103
  @client = ClientConfig.new
@@ -95,10 +108,6 @@ module InfluxDB
95
108
  @debug
96
109
  end
97
110
 
98
- def instrumentation_enabled?
99
- @instrumentation_enabled
100
- end
101
-
102
111
  def ignore_current_environment?
103
112
  ignored_environments.include?(environment)
104
113
  end
@@ -1,59 +1,25 @@
1
1
  module InfluxDB
2
2
  module Rails
3
3
  class Context
4
- def controller
5
- Thread.current[:_influxdb_rails_controller]
6
- end
7
-
8
- def controller=(value)
9
- Thread.current[:_influxdb_rails_controller] = value
10
- end
11
-
12
- def action
13
- Thread.current[:_influxdb_rails_action]
14
- end
15
-
16
- def action=(value)
17
- Thread.current[:_influxdb_rails_action] = value
18
- end
19
-
20
- def request_id=(value)
21
- Thread.current[:_influxdb_rails_request_id] = value
22
- end
23
-
24
- def request_id
25
- Thread.current[:_influxdb_rails_request_id]
26
- end
27
-
28
- def location
29
- [
30
- controller,
31
- action,
32
- ].reject(&:blank?).join("#")
33
- end
34
-
35
4
  def reset
36
- Thread.current[:_influxdb_rails_controller] = nil
37
- Thread.current[:_influxdb_rails_action] = nil
38
- Thread.current[:_influxdb_rails_tags] = nil
39
- Thread.current[:_influxdb_rails_values] = nil
40
- Thread.current[:_influxdb_rails_request_id] = nil
5
+ Thread.current[:_influxdb_rails_tags] = {}
6
+ Thread.current[:_influxdb_rails_values] = {}
41
7
  end
42
8
 
43
9
  def tags
44
- Thread.current[:_influxdb_rails_tags] || {}
10
+ Thread.current[:_influxdb_rails_tags].to_h
45
11
  end
46
12
 
47
13
  def tags=(tags)
48
- Thread.current[:_influxdb_rails_tags] = tags
14
+ Thread.current[:_influxdb_rails_tags] = self.tags.merge(tags)
49
15
  end
50
16
 
51
17
  def values
52
- Thread.current[:_influxdb_rails_values].to_h.merge(request_id: request_id)
18
+ Thread.current[:_influxdb_rails_values].to_h
53
19
  end
54
20
 
55
21
  def values=(values)
56
- Thread.current[:_influxdb_rails_values] = values
22
+ Thread.current[:_influxdb_rails_values] = self.values.merge(values)
57
23
  end
58
24
  end
59
25
  end
@@ -0,0 +1,48 @@
1
+ require_relative "../test_client"
2
+ require "launchy"
3
+
4
+ module InfluxDB
5
+ module Rails
6
+ module Matchers
7
+ def expect_metric(name: "rails", **options)
8
+ expect(metrics).to include(
9
+ a_hash_including(options.merge(name: name))
10
+ )
11
+ end
12
+
13
+ def expect_no_metric(name: "rails", **options)
14
+ expect(metrics).not_to include(
15
+ a_hash_including(options.merge(name: name))
16
+ )
17
+ end
18
+
19
+ def save_and_open_metrics
20
+ dir = File.join(File.dirname(__FILE__), "..", "..", "tmp")
21
+ FileUtils.mkdir_p(dir)
22
+ file_path = File.join(dir, "metrics.json")
23
+ output = JSON.pretty_generate(metrics)
24
+ File.write(file_path, output, mode: "wb")
25
+ ::Launchy.open(file_path)
26
+ end
27
+
28
+ def metrics
29
+ TestClient.metrics
30
+ end
31
+
32
+ RSpec.configure do |config|
33
+ config.before :each do
34
+ InfluxDB::Rails.instance_variable_set :@configuration, nil
35
+ InfluxDB::Rails.configure
36
+
37
+ allow(InfluxDB::Rails).to receive(:client).and_return(InfluxDB::Rails::TestClient.new)
38
+ allow_any_instance_of(InfluxDB::Rails::Configuration)
39
+ .to receive(:ignored_environments).and_return(%w[development])
40
+
41
+ InfluxDB::Rails::TestClient.metrics.clear
42
+ end
43
+
44
+ config.include InfluxDB::Rails::Matchers
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ require "influxdb/rails/values"
2
+ require "influxdb/rails/tags"
3
+
4
+ module InfluxDB
5
+ module Rails
6
+ class Metric
7
+ def initialize(configuration:, timestamp:, tags: {}, values: {})
8
+ @configuration = configuration
9
+ @timestamp = timestamp
10
+ @tags = tags
11
+ @values = values
12
+ end
13
+
14
+ def write
15
+ client.write_point configuration.measurement_name, options
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :configuration, :tags, :values, :timestamp
21
+
22
+ def options
23
+ {
24
+ values: Values.new(values: values).to_h,
25
+ tags: Tags.new(tags: tags, config: configuration).to_h,
26
+ timestamp: timestamp_with_precision,
27
+ }
28
+ end
29
+
30
+ def timestamp_with_precision
31
+ InfluxDB.convert_timestamp(timestamp.utc, configuration.client.time_precision)
32
+ end
33
+
34
+ def client
35
+ InfluxDB::Rails.client
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ require "influxdb/rails/middleware/subscriber"
2
+
3
+ module InfluxDB
4
+ module Rails
5
+ module Middleware
6
+ class ActionMailerSubscriber < Subscriber # :nodoc:
7
+ private
8
+
9
+ def values
10
+ { value: 1 }
11
+ end
12
+
13
+ def tags
14
+ {
15
+ hook: "deliver",
16
+ mailer: payload[:mailer],
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,67 @@
1
+ require "influxdb/rails/middleware/subscriber"
2
+
3
+ module InfluxDB
4
+ module Rails
5
+ module Middleware
6
+ class ActiveJobSubscriber < Subscriber # :nodoc:
7
+ private
8
+
9
+ JOB_STATE = {
10
+ "enqueue" => "queued",
11
+ "perform_start" => "running",
12
+ "perform" => "succeeded",
13
+ }.freeze
14
+ private_constant :JOB_STATE
15
+
16
+ def values
17
+ {
18
+ value: value,
19
+ }
20
+ end
21
+
22
+ def tags
23
+ {
24
+ hook: short_hook_name,
25
+ state: job_state,
26
+ job: job.class.name,
27
+ queue: job.queue_name,
28
+ }
29
+ end
30
+
31
+ def job_state
32
+ return "failed" if failed?
33
+
34
+ JOB_STATE[short_hook_name]
35
+ end
36
+
37
+ def measure_performance?
38
+ short_hook_name == "perform"
39
+ end
40
+
41
+ def short_hook_name
42
+ @short_hook_name ||= fetch_short_hook_name
43
+ end
44
+
45
+ def fetch_short_hook_name
46
+ return "enqueue" if hook_name.include?("enqueue")
47
+
48
+ "perform"
49
+ end
50
+
51
+ def job
52
+ @job ||= payload[:job]
53
+ end
54
+
55
+ def value
56
+ return duration if measure_performance?
57
+
58
+ 1
59
+ end
60
+
61
+ def failed?
62
+ payload[:aborted]
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,26 @@
1
+ require "influxdb/rails/middleware/subscriber"
2
+ require "influxdb/rails/sql/query"
3
+
4
+ module InfluxDB
5
+ module Rails
6
+ module Middleware
7
+ class ActiveRecordSubscriber < Subscriber # :nodoc:
8
+ private
9
+
10
+ def values
11
+ {
12
+ value: duration,
13
+ record_count: payload[:record_count],
14
+ }
15
+ end
16
+
17
+ def tags
18
+ {
19
+ hook: "instantiation",
20
+ class_name: payload[:class_name],
21
+ }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end