From ea3185ebdd2ff87d0160feeea7db6e60440c7f47 Mon Sep 17 00:00:00 2001 From: Alex Ghiculescu Date: Thu, 29 Jul 2021 15:02:51 -0500 Subject: [PATCH] Allow entirely opting out of deprecation warnings Previously if you did `app.config.active_support.deprecation = :silence`, some work would still be done on each call to `ActiveSupport::Deprecation.warn`. Specifically [checking the backtrace](https://github.com/rails/rails/blob/12372c54828e2ac04b230cedd5cbb75181e62d29/activesupport/lib/active_support/deprecation/reporting.rb#L21), generating the [deprecation warning](https://github.com/rails/rails/blob/12372c54828e2ac04b230cedd5cbb75181e62d29/activesupport/lib/active_support/deprecation/reporting.rb#L22), and [checking if the warning is disallowed](https://github.com/rails/rails/blob/12372c54828e2ac04b230cedd5cbb75181e62d29/activesupport/lib/active_support/deprecation/reporting.rb#L23). In very hot paths, this could cause performance issues. This PR lets you turn off deprecation reporting entirely for a specific environment. ```ruby config.active_support.report_deprecations = false ``` ^ so has the same outcome as: ```ruby config.active_support.deprecation = :silence config.active_support.disallowed_deprecation = :silence ``` But it will short circuit [here](https://github.com/rails/rails/blob/12372c54828e2ac04b230cedd5cbb75181e62d29/activesupport/lib/active_support/deprecation/reporting.rb#L19). --- activesupport/CHANGELOG.md | 23 +++++++++++++++++++ .../active_support/deprecation/behaviors.rb | 5 +++- activesupport/lib/active_support/railtie.rb | 22 +++++++++++------- activesupport/test/deprecation_test.rb | 4 ++++ guides/source/configuring.md | 20 ++++++++-------- .../config/environments/production.rb.tt | 10 ++------ .../test/application/configuration_test.rb | 10 ++++++++ 7 files changed, 66 insertions(+), 28 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 117f4c6daa..0542432bff 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,26 @@ +* Allow entirely opting out of deprecation warnings + + Previously if you did `app.config.active_support.deprecation = :silence`, some work would + still be done on each call to `ActiveSupport::Deprecation.warn`. In very hot paths, this could + cause performance issues. + + Now, you can make `ActiveSupport::Deprecation.warn` a no-op: + + ```ruby + config.active_support.report_deprecations = false + ``` + + This is the default in production for new apps. It is the equivalent to: + + ```ruby + config.active_support.deprecation = :silence + config.active_support.disallowed_deprecation = :silence + ``` + + but will take a more optimised code path. + + *Alex Ghiculescu* + * Faster tests by parallelizing only when overhead is justified by the number of them. diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb index 9d1fc78360..87eec6f404 100644 --- a/activesupport/lib/active_support/deprecation/behaviors.rb +++ b/activesupport/lib/active_support/deprecation/behaviors.rb @@ -54,7 +54,7 @@ module ActiveSupport # [+stderr+] Log all deprecation warnings to $stderr. # [+log+] Log all deprecation warnings to +Rails.logger+. # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+. - # [+silence+] Do nothing. + # [+silence+] Do nothing. On Rails, set `config.active_support.report_deprecations = false` to disable all behaviors. # # Setting behaviors only affects deprecations that happen after boot time. # For more information you can read the documentation of the +behavior=+ method. @@ -93,6 +93,9 @@ module ActiveSupport # ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) { # # custom stuff # } + # + # If you are using Rails, you can set `config.active_support.report_deprecations = false` to disable + # all deprecation behaviors. This is similar to the `silence` option but more performant. def behavior=(behavior) @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) } end diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb index ef2ffe7aa8..8d524a2037 100644 --- a/activesupport/lib/active_support/railtie.rb +++ b/activesupport/lib/active_support/railtie.rb @@ -39,16 +39,22 @@ module ActiveSupport end initializer "active_support.deprecation_behavior" do |app| - if deprecation = app.config.active_support.deprecation - ActiveSupport::Deprecation.behavior = deprecation - end + if app.config.active_support.report_deprecations == false + ActiveSupport::Deprecation.silenced = true + ActiveSupport::Deprecation.behavior = :silence + ActiveSupport::Deprecation.disallowed_behavior = :silence + else + if deprecation = app.config.active_support.deprecation + ActiveSupport::Deprecation.behavior = deprecation + end - if disallowed_deprecation = app.config.active_support.disallowed_deprecation - ActiveSupport::Deprecation.disallowed_behavior = disallowed_deprecation - end + if disallowed_deprecation = app.config.active_support.disallowed_deprecation + ActiveSupport::Deprecation.disallowed_behavior = disallowed_deprecation + end - if disallowed_warnings = app.config.active_support.disallowed_deprecation_warnings - ActiveSupport::Deprecation.disallowed_warnings = disallowed_warnings + if disallowed_warnings = app.config.active_support.disallowed_deprecation_warnings + ActiveSupport::Deprecation.disallowed_warnings = disallowed_warnings + end end end diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb index 11d9d3a137..3adab7b223 100644 --- a/activesupport/test/deprecation_test.rb +++ b/activesupport/test/deprecation_test.rb @@ -298,8 +298,12 @@ class DeprecationTest < ActiveSupport::TestCase end ActiveSupport::Deprecation.silenced = true + assert ActiveSupport::Deprecation.silenced + assert_not_deprecated { @dtc.partially } + ActiveSupport::Deprecation.silenced = false + assert_not ActiveSupport::Deprecation.silenced end def test_silence_threaded diff --git a/guides/source/configuring.md b/guides/source/configuring.md index e678935ac1..ae816f114b 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -922,20 +922,18 @@ There are a few configuration options available in Active Support: * `config.active_support.cache_format_version` specifies which version of the cache serializer to use. Possible values are `6.1` and `7.0`. +* `config.active_support.deprecation` configures the behavior of deprecation warnings. The options are `:raise`, `:stderr`, `:log`, `:notify`, or `:silence`. The default is `:stderr`. Alternatively, you can set `ActiveSupport::Deprecation.behavior`. + +* `config.active_support.disallowed_deprecation` configures the behavior of disallowed deprecation warnings. The options are `:raise`, `:stderr`, `:log`, `:notify`, or `:silence`. The default is `:raise`. Alternatively, you can set `ActiveSupport::Deprecation.disallowed_behavior`. + +* `config.active_support.disallowed_deprecation_warnings` configures deprecation warnings that the Application considers disallowed. This allows, for example, specific deprecations to be treated as hard failures. Alternatively, you can set `ActiveSupport::Deprecation.disallowed_warnings`. + +* `config.active_support.report_deprecations` allows you to disable all deprecation warnings (including disallowed deprecations); it makes `ActiveSupport::Deprecation.warn` a no-op. This is enabled by default in production. + * `ActiveSupport::Logger.silencer` is set to `false` to disable the ability to silence logging in a block. The default is `true`. * `ActiveSupport::Cache::Store.logger` specifies the logger to use within cache store operations. -* `ActiveSupport::Deprecation.behavior` alternative setter to `config.active_support.deprecation` which configures the behavior of deprecation warnings for Rails. - -* `ActiveSupport::Deprecation.disallowed_behavior` alternative setter to `config.active_support.disallowed_deprecation` which configures the behavior of disallowed deprecation warnings for Rails. - -* `ActiveSupport::Deprecation.disallowed_warnings` alternative setter to `config.active_support.disallowed_deprecation_warnings` which configures deprecation warnings that the Application considers disallowed. This allows, for example, specific deprecations to be treated as hard failures. - -* `ActiveSupport::Deprecation.silence` takes a block in which all deprecation warnings are silenced. - -* `ActiveSupport::Deprecation.silenced` sets whether or not to display deprecation warnings. The default is `false`. - * `ActiveSupport.utc_to_local_returns_utc_offset_times` configures `ActiveSupport::TimeZone.utc_to_local` to return a time with a UTC offset instead of a UTC time incorporating that offset. @@ -1673,7 +1671,7 @@ Below is a comprehensive list of all the initializers found in Rails in the orde * `i18n.callbacks`: In the development environment, sets up a `to_prepare` callback which will call `I18n.reload!` if any of the locales have changed since the last request. In production this callback will only run on the first request. -* `active_support.deprecation_behavior`: Sets up deprecation reporting for environments, defaulting to `:log` for development, `:notify` for production, and `:stderr` for test. If a value isn't set for `config.active_support.deprecation` then this initializer will prompt the user to configure this line in the current environment's `config/environments` file. Can be set to an array of values. This initializer also sets up behaviors for disallowed deprecations, defaulting to `:raise` for development and test and `:log` for production. Disallowed deprecation warnings default to an empty array. +* `active_support.deprecation_behavior`: Sets up deprecation reporting for environments, defaulting to `:log` for development, `:silence` for production, and `:stderr` for test. Can be set to an array of values. This initializer also sets up behaviors for disallowed deprecations, defaulting to `:raise` for development and test and `:silence` for production. Disallowed deprecation warnings default to an empty array. * `active_support.initialize_time_zone`: Sets the default time zone for the application based on the `config.time_zone` setting, which defaults to "UTC". diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index ac1f4040e5..2bc3486a91 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -84,14 +84,8 @@ Rails.application.configure do # the I18n.default_locale when a translation cannot be found). config.i18n.fallbacks = true - # Send deprecation notices to registered listeners. - config.active_support.deprecation = :notify - - # Log disallowed deprecations. - config.active_support.disallowed_deprecation = :log - - # Tell Active Support which deprecation messages to disallow. - config.active_support.disallowed_deprecation_warnings = [] + # Don't log any deprecations. + config.active_support.report_deprecations = false # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index a0e1dea61b..3040f5f035 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -3459,6 +3459,16 @@ module ApplicationTests assert_equal true, ActiveSupport::TimeWithZone.methods(false).include?(:name) end + test "can entirely opt out of ActiveSupport::Deprecations" do + add_to_config "config.active_support.report_deprecations = false" + + app "production" + + assert_equal true, ActiveSupport::Deprecation.silenced + assert_equal [ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:silence]], ActiveSupport::Deprecation.behavior + assert_equal [ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:silence]], ActiveSupport::Deprecation.disallowed_behavior + end + private def set_custom_config(contents, config_source = "custom".inspect) app_file "config/custom.yml", contents