activesupport 7.0.8.6 → 7.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +724 -311
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +25 -5
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +128 -0
- data/lib/active_support/cache/file_store.rb +36 -9
- data/lib/active_support/cache/mem_cache_store.rb +84 -68
- data/lib/active_support/cache/memory_store.rb +76 -24
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +126 -131
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +20 -8
- data/lib/active_support/cache.rb +304 -246
- data/lib/active_support/callbacks.rb +38 -18
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +2 -1
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +13 -10
- data/lib/active_support/core_ext/date/conversions.rb +1 -0
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +1 -10
- data/lib/active_support/core_ext/enumerable.rb +3 -75
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/delegation.rb +40 -11
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +15 -24
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +10 -2
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +3 -3
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- data/lib/active_support/core_ext/range/{overlaps.rb → overlap.rb} +5 -3
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +24 -12
- data/lib/active_support/core_ext/string/filters.rb +20 -14
- data/lib/active_support/core_ext/string/inflections.rb +16 -5
- data/lib/active_support/core_ext/string/output_safety.rb +38 -174
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +18 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +4 -4
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/current_attributes.rb +15 -6
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/deprecation/behaviors.rb +53 -32
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +3 -5
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
- data/lib/active_support/deprecation/reporting.rb +35 -21
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +104 -132
- data/lib/active_support/duration/iso8601_serializer.rb +0 -2
- data/lib/active_support/duration.rb +2 -1
- data/lib/active_support/encrypted_configuration.rb +30 -9
- data/lib/active_support/encrypted_file.rb +8 -3
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +121 -35
- data/lib/active_support/execution_wrapper.rb +4 -4
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +10 -2
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +35 -17
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +22 -10
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +6 -4
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +78 -33
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_thread_safe_level.rb +9 -21
- data/lib/active_support/message_encryptor.rb +197 -53
- data/lib/active_support/message_encryptors.rb +140 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +212 -93
- data/lib/active_support/message_verifiers.rb +134 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +111 -45
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +239 -81
- data/lib/active_support/notifications/instrumenter.rb +71 -14
- data/lib/active_support/notifications.rb +1 -1
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +14 -0
- data/lib/active_support/parameter_filter.rb +84 -69
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +33 -21
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +3 -1
- data/lib/active_support/subscriber.rb +9 -27
- data/lib/active_support/syntax_error_proxy.rb +49 -0
- data/lib/active_support/tagged_logging.rb +60 -24
- data/lib/active_support/test_case.rb +153 -6
- data/lib/active_support/testing/assertions.rb +25 -9
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +25 -25
- data/lib/active_support/testing/error_reporter_assertions.rb +108 -0
- data/lib/active_support/testing/isolation.rb +1 -1
- data/lib/active_support/testing/method_call_assertions.rb +21 -8
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +38 -0
- data/lib/active_support/testing/time_helpers.rb +32 -14
- data/lib/active_support/time_with_zone.rb +4 -14
- data/lib/active_support/values/time_zone.rb +9 -7
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +2 -2
- data/lib/active_support.rb +13 -3
- metadata +106 -21
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/per_thread_registry.rb +0 -65
@@ -4,25 +4,30 @@ require "fiber"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module IsolatedExecutionState # :nodoc:
|
7
|
-
@isolation_level =
|
7
|
+
@isolation_level = nil
|
8
8
|
|
9
9
|
Thread.attr_accessor :active_support_execution_state
|
10
10
|
Fiber.attr_accessor :active_support_execution_state
|
11
11
|
|
12
12
|
class << self
|
13
|
-
attr_reader :isolation_level
|
13
|
+
attr_reader :isolation_level, :scope
|
14
14
|
|
15
15
|
def isolation_level=(level)
|
16
|
+
return if level == @isolation_level
|
17
|
+
|
16
18
|
unless %i(thread fiber).include?(level)
|
17
19
|
raise ArgumentError, "isolation_level must be `:thread` or `:fiber`, got: `#{level.inspect}`"
|
18
20
|
end
|
19
21
|
|
20
|
-
if
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
clear if @isolation_level
|
23
|
+
|
24
|
+
@scope =
|
25
|
+
case level
|
26
|
+
when :thread; Thread
|
27
|
+
when :fiber; Fiber
|
28
|
+
end
|
29
|
+
|
30
|
+
@isolation_level = level
|
26
31
|
end
|
27
32
|
|
28
33
|
def unique_id
|
@@ -30,43 +35,42 @@ module ActiveSupport
|
|
30
35
|
end
|
31
36
|
|
32
37
|
def [](key)
|
33
|
-
|
38
|
+
state[key]
|
34
39
|
end
|
35
40
|
|
36
41
|
def []=(key, value)
|
37
|
-
|
42
|
+
state[key] = value
|
38
43
|
end
|
39
44
|
|
40
45
|
def key?(key)
|
41
|
-
|
46
|
+
state.key?(key)
|
42
47
|
end
|
43
48
|
|
44
49
|
def delete(key)
|
45
|
-
|
50
|
+
state.delete(key)
|
46
51
|
end
|
47
52
|
|
48
53
|
def clear
|
49
|
-
|
54
|
+
state.clear
|
55
|
+
end
|
56
|
+
|
57
|
+
def context
|
58
|
+
scope.current
|
50
59
|
end
|
51
60
|
|
52
61
|
def share_with(other)
|
53
62
|
# Action Controller streaming spawns a new thread and copy thread locals.
|
54
63
|
# We do the same here for backward compatibility, but this is very much a hack
|
55
64
|
# and streaming should be rethought.
|
56
|
-
context = @isolation_level == :thread ? Thread.current : Fiber.current
|
57
65
|
context.active_support_execution_state = other.active_support_execution_state.dup
|
58
66
|
end
|
59
67
|
|
60
68
|
private
|
61
|
-
def
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
def current_fiber
|
66
|
-
Fiber.current.active_support_execution_state ||= {}
|
69
|
+
def state
|
70
|
+
context.active_support_execution_state ||= {}
|
67
71
|
end
|
68
|
-
|
69
|
-
alias_method :current, :current_thread
|
70
72
|
end
|
73
|
+
|
74
|
+
self.isolation_level = :thread
|
71
75
|
end
|
72
76
|
end
|
@@ -5,7 +5,7 @@ require "active_support/core_ext/module/delegation"
|
|
5
5
|
require "json"
|
6
6
|
|
7
7
|
module ActiveSupport
|
8
|
-
# Look for and parse
|
8
|
+
# Look for and parse JSON strings that look like ISO 8601 times.
|
9
9
|
mattr_accessor :parse_json_times
|
10
10
|
|
11
11
|
module JSON
|
@@ -28,6 +28,7 @@ module ActiveSupport
|
|
28
28
|
data
|
29
29
|
end
|
30
30
|
end
|
31
|
+
alias_method :load, :decode
|
31
32
|
|
32
33
|
# Returns the class of the error that will be raised when there is an
|
33
34
|
# error in decoding JSON. Using this method means you won't directly
|
@@ -18,8 +18,11 @@ module ActiveSupport
|
|
18
18
|
#
|
19
19
|
# ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
|
20
20
|
# # => "{\"team\":\"rails\",\"players\":\"36\"}"
|
21
|
-
|
22
|
-
|
21
|
+
class << self
|
22
|
+
def encode(value, options = nil)
|
23
|
+
Encoding.json_encoder.new(options).encode(value)
|
24
|
+
end
|
25
|
+
alias_method :dump, :encode
|
23
26
|
end
|
24
27
|
|
25
28
|
module Encoding # :nodoc:
|
@@ -32,49 +35,27 @@ module ActiveSupport
|
|
32
35
|
|
33
36
|
# Encode the given object into a JSON string
|
34
37
|
def encode(value)
|
35
|
-
|
36
|
-
|
38
|
+
unless options.empty?
|
39
|
+
value = value.as_json(options.dup)
|
40
|
+
end
|
41
|
+
json = stringify(jsonify(value))
|
37
42
|
|
38
|
-
private
|
39
43
|
# Rails does more escaping than the JSON gem natively does (we
|
40
44
|
# escape \u2028 and \u2029 and optionally >, <, & to work around
|
41
45
|
# certain browser problems).
|
42
|
-
|
43
|
-
"
|
44
|
-
"
|
45
|
-
"
|
46
|
-
"<" => '\u003c',
|
47
|
-
"&" => '\u0026',
|
48
|
-
}
|
49
|
-
|
50
|
-
ESCAPE_REGEX_WITH_HTML_ENTITIES = /[\u2028\u2029><&]/u
|
51
|
-
ESCAPE_REGEX_WITHOUT_HTML_ENTITIES = /[\u2028\u2029]/u
|
52
|
-
|
53
|
-
# This class wraps all the strings we see and does the extra escaping
|
54
|
-
class EscapedString < String # :nodoc:
|
55
|
-
def to_json(*)
|
56
|
-
if Encoding.escape_html_entities_in_json
|
57
|
-
s = super
|
58
|
-
s.gsub! ESCAPE_REGEX_WITH_HTML_ENTITIES, ESCAPED_CHARS
|
59
|
-
s
|
60
|
-
else
|
61
|
-
s = super
|
62
|
-
s.gsub! ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, ESCAPED_CHARS
|
63
|
-
s
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def to_s
|
68
|
-
self
|
69
|
-
end
|
46
|
+
if Encoding.escape_html_entities_in_json
|
47
|
+
json.gsub!(">", '\u003e')
|
48
|
+
json.gsub!("<", '\u003c')
|
49
|
+
json.gsub!("&", '\u0026')
|
70
50
|
end
|
51
|
+
json.gsub!("\u2028", '\u2028')
|
52
|
+
json.gsub!("\u2029", '\u2029')
|
53
|
+
json
|
54
|
+
end
|
71
55
|
|
72
|
-
|
73
|
-
private_constant :ESCAPED_CHARS, :ESCAPE_REGEX_WITH_HTML_ENTITIES,
|
74
|
-
:ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, :EscapedString
|
75
|
-
|
56
|
+
private
|
76
57
|
# Convert an object into a "JSON-ready" representation composed of
|
77
|
-
# primitives like Hash, Array, String, Numeric,
|
58
|
+
# primitives like Hash, Array, String, Symbol, Numeric,
|
78
59
|
# and +true+/+false+/+nil+.
|
79
60
|
# Recursively calls #as_json to the object to recursively build a
|
80
61
|
# fully JSON-ready object.
|
@@ -88,14 +69,15 @@ module ActiveSupport
|
|
88
69
|
# calls.
|
89
70
|
def jsonify(value)
|
90
71
|
case value
|
91
|
-
when String
|
92
|
-
|
93
|
-
when Numeric
|
72
|
+
when String, Integer, Symbol, nil, true, false
|
73
|
+
value
|
74
|
+
when Numeric
|
94
75
|
value.as_json
|
95
76
|
when Hash
|
96
77
|
result = {}
|
97
78
|
value.each do |k, v|
|
98
|
-
|
79
|
+
k = k.to_s unless Symbol === k || String === k
|
80
|
+
result[k] = jsonify(v)
|
99
81
|
end
|
100
82
|
result
|
101
83
|
when Array
|
@@ -124,7 +106,7 @@ module ActiveSupport
|
|
124
106
|
# Defaults to 3 (equivalent to millisecond precision)
|
125
107
|
attr_accessor :time_precision
|
126
108
|
|
127
|
-
# Sets the encoder used by Rails to encode Ruby objects into JSON strings
|
109
|
+
# Sets the encoder used by \Rails to encode Ruby objects into JSON strings
|
128
110
|
# in +Object#to_json+ and +ActiveSupport::JSON.encode+.
|
129
111
|
attr_accessor :json_encoder
|
130
112
|
end
|
@@ -4,9 +4,11 @@ require "concurrent/map"
|
|
4
4
|
require "openssl"
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
|
+
# = Key Generator
|
8
|
+
#
|
7
9
|
# KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2.
|
8
10
|
# It can be used to derive a number of keys for various purposes from a given secret.
|
9
|
-
# This lets Rails applications have a single secure secret, but avoid reusing that
|
11
|
+
# This lets \Rails applications have a single secure secret, but avoid reusing that
|
10
12
|
# key in multiple incompatible contexts.
|
11
13
|
class KeyGenerator
|
12
14
|
class << self
|
@@ -39,8 +41,14 @@ module ActiveSupport
|
|
39
41
|
def generate_key(salt, key_size = 64)
|
40
42
|
OpenSSL::PKCS5.pbkdf2_hmac(@secret, salt, @iterations, key_size, @hash_digest_class.new)
|
41
43
|
end
|
44
|
+
|
45
|
+
def inspect # :nodoc:
|
46
|
+
"#<#{self.class.name}:#{'%#016x' % (object_id << 1)}>"
|
47
|
+
end
|
42
48
|
end
|
43
49
|
|
50
|
+
# = Caching Key Generator
|
51
|
+
#
|
44
52
|
# CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
|
45
53
|
# re-executing the key generation process when it's called using the same +salt+ and
|
46
54
|
# +key_size+.
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
|
-
#
|
4
|
+
# = Lazy Load Hooks
|
5
|
+
#
|
6
|
+
# LazyLoadHooks allows \Rails to lazily load a lot of components and thus
|
5
7
|
# making the app boot faster. Because of this feature now there is no need to
|
6
|
-
# require
|
8
|
+
# require +ActiveRecord::Base+ at boot time purely to apply
|
7
9
|
# configuration. Instead a hook is registered that applies configuration once
|
8
|
-
#
|
10
|
+
# +ActiveRecord::Base+ is loaded. Here +ActiveRecord::Base+ is
|
9
11
|
# used as example but this feature can be applied elsewhere too.
|
10
12
|
#
|
11
13
|
# Here is an example where on_load method is called to register a hook.
|
@@ -47,7 +49,7 @@ module ActiveSupport
|
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
|
-
# Declares a block that will be executed when a Rails component is fully
|
52
|
+
# Declares a block that will be executed when a \Rails component is fully
|
51
53
|
# loaded. If the component has already loaded, the block is executed
|
52
54
|
# immediately.
|
53
55
|
#
|
@@ -57,6 +57,7 @@ en:
|
|
57
57
|
format:
|
58
58
|
# Where is the currency sign? %u is the currency unit, %n is the number (default: $5.00)
|
59
59
|
format: "%u%n"
|
60
|
+
negative_format: "-%u%n"
|
60
61
|
unit: "$"
|
61
62
|
# These six are to override number.format and are optional
|
62
63
|
separator: "."
|
@@ -112,6 +113,7 @@ en:
|
|
112
113
|
tb: "TB"
|
113
114
|
pb: "PB"
|
114
115
|
eb: "EB"
|
116
|
+
zb: "ZB"
|
115
117
|
# Used in NumberHelper.number_to_human()
|
116
118
|
decimal_units:
|
117
119
|
format: "%n %u"
|
@@ -3,9 +3,12 @@
|
|
3
3
|
require "active_support/core_ext/module/attribute_accessors"
|
4
4
|
require "active_support/core_ext/class/attribute"
|
5
5
|
require "active_support/subscriber"
|
6
|
+
require "active_support/deprecation/proxy_wrappers"
|
6
7
|
|
7
8
|
module ActiveSupport
|
8
|
-
#
|
9
|
+
# = Active Support Log \Subscriber
|
10
|
+
#
|
11
|
+
# +ActiveSupport::LogSubscriber+ is an object set to consume
|
9
12
|
# ActiveSupport::Notifications with the sole purpose of logging them.
|
10
13
|
# The log subscriber dispatches notifications to a registered object based
|
11
14
|
# on its given namespace.
|
@@ -15,29 +18,23 @@ module ActiveSupport
|
|
15
18
|
#
|
16
19
|
# module ActiveRecord
|
17
20
|
# class LogSubscriber < ActiveSupport::LogSubscriber
|
21
|
+
# attach_to :active_record
|
22
|
+
#
|
18
23
|
# def sql(event)
|
19
24
|
# info "#{event.payload[:name]} (#{event.duration}) #{event.payload[:sql]}"
|
20
25
|
# end
|
21
26
|
# end
|
22
27
|
# end
|
23
28
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# ActiveRecord::LogSubscriber.attach_to :active_record
|
29
|
+
# ActiveRecord::LogSubscriber.logger must be set as well, but it is assigned
|
30
|
+
# automatically in a \Rails environment.
|
27
31
|
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# A logger also needs to be set with <tt>ActiveRecord::LogSubscriber.logger=</tt>.
|
33
|
-
# This is assigned automatically in a Rails environment.
|
34
|
-
#
|
35
|
-
# After configured, whenever a <tt>"sql.active_record"</tt> notification is published,
|
36
|
-
# it will properly dispatch the event
|
37
|
-
# (<tt>ActiveSupport::Notifications::Event</tt>) to the sql method.
|
32
|
+
# After configured, whenever a <tt>"sql.active_record"</tt> notification is
|
33
|
+
# published, it will properly dispatch the event
|
34
|
+
# (ActiveSupport::Notifications::Event) to the +sql+ method.
|
38
35
|
#
|
39
36
|
# Being an ActiveSupport::Notifications consumer,
|
40
|
-
#
|
37
|
+
# +ActiveSupport::LogSubscriber+ exposes a simple interface to check if
|
41
38
|
# instrumented code raises an exception. It is common to log a different
|
42
39
|
# message in case of an error, and this can be achieved by extending
|
43
40
|
# the previous example:
|
@@ -59,15 +56,24 @@ module ActiveSupport
|
|
59
56
|
# end
|
60
57
|
# end
|
61
58
|
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
59
|
+
# +ActiveSupport::LogSubscriber+ also has some helpers to deal with
|
60
|
+
# logging. For example, ActiveSupport::LogSubscriber.flush_all! will ensure
|
61
|
+
# that all logs are flushed, and it is called in Rails::Rack::Logger after a
|
62
|
+
# request finishes.
|
65
63
|
class LogSubscriber < Subscriber
|
66
64
|
# Embed in a String to clear all previous ANSI sequences.
|
67
|
-
CLEAR
|
68
|
-
BOLD
|
69
|
-
|
70
|
-
#
|
65
|
+
CLEAR = ActiveSupport::Deprecation::DeprecatedObjectProxy.new("\e[0m", "CLEAR is deprecated! Use MODES[:clear] instead.", ActiveSupport.deprecator)
|
66
|
+
BOLD = ActiveSupport::Deprecation::DeprecatedObjectProxy.new("\e[1m", "BOLD is deprecated! Use MODES[:bold] instead.", ActiveSupport.deprecator)
|
67
|
+
|
68
|
+
# ANSI sequence modes
|
69
|
+
MODES = {
|
70
|
+
clear: 0,
|
71
|
+
bold: 1,
|
72
|
+
italic: 3,
|
73
|
+
underline: 4,
|
74
|
+
}
|
75
|
+
|
76
|
+
# ANSI sequence colors
|
71
77
|
BLACK = "\e[30m"
|
72
78
|
RED = "\e[31m"
|
73
79
|
GREEN = "\e[32m"
|
@@ -78,6 +84,7 @@ module ActiveSupport
|
|
78
84
|
WHITE = "\e[37m"
|
79
85
|
|
80
86
|
mattr_accessor :colorize_logging, default: true
|
87
|
+
class_attribute :log_levels, instance_accessor: false, default: {} # :nodoc:
|
81
88
|
|
82
89
|
class << self
|
83
90
|
def logger
|
@@ -86,6 +93,12 @@ module ActiveSupport
|
|
86
93
|
end
|
87
94
|
end
|
88
95
|
|
96
|
+
def attach_to(...) # :nodoc:
|
97
|
+
result = super
|
98
|
+
set_event_levels
|
99
|
+
result
|
100
|
+
end
|
101
|
+
|
89
102
|
attr_writer :logger
|
90
103
|
|
91
104
|
def log_subscribers
|
@@ -101,20 +114,36 @@ module ActiveSupport
|
|
101
114
|
def fetch_public_methods(subscriber, inherit_all)
|
102
115
|
subscriber.public_methods(inherit_all) - LogSubscriber.public_instance_methods(true)
|
103
116
|
end
|
117
|
+
|
118
|
+
def set_event_levels
|
119
|
+
if subscriber
|
120
|
+
subscriber.event_levels = log_levels.transform_keys { |k| "#{k}.#{namespace}" }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def subscribe_log_level(method, level)
|
125
|
+
self.log_levels = log_levels.merge(method => ::Logger.const_get(level.upcase))
|
126
|
+
set_event_levels
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def initialize
|
131
|
+
super
|
132
|
+
@event_levels = {}
|
104
133
|
end
|
105
134
|
|
106
135
|
def logger
|
107
136
|
LogSubscriber.logger
|
108
137
|
end
|
109
138
|
|
110
|
-
def
|
111
|
-
|
139
|
+
def silenced?(event)
|
140
|
+
logger.nil? || logger.level > @event_levels.fetch(event, Float::INFINITY)
|
112
141
|
end
|
113
142
|
|
114
|
-
def
|
143
|
+
def call(event)
|
115
144
|
super if logger
|
116
145
|
rescue => e
|
117
|
-
log_exception(name, e)
|
146
|
+
log_exception(event.name, e)
|
118
147
|
end
|
119
148
|
|
120
149
|
def publish_event(event)
|
@@ -123,6 +152,8 @@ module ActiveSupport
|
|
123
152
|
log_exception(event.name, e)
|
124
153
|
end
|
125
154
|
|
155
|
+
attr_writer :event_levels # :nodoc:
|
156
|
+
|
126
157
|
private
|
127
158
|
%w(info debug warn error fatal unknown).each do |level|
|
128
159
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
@@ -132,15 +163,29 @@ module ActiveSupport
|
|
132
163
|
METHOD
|
133
164
|
end
|
134
165
|
|
135
|
-
# Set color by using a symbol or one of the defined constants.
|
136
|
-
#
|
137
|
-
#
|
138
|
-
|
139
|
-
def color(text, color, bold = false) # :doc:
|
166
|
+
# Set color by using a symbol or one of the defined constants. Set modes
|
167
|
+
# by specifying bold, italic, or underline options. Inspired by Highline,
|
168
|
+
# this method will automatically clear formatting at the end of the returned String.
|
169
|
+
def color(text, color, mode_options = {}) # :doc:
|
140
170
|
return text unless colorize_logging
|
141
171
|
color = self.class.const_get(color.upcase) if color.is_a?(Symbol)
|
142
|
-
|
143
|
-
"#{
|
172
|
+
mode = mode_from(mode_options)
|
173
|
+
clear = "\e[#{MODES[:clear]}m"
|
174
|
+
"#{mode}#{color}#{text}#{clear}"
|
175
|
+
end
|
176
|
+
|
177
|
+
def mode_from(options)
|
178
|
+
if options.is_a?(TrueClass) || options.is_a?(FalseClass)
|
179
|
+
ActiveSupport.deprecator.warn(<<~MSG.squish)
|
180
|
+
Bolding log text with a positional boolean is deprecated and will be removed
|
181
|
+
in Rails 7.2. Use an option hash instead (eg. `color("my text", :red, bold: true)`).
|
182
|
+
MSG
|
183
|
+
options = { bold: options }
|
184
|
+
end
|
185
|
+
|
186
|
+
modes = MODES.values_at(*options.compact_blank.keys)
|
187
|
+
|
188
|
+
"\e[#{modes.join(";")}m" if modes.any?
|
144
189
|
end
|
145
190
|
|
146
191
|
def log_exception(name, e)
|
@@ -18,7 +18,7 @@ module ActiveSupport
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def local_level
|
21
|
-
IsolatedExecutionState[
|
21
|
+
IsolatedExecutionState[local_level_key]
|
22
22
|
end
|
23
23
|
|
24
24
|
def local_level=(level)
|
@@ -30,7 +30,11 @@ module ActiveSupport
|
|
30
30
|
else
|
31
31
|
raise ArgumentError, "Invalid log level: #{level.inspect}"
|
32
32
|
end
|
33
|
-
|
33
|
+
if level.nil?
|
34
|
+
IsolatedExecutionState.delete(local_level_key)
|
35
|
+
else
|
36
|
+
IsolatedExecutionState[local_level_key] = level
|
37
|
+
end
|
34
38
|
end
|
35
39
|
|
36
40
|
def level
|
@@ -45,25 +49,9 @@ module ActiveSupport
|
|
45
49
|
self.local_level = old_local_level
|
46
50
|
end
|
47
51
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
severity ||= UNKNOWN
|
52
|
-
progname ||= @progname
|
53
|
-
|
54
|
-
return true if @logdev.nil? || severity < level
|
55
|
-
|
56
|
-
if message.nil?
|
57
|
-
if block_given?
|
58
|
-
message = yield
|
59
|
-
else
|
60
|
-
message = progname
|
61
|
-
progname = @progname
|
62
|
-
end
|
52
|
+
private
|
53
|
+
def local_level_key
|
54
|
+
@local_level_key ||= :"logger_thread_safe_level_#{object_id}"
|
63
55
|
end
|
64
|
-
|
65
|
-
@logdev.write \
|
66
|
-
format_message(format_severity(severity), Time.now, progname, message)
|
67
|
-
end
|
68
56
|
end
|
69
57
|
end
|