mirror of https://github.com/rails/rails
Merge pull request #46041 from Shopify/fix-ar-log-sub
Fix Active Record :db_runtime metric
This commit is contained in:
commit
fc71f585ba
|
@ -19,7 +19,7 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
ActiveRecord::LogSubscriber.runtime += 100
|
ActiveRecord::RuntimeRegistry.sql_runtime += 100.0
|
||||||
Project.last
|
Project.last
|
||||||
redirect_to "/"
|
redirect_to "/"
|
||||||
end
|
end
|
||||||
|
@ -32,7 +32,7 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase
|
||||||
def db_after_render
|
def db_after_render
|
||||||
render inline: "Hello world"
|
render inline: "Hello world"
|
||||||
Project.all
|
Project.all
|
||||||
ActiveRecord::LogSubscriber.runtime += 100
|
ActiveRecord::RuntimeRegistry.sql_runtime += 100.0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_runtime_reset_before_requests
|
def test_runtime_reset_before_requests
|
||||||
ActiveRecord::LogSubscriber.runtime += 12345
|
ActiveRecord::RuntimeRegistry.sql_runtime += 12345.0
|
||||||
get :zero
|
get :zero
|
||||||
wait
|
wait
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,24 @@ module ActiveRecord
|
||||||
class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
|
class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
|
||||||
|
|
||||||
def self.runtime=(value)
|
def self.runtime=(value)
|
||||||
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
||||||
|
ActiveRecord::LogSubscriber.runtime= is deprecated and will be removed in Rails 7.2.
|
||||||
|
MSG
|
||||||
ActiveRecord::RuntimeRegistry.sql_runtime = value
|
ActiveRecord::RuntimeRegistry.sql_runtime = value
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.runtime
|
def self.runtime
|
||||||
ActiveRecord::RuntimeRegistry.sql_runtime ||= 0
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
||||||
|
ActiveRecord::LogSubscriber.runtime is deprecated and will be removed in Rails 7.2.
|
||||||
|
MSG
|
||||||
|
ActiveRecord::RuntimeRegistry.sql_runtime
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.reset_runtime
|
def self.reset_runtime
|
||||||
rt, self.runtime = runtime, 0
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
||||||
rt
|
ActiveRecord::LogSubscriber.reset_runtime is deprecated and will be removed in Rails 7.2.
|
||||||
|
MSG
|
||||||
|
ActiveRecord::RuntimeRegistry.reset
|
||||||
end
|
end
|
||||||
|
|
||||||
def strict_loading_violation(event)
|
def strict_loading_violation(event)
|
||||||
|
@ -29,8 +37,6 @@ module ActiveRecord
|
||||||
subscribe_log_level :strict_loading_violation, :debug
|
subscribe_log_level :strict_loading_violation, :debug
|
||||||
|
|
||||||
def sql(event)
|
def sql(event)
|
||||||
self.class.runtime += event.duration
|
|
||||||
|
|
||||||
payload = event.payload
|
payload = event.payload
|
||||||
|
|
||||||
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "active_support/core_ext/module/attr_internal"
|
require "active_support/core_ext/module/attr_internal"
|
||||||
require "active_record/log_subscriber"
|
require "active_record/runtime_registry"
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
module Railties # :nodoc:
|
module Railties # :nodoc:
|
||||||
|
@ -23,16 +23,16 @@ module ActiveRecord
|
||||||
# We also need to reset the runtime before each action
|
# We also need to reset the runtime before each action
|
||||||
# because of queries in middleware or in cases we are streaming
|
# because of queries in middleware or in cases we are streaming
|
||||||
# and it won't be cleaned up by the method below.
|
# and it won't be cleaned up by the method below.
|
||||||
ActiveRecord::LogSubscriber.reset_runtime
|
ActiveRecord::RuntimeRegistry.reset
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def cleanup_view_runtime
|
def cleanup_view_runtime
|
||||||
if logger && logger.info? && ActiveRecord::Base.connected?
|
if logger && logger.info? && ActiveRecord::Base.connected?
|
||||||
db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
|
db_rt_before_render = ActiveRecord::RuntimeRegistry.reset
|
||||||
self.db_runtime = (db_runtime || 0) + db_rt_before_render
|
self.db_runtime = (db_runtime || 0) + db_rt_before_render
|
||||||
runtime = super
|
runtime = super
|
||||||
db_rt_after_render = ActiveRecord::LogSubscriber.reset_runtime
|
db_rt_after_render = ActiveRecord::RuntimeRegistry.reset
|
||||||
self.db_runtime += db_rt_after_render
|
self.db_runtime += db_rt_after_render
|
||||||
runtime - db_rt_after_render
|
runtime - db_rt_after_render
|
||||||
else
|
else
|
||||||
|
@ -43,7 +43,7 @@ module ActiveRecord
|
||||||
def append_info_to_payload(payload)
|
def append_info_to_payload(payload)
|
||||||
super
|
super
|
||||||
if ActiveRecord::Base.connected?
|
if ActiveRecord::Base.connected?
|
||||||
payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
|
payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::RuntimeRegistry.reset
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "active_record/log_subscriber"
|
require "active_record/runtime_registry"
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
module Railties # :nodoc:
|
module Railties # :nodoc:
|
||||||
|
@ -9,9 +9,9 @@ module ActiveRecord
|
||||||
def instrument(operation, payload = {}, &block)
|
def instrument(operation, payload = {}, &block)
|
||||||
if operation == :perform && block
|
if operation == :perform && block
|
||||||
super(operation, payload) do
|
super(operation, payload) do
|
||||||
db_runtime_before_perform = ActiveRecord::LogSubscriber.runtime
|
db_runtime_before_perform = ActiveRecord::RuntimeRegistry.sql_runtime
|
||||||
result = block.call
|
result = block.call
|
||||||
payload[:db_runtime] = ActiveRecord::LogSubscriber.runtime - db_runtime_before_perform
|
payload[:db_runtime] = ActiveRecord::RuntimeRegistry.sql_runtime - db_runtime_before_perform
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
|
@ -10,11 +10,20 @@ module ActiveRecord
|
||||||
extend self
|
extend self
|
||||||
|
|
||||||
def sql_runtime
|
def sql_runtime
|
||||||
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime]
|
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] ||= 0.0
|
||||||
end
|
end
|
||||||
|
|
||||||
def sql_runtime=(runtime)
|
def sql_runtime=(runtime)
|
||||||
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
|
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reset
|
||||||
|
rt, self.sql_runtime = sql_runtime, 0.0
|
||||||
|
rt
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record") do |name, start, finish, id, payload|
|
||||||
|
ActiveRecord::RuntimeRegistry.sql_runtime += (finish - start) * 1_000.0
|
||||||
|
end
|
||||||
|
|
|
@ -8,21 +8,21 @@ class JobRuntimeTest < ActiveSupport::TestCase
|
||||||
include ActiveRecord::Railties::JobRuntime
|
include ActiveRecord::Railties::JobRuntime
|
||||||
|
|
||||||
def perform(*)
|
def perform(*)
|
||||||
ActiveRecord::LogSubscriber.runtime += 42
|
ActiveRecord::RuntimeRegistry.sql_runtime += 42.0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "job notification payload includes db_runtime" do
|
test "job notification payload includes db_runtime" do
|
||||||
ActiveRecord::LogSubscriber.runtime = 0
|
ActiveRecord::RuntimeRegistry.sql_runtime = 0.0
|
||||||
|
|
||||||
assert_equal 42, notification_payload[:db_runtime]
|
assert_equal 42, notification_payload[:db_runtime]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "db_runtime tracks database runtime for job only" do
|
test "db_runtime tracks database runtime for job only" do
|
||||||
ActiveRecord::LogSubscriber.runtime = 100
|
ActiveRecord::RuntimeRegistry.sql_runtime = 100.0
|
||||||
|
|
||||||
assert_equal 42, notification_payload[:db_runtime]
|
assert_equal 42.0, notification_payload[:db_runtime]
|
||||||
assert_equal 142, ActiveRecord::LogSubscriber.runtime
|
assert_equal 142.0, ActiveRecord::RuntimeRegistry.sql_runtime
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -247,10 +247,6 @@ class LogSubscriberTest < ActiveRecord::TestCase
|
||||||
assert_equal 0, @logger.logged(:debug).size
|
assert_equal 0, @logger.logged(:debug).size
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_initializes_runtime
|
|
||||||
Thread.new { assert_equal 0, ActiveRecord::LogSubscriber.runtime }.join
|
|
||||||
end
|
|
||||||
|
|
||||||
if ActiveRecord::Base.connection.prepared_statements
|
if ActiveRecord::Base.connection.prepared_statements
|
||||||
def test_where_in_binds_logging_include_attribute_names
|
def test_where_in_binds_logging_include_attribute_names
|
||||||
Developer.where(id: [1, 2, 3, 4, 5]).load
|
Developer.where(id: [1, 2, 3, 4, 5]).load
|
||||||
|
|
Loading…
Reference in New Issue