From 4cd6fcd4d15a256f44b91a98d987ce83c33224f8 Mon Sep 17 00:00:00 2001 From: Christian Bruckmayer Date: Thu, 20 Feb 2020 11:31:36 +0000 Subject: [PATCH] Implement instantiation.active_record subscriber Partially address https://github.com/influxdata/influxdb-rails/issues/74 --- CHANGELOG.md | 1 + lib/influxdb-rails.rb | 1 + .../middleware/active_record_subscriber.rb | 26 ++++++++ lib/influxdb/rails/railtie.rb | 1 + ...ctive_record_instantiation_metrics_spec.rb | 65 +++++++++++++++++++ spec/support/rails4/app.rb | 6 +- spec/support/rails5/app.rb | 6 +- spec/support/rails6/app.rb | 6 +- spec/support/views/metrics/show.html.erb | 4 ++ 9 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 lib/influxdb/rails/middleware/active_record_subscriber.rb create mode 100644 spec/requests/active_record_instantiation_metrics_spec.rb create mode 100644 spec/support/views/metrics/show.html.erb diff --git a/CHANGELOG.md b/CHANGELOG.md index ba33534..4eefc14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ For the full commit log, [see here](https://github.com/influxdata/influxdb-rails - Drop undocumented `instrumentation_enabled` setting, use `ignored_environments` do disable instrumentation - Simplified spec with a PORO test client +- Implement `instantiation.active_record` subscriber (https://guides.rubyonrails.org/active_support_instrumentation.html#instantiation-active-record) ## v1.0.0, released 2019-10-23 The Final release, no code changes. diff --git a/lib/influxdb-rails.rb b/lib/influxdb-rails.rb index a0b13e7..ed4a4e3 100644 --- a/lib/influxdb-rails.rb +++ b/lib/influxdb-rails.rb @@ -5,6 +5,7 @@ require "influxdb/rails/middleware/render_subscriber" require "influxdb/rails/middleware/request_subscriber" require "influxdb/rails/middleware/sql_subscriber" +require "influxdb/rails/middleware/active_record_subscriber" require "influxdb/rails/sql/query" require "influxdb/rails/version" require "influxdb/rails/configuration" diff --git a/lib/influxdb/rails/middleware/active_record_subscriber.rb b/lib/influxdb/rails/middleware/active_record_subscriber.rb new file mode 100644 index 0000000..cdfa5e6 --- /dev/null +++ b/lib/influxdb/rails/middleware/active_record_subscriber.rb @@ -0,0 +1,26 @@ +require "influxdb/rails/middleware/subscriber" +require "influxdb/rails/sql/query" + +module InfluxDB + module Rails + module Middleware + class ActiveRecordSubscriber < Subscriber # :nodoc: + private + + def values(started, finished, payload) + { + value: ((finished - started) * 1000).ceil, + record_count: payload[:record_count], + } + end + + def tags(payload) + { + hook: "instantiation", + class_name: payload[:class_name], + } + end + end + end + end +end diff --git a/lib/influxdb/rails/railtie.rb b/lib/influxdb/rails/railtie.rb index 2b6b41d..acb5776 100644 --- a/lib/influxdb/rails/railtie.rb +++ b/lib/influxdb/rails/railtie.rb @@ -29,6 +29,7 @@ class Railtie < ::Rails::Railtie # :nodoc: "render_partial.action_view" => Middleware::RenderSubscriber, "render_collection.action_view" => Middleware::RenderSubscriber, "sql.active_record" => Middleware::SqlSubscriber, + "instantiation.active_record" => Middleware::ActiveRecordSubscriber, }.each do |hook_name, subscriber_class| subscribe_to(hook_name, subscriber_class) end diff --git a/spec/requests/active_record_instantiation_metrics_spec.rb b/spec/requests/active_record_instantiation_metrics_spec.rb new file mode 100644 index 0000000..a5977e8 --- /dev/null +++ b/spec/requests/active_record_instantiation_metrics_spec.rb @@ -0,0 +1,65 @@ +require File.dirname(__FILE__) + "/../spec_helper" + +RSpec.describe "ActiveRecord instantiation metrics", type: :request do + let(:tags_middleware) do + lambda do |tags| + tags.merge(tags_middleware: :tags_middleware) + end + end + let(:metric) { Metric.create!(name: "name") } + before do + allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_environments).and_return(%w[development]) + allow_any_instance_of(ActionDispatch::Request).to receive(:request_id).and_return(:request_id) + allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:application_name).and_return(:app_name) + allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:tags_middleware).and_return(tags_middleware) + end + + it "writes metric" do + get metric_path(metric) + + expect_metric( + tags: a_hash_including( + location: "MetricsController#show", + hook: "instantiation", + class_name: "Metric", + additional_tag: :value, + server: Socket.gethostname, + app_name: :app_name, + tags_middleware: :tags_middleware + ), + values: a_hash_including( + additional_value: :value, + request_id: :request_id, + value: be_between(1, 30), + record_count: 1 + ) + ) + end + + it "includes correct timestamps" do + travel_to Time.zone.local(2018, 1, 1, 9, 0, 0) + + get metric_path(metric) + + expect_metric( + tags: a_hash_including( + location: "MetricsController#show", + hook: "instantiation" + ), + timestamp: 1_514_797_200 + ) + end + + it "does not write metric when hook is ignored" do + allow_any_instance_of(InfluxDB::Rails::Configuration).to receive(:ignored_hooks).and_return(["instantiation.active_record"]) + + get metric_path(metric) + + expect_no_metric( + tags: a_hash_including( + location: "MetricsController#show", + hook: "instantiation" + ) + ) + end +end diff --git a/spec/support/rails4/app.rb b/spec/support/rails4/app.rb index cc4f780..8dc9527 100644 --- a/spec/support/rails4/app.rb +++ b/spec/support/rails4/app.rb @@ -12,7 +12,7 @@ app.initialize! app.routes.draw do - resources :metrics, only: :index + resources :metrics, only: %i[index show] resources :exceptions, only: :index end @@ -41,6 +41,10 @@ class MetricsController < ApplicationController def index Metric.create!(name: "name") end + + def show + @metric = Metric.find_by(name: "name") + end end class ExceptionsController < ApplicationController diff --git a/spec/support/rails5/app.rb b/spec/support/rails5/app.rb index cc4f780..8dc9527 100644 --- a/spec/support/rails5/app.rb +++ b/spec/support/rails5/app.rb @@ -12,7 +12,7 @@ app.initialize! app.routes.draw do - resources :metrics, only: :index + resources :metrics, only: %i[index show] resources :exceptions, only: :index end @@ -41,6 +41,10 @@ class MetricsController < ApplicationController def index Metric.create!(name: "name") end + + def show + @metric = Metric.find_by(name: "name") + end end class ExceptionsController < ApplicationController diff --git a/spec/support/rails6/app.rb b/spec/support/rails6/app.rb index cc4f780..8dc9527 100644 --- a/spec/support/rails6/app.rb +++ b/spec/support/rails6/app.rb @@ -12,7 +12,7 @@ app.initialize! app.routes.draw do - resources :metrics, only: :index + resources :metrics, only: %i[index show] resources :exceptions, only: :index end @@ -41,6 +41,10 @@ class MetricsController < ApplicationController def index Metric.create!(name: "name") end + + def show + @metric = Metric.find_by(name: "name") + end end class ExceptionsController < ApplicationController diff --git a/spec/support/views/metrics/show.html.erb b/spec/support/views/metrics/show.html.erb new file mode 100644 index 0000000..ccd2930 --- /dev/null +++ b/spec/support/views/metrics/show.html.erb @@ -0,0 +1,4 @@ +

Show

+
+ <%= @metric.name %> +