activesupport 6.0.3.7 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +220 -533
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_support/actionable_error.rb +1 -1
- data/lib/active_support/array_inquirer.rb +2 -2
- data/lib/active_support/backtrace_cleaner.rb +3 -3
- data/lib/active_support/benchmarkable.rb +3 -3
- data/lib/active_support/cache/file_store.rb +18 -11
- data/lib/active_support/cache/mem_cache_store.rb +143 -37
- data/lib/active_support/cache/memory_store.rb +56 -28
- data/lib/active_support/cache/null_store.rb +10 -2
- data/lib/active_support/cache/redis_cache_store.rb +63 -88
- data/lib/active_support/cache/strategy/local_cache.rb +46 -57
- data/lib/active_support/cache.rb +273 -82
- data/lib/active_support/callbacks.rb +226 -118
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +49 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +9 -6
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +9 -7
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +21 -40
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +4 -4
- data/lib/active_support/core_ext/date/conversions.rb +5 -4
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date.rb +1 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +5 -5
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +39 -13
- data/lib/active_support/core_ext/enumerable.rb +139 -15
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- data/lib/active_support/core_ext/hash/conversions.rb +2 -2
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +2 -2
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +25 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +26 -13
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +40 -36
- data/lib/active_support/core_ext/module/introspection.rb +1 -25
- data/lib/active_support/core_ext/name_error.rb +23 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +79 -72
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +11 -0
- data/lib/active_support/core_ext/object/json.rb +42 -26
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with_options.rb +20 -1
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +6 -25
- data/lib/active_support/core_ext/range/conversions.rb +8 -8
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
- data/lib/active_support/core_ext/range.rb +1 -1
- data/lib/active_support/core_ext/regexp.rb +8 -1
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +39 -5
- data/lib/active_support/core_ext/string/inquiry.rb +1 -0
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +69 -45
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +26 -6
- data/lib/active_support/core_ext/time/conversions.rb +6 -3
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +4 -19
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +3 -23
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +39 -16
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -764
- data/lib/active_support/deprecation/behaviors.rb +19 -3
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +0 -1
- data/lib/active_support/deprecation/method_wrappers.rb +6 -5
- data/lib/active_support/deprecation/proxy_wrappers.rb +4 -4
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/descendants_tracker.rb +177 -64
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +24 -10
- data/lib/active_support/duration.rb +134 -55
- data/lib/active_support/encrypted_configuration.rb +11 -1
- data/lib/active_support/encrypted_file.rb +20 -3
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +70 -134
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +30 -4
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +51 -25
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +14 -19
- data/lib/active_support/inflector/inflections.rb +24 -9
- data/lib/active_support/inflector/methods.rb +29 -49
- data/lib/active_support/inflector/transliterate.rb +4 -4
- data/lib/active_support/isolated_execution_state.rb +56 -0
- data/lib/active_support/json/decoding.rb +4 -4
- data/lib/active_support/json/encoding.rb +8 -4
- data/lib/active_support/key_generator.rb +19 -2
- data/lib/active_support/locale/en.yml +8 -4
- data/lib/active_support/log_subscriber.rb +21 -3
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_silence.rb +2 -26
- data/lib/active_support/logger_thread_safe_level.rb +34 -21
- data/lib/active_support/message_encryptor.rb +12 -10
- data/lib/active_support/message_verifier.rb +50 -18
- data/lib/active_support/messages/metadata.rb +11 -3
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +6 -5
- data/lib/active_support/multibyte/chars.rb +13 -52
- data/lib/active_support/multibyte/unicode.rb +1 -87
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +110 -69
- data/lib/active_support/notifications/instrumenter.rb +37 -29
- data/lib/active_support/notifications.rb +47 -26
- data/lib/active_support/number_helper/number_converter.rb +2 -4
- data/lib/active_support/number_helper/number_to_currency_converter.rb +10 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
- data/lib/active_support/number_helper/rounding_helper.rb +12 -32
- data/lib/active_support/number_helper.rb +29 -16
- data/lib/active_support/option_merger.rb +9 -16
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +8 -2
- data/lib/active_support/parameter_filter.rb +21 -11
- data/lib/active_support/per_thread_registry.rb +6 -1
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +77 -5
- data/lib/active_support/rescuable.rb +6 -6
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +2 -2
- data/lib/active_support/subscriber.rb +19 -25
- data/lib/active_support/tagged_logging.rb +31 -6
- data/lib/active_support/test_case.rb +9 -21
- data/lib/active_support/testing/assertions.rb +49 -12
- data/lib/active_support/testing/deprecation.rb +52 -1
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +5 -5
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +16 -95
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/stream.rb +3 -5
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +53 -5
- data/lib/active_support/time_with_zone.rb +120 -55
- data/lib/active_support/values/time_zone.rb +49 -18
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +4 -4
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +9 -2
- data/lib/active_support/xml_mini.rb +5 -4
- data/lib/active_support.rb +29 -1
- metadata +46 -45
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
- data/lib/active_support/core_ext/hash/compact.rb +0 -5
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
- data/lib/active_support/core_ext/marshal.rb +0 -24
- data/lib/active_support/core_ext/module/reachable.rb +0 -6
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
- data/lib/active_support/core_ext/range/include_range.rb +0 -9
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -3,9 +3,20 @@
|
|
3
3
|
require "mutex_m"
|
4
4
|
require "concurrent/map"
|
5
5
|
require "set"
|
6
|
+
require "active_support/core_ext/object/try"
|
6
7
|
|
7
8
|
module ActiveSupport
|
8
9
|
module Notifications
|
10
|
+
class InstrumentationSubscriberError < RuntimeError
|
11
|
+
attr_reader :exceptions
|
12
|
+
|
13
|
+
def initialize(exceptions)
|
14
|
+
@exceptions = exceptions
|
15
|
+
exception_class_names = exceptions.map { |e| e.class.name }
|
16
|
+
super "Exception(s) occurred within instrumentation subscribers: #{exception_class_names.join(', ')}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
9
20
|
# This is a default queue implementation that ships with Notifications.
|
10
21
|
# It just pushes events to all registered log subscribers.
|
11
22
|
#
|
@@ -20,15 +31,18 @@ module ActiveSupport
|
|
20
31
|
super
|
21
32
|
end
|
22
33
|
|
23
|
-
def subscribe(pattern = nil, callable = nil, &block)
|
24
|
-
subscriber = Subscribers.new(pattern, callable || block)
|
34
|
+
def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
|
35
|
+
subscriber = Subscribers.new(pattern, callable || block, monotonic)
|
25
36
|
synchronize do
|
26
|
-
|
37
|
+
case pattern
|
38
|
+
when String
|
27
39
|
@string_subscribers[pattern] << subscriber
|
28
40
|
@listeners_for.delete(pattern)
|
29
|
-
|
41
|
+
when NilClass, Regexp
|
30
42
|
@other_subscribers << subscriber
|
31
43
|
@listeners_for.clear
|
44
|
+
else
|
45
|
+
raise ArgumentError, "pattern must be specified as a String, Regexp or empty"
|
32
46
|
end
|
33
47
|
end
|
34
48
|
subscriber
|
@@ -55,15 +69,40 @@ module ActiveSupport
|
|
55
69
|
end
|
56
70
|
|
57
71
|
def start(name, id, payload)
|
58
|
-
listeners_for(name)
|
72
|
+
iterate_guarding_exceptions(listeners_for(name)) { |s| s.start(name, id, payload) }
|
59
73
|
end
|
60
74
|
|
61
75
|
def finish(name, id, payload, listeners = listeners_for(name))
|
62
|
-
listeners
|
76
|
+
iterate_guarding_exceptions(listeners) { |s| s.finish(name, id, payload) }
|
63
77
|
end
|
64
78
|
|
65
79
|
def publish(name, *args)
|
66
|
-
listeners_for(name)
|
80
|
+
iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name, *args) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def publish_event(event)
|
84
|
+
iterate_guarding_exceptions(listeners_for(event.name)) { |s| s.publish_event(event) }
|
85
|
+
end
|
86
|
+
|
87
|
+
def iterate_guarding_exceptions(listeners)
|
88
|
+
exceptions = nil
|
89
|
+
|
90
|
+
listeners.each do |s|
|
91
|
+
yield s
|
92
|
+
rescue Exception => e
|
93
|
+
exceptions ||= []
|
94
|
+
exceptions << e
|
95
|
+
end
|
96
|
+
|
97
|
+
if exceptions
|
98
|
+
if exceptions.size == 1
|
99
|
+
raise exceptions.first
|
100
|
+
else
|
101
|
+
raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
listeners
|
67
106
|
end
|
68
107
|
|
69
108
|
def listeners_for(name)
|
@@ -84,43 +123,36 @@ module ActiveSupport
|
|
84
123
|
end
|
85
124
|
|
86
125
|
module Subscribers # :nodoc:
|
87
|
-
def self.new(pattern, listener)
|
88
|
-
subscriber_class = Timed
|
126
|
+
def self.new(pattern, listener, monotonic)
|
127
|
+
subscriber_class = monotonic ? MonotonicTimed : Timed
|
89
128
|
|
90
129
|
if listener.respond_to?(:start) && listener.respond_to?(:finish)
|
91
130
|
subscriber_class = Evented
|
92
131
|
else
|
93
|
-
# Doing
|
94
|
-
# `proc {
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
132
|
+
# Doing this to detect a single argument block or callable
|
133
|
+
# like `proc { |x| }` vs `proc { |*x| }`, `proc { |**x| }`,
|
134
|
+
# or `proc { |x, **y| }`
|
135
|
+
procish = listener.respond_to?(:parameters) ? listener : listener.method(:call)
|
136
|
+
|
137
|
+
if procish.arity == 1 && procish.parameters.length == 1
|
138
|
+
subscriber_class = EventObject
|
100
139
|
end
|
101
140
|
end
|
102
141
|
|
103
|
-
|
142
|
+
subscriber_class.new(pattern, listener)
|
104
143
|
end
|
105
144
|
|
106
|
-
|
107
|
-
wrap_all pattern, EventObject.new(pattern, block)
|
108
|
-
end
|
109
|
-
|
110
|
-
def self.wrap_all(pattern, subscriber)
|
111
|
-
unless pattern
|
112
|
-
AllMessages.new(subscriber)
|
113
|
-
else
|
114
|
-
subscriber
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
class Matcher #:nodoc:
|
145
|
+
class Matcher # :nodoc:
|
119
146
|
attr_reader :pattern, :exclusions
|
120
147
|
|
121
148
|
def self.wrap(pattern)
|
122
|
-
|
123
|
-
|
149
|
+
if String === pattern
|
150
|
+
pattern
|
151
|
+
elsif pattern.nil?
|
152
|
+
AllMessages.new
|
153
|
+
else
|
154
|
+
new(pattern)
|
155
|
+
end
|
124
156
|
end
|
125
157
|
|
126
158
|
def initialize(pattern)
|
@@ -135,15 +167,26 @@ module ActiveSupport
|
|
135
167
|
def ===(name)
|
136
168
|
pattern === name && !exclusions.include?(name)
|
137
169
|
end
|
170
|
+
|
171
|
+
class AllMessages
|
172
|
+
def ===(name)
|
173
|
+
true
|
174
|
+
end
|
175
|
+
|
176
|
+
def unsubscribe!(*)
|
177
|
+
false
|
178
|
+
end
|
179
|
+
end
|
138
180
|
end
|
139
181
|
|
140
|
-
class Evented
|
182
|
+
class Evented # :nodoc:
|
141
183
|
attr_reader :pattern
|
142
184
|
|
143
185
|
def initialize(pattern, delegate)
|
144
186
|
@pattern = Matcher.wrap(pattern)
|
145
187
|
@delegate = delegate
|
146
188
|
@can_publish = delegate.respond_to?(:publish)
|
189
|
+
@can_publish_event = delegate.respond_to?(:publish_event)
|
147
190
|
end
|
148
191
|
|
149
192
|
def publish(name, *args)
|
@@ -152,6 +195,14 @@ module ActiveSupport
|
|
152
195
|
end
|
153
196
|
end
|
154
197
|
|
198
|
+
def publish_event(event)
|
199
|
+
if @can_publish_event
|
200
|
+
@delegate.publish_event event
|
201
|
+
else
|
202
|
+
publish(event.name, event.time, event.end, event.transaction_id, event.payload)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
155
206
|
def start(name, id, payload)
|
156
207
|
@delegate.start name, id, payload
|
157
208
|
end
|
@@ -164,10 +215,6 @@ module ActiveSupport
|
|
164
215
|
pattern === name
|
165
216
|
end
|
166
217
|
|
167
|
-
def matches?(name)
|
168
|
-
pattern && pattern === name
|
169
|
-
end
|
170
|
-
|
171
218
|
def unsubscribe!(name)
|
172
219
|
pattern.unsubscribe!(name)
|
173
220
|
end
|
@@ -179,65 +226,59 @@ module ActiveSupport
|
|
179
226
|
end
|
180
227
|
|
181
228
|
def start(name, id, payload)
|
182
|
-
timestack =
|
229
|
+
timestack = IsolatedExecutionState[:_timestack] ||= []
|
183
230
|
timestack.push Time.now
|
184
231
|
end
|
185
232
|
|
186
233
|
def finish(name, id, payload)
|
187
|
-
timestack =
|
234
|
+
timestack = IsolatedExecutionState[:_timestack]
|
188
235
|
started = timestack.pop
|
189
236
|
@delegate.call(name, started, Time.now, id, payload)
|
190
237
|
end
|
191
238
|
end
|
192
239
|
|
240
|
+
class MonotonicTimed < Evented # :nodoc:
|
241
|
+
def publish(name, *args)
|
242
|
+
@delegate.call name, *args
|
243
|
+
end
|
244
|
+
|
245
|
+
def start(name, id, payload)
|
246
|
+
timestack = IsolatedExecutionState[:_timestack_monotonic] ||= []
|
247
|
+
timestack.push Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
248
|
+
end
|
249
|
+
|
250
|
+
def finish(name, id, payload)
|
251
|
+
timestack = IsolatedExecutionState[:_timestack_monotonic]
|
252
|
+
started = timestack.pop
|
253
|
+
@delegate.call(name, started, Process.clock_gettime(Process::CLOCK_MONOTONIC), id, payload)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
193
257
|
class EventObject < Evented
|
194
258
|
def start(name, id, payload)
|
195
|
-
stack =
|
259
|
+
stack = IsolatedExecutionState[:_event_stack] ||= []
|
196
260
|
event = build_event name, id, payload
|
197
261
|
event.start!
|
198
262
|
stack.push event
|
199
263
|
end
|
200
264
|
|
201
265
|
def finish(name, id, payload)
|
202
|
-
stack =
|
266
|
+
stack = IsolatedExecutionState[:_event_stack]
|
203
267
|
event = stack.pop
|
268
|
+
event.payload = payload
|
204
269
|
event.finish!
|
205
270
|
@delegate.call event
|
206
271
|
end
|
207
272
|
|
273
|
+
def publish_event(event)
|
274
|
+
@delegate.call event
|
275
|
+
end
|
276
|
+
|
208
277
|
private
|
209
278
|
def build_event(name, id, payload)
|
210
279
|
ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
|
211
280
|
end
|
212
281
|
end
|
213
|
-
|
214
|
-
class AllMessages # :nodoc:
|
215
|
-
def initialize(delegate)
|
216
|
-
@delegate = delegate
|
217
|
-
end
|
218
|
-
|
219
|
-
def start(name, id, payload)
|
220
|
-
@delegate.start name, id, payload
|
221
|
-
end
|
222
|
-
|
223
|
-
def finish(name, id, payload)
|
224
|
-
@delegate.finish name, id, payload
|
225
|
-
end
|
226
|
-
|
227
|
-
def publish(name, *args)
|
228
|
-
@delegate.publish name, *args
|
229
|
-
end
|
230
|
-
|
231
|
-
def subscribed_to?(name)
|
232
|
-
true
|
233
|
-
end
|
234
|
-
|
235
|
-
def unsubscribe!(*)
|
236
|
-
false
|
237
|
-
end
|
238
|
-
|
239
|
-
alias :matches? :===
|
240
|
-
end
|
241
282
|
end
|
242
283
|
end
|
243
284
|
end
|
@@ -31,6 +31,10 @@ module ActiveSupport
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
def new_event(name, payload = {}) # :nodoc:
|
35
|
+
Event.new(name, nil, nil, @id, payload)
|
36
|
+
end
|
37
|
+
|
34
38
|
# Send a start notification with +name+ and +payload+.
|
35
39
|
def start(name, payload)
|
36
40
|
@notifier.start name, @id, payload
|
@@ -52,28 +56,35 @@ module ActiveSupport
|
|
52
56
|
end
|
53
57
|
|
54
58
|
class Event
|
55
|
-
attr_reader :name, :time, :end, :transaction_id, :
|
56
|
-
|
57
|
-
def self.clock_gettime_supported? # :nodoc:
|
58
|
-
defined?(Process::CLOCK_THREAD_CPUTIME_ID) &&
|
59
|
-
!Gem.win_platform? &&
|
60
|
-
!RUBY_PLATFORM.match?(/solaris/i)
|
61
|
-
end
|
62
|
-
private_class_method :clock_gettime_supported?
|
59
|
+
attr_reader :name, :time, :end, :transaction_id, :children
|
60
|
+
attr_accessor :payload
|
63
61
|
|
64
62
|
def initialize(name, start, ending, transaction_id, payload)
|
65
63
|
@name = name
|
66
64
|
@payload = payload.dup
|
67
|
-
@time = start
|
65
|
+
@time = start ? start.to_f * 1_000.0 : start
|
68
66
|
@transaction_id = transaction_id
|
69
|
-
@end = ending
|
67
|
+
@end = ending ? ending.to_f * 1_000.0 : ending
|
70
68
|
@children = []
|
71
|
-
@cpu_time_start = 0
|
72
|
-
@cpu_time_finish = 0
|
69
|
+
@cpu_time_start = 0.0
|
70
|
+
@cpu_time_finish = 0.0
|
73
71
|
@allocation_count_start = 0
|
74
72
|
@allocation_count_finish = 0
|
75
73
|
end
|
76
74
|
|
75
|
+
def record
|
76
|
+
start!
|
77
|
+
begin
|
78
|
+
yield payload if block_given?
|
79
|
+
rescue Exception => e
|
80
|
+
payload[:exception] = [e.class.name, e.message]
|
81
|
+
payload[:exception_object] = e
|
82
|
+
raise e
|
83
|
+
ensure
|
84
|
+
finish!
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
77
88
|
# Record information at the time this event starts
|
78
89
|
def start!
|
79
90
|
@time = now
|
@@ -88,15 +99,10 @@ module ActiveSupport
|
|
88
99
|
@allocation_count_finish = now_allocations
|
89
100
|
end
|
90
101
|
|
91
|
-
def end=(ending)
|
92
|
-
ActiveSupport::Deprecation.deprecation_warning(:end=, :finish!)
|
93
|
-
@end = ending
|
94
|
-
end
|
95
|
-
|
96
102
|
# Returns the CPU time (in milliseconds) passed since the call to
|
97
103
|
# +start!+ and the call to +finish!+
|
98
104
|
def cpu_time
|
99
|
-
|
105
|
+
@cpu_time_finish - @cpu_time_start
|
100
106
|
end
|
101
107
|
|
102
108
|
# Returns the idle time time (in milliseconds) passed since the call to
|
@@ -124,7 +130,7 @@ module ActiveSupport
|
|
124
130
|
#
|
125
131
|
# @event.duration # => 1000.138
|
126
132
|
def duration
|
127
|
-
|
133
|
+
self.end - time
|
128
134
|
end
|
129
135
|
|
130
136
|
def <<(event)
|
@@ -137,26 +143,28 @@ module ActiveSupport
|
|
137
143
|
|
138
144
|
private
|
139
145
|
def now
|
140
|
-
|
146
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
141
147
|
end
|
142
148
|
|
143
|
-
|
149
|
+
begin
|
150
|
+
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_millisecond)
|
151
|
+
|
144
152
|
def now_cpu
|
145
|
-
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
|
153
|
+
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_millisecond)
|
146
154
|
end
|
147
|
-
|
148
|
-
def now_cpu
|
149
|
-
0
|
155
|
+
rescue
|
156
|
+
def now_cpu # rubocop:disable Lint/DuplicateMethods
|
157
|
+
0.0
|
150
158
|
end
|
151
159
|
end
|
152
160
|
|
153
|
-
if
|
161
|
+
if GC.stat.key?(:total_allocated_objects)
|
154
162
|
def now_allocations
|
155
|
-
|
163
|
+
GC.stat(:total_allocated_objects)
|
156
164
|
end
|
157
|
-
else
|
165
|
+
else # Likely on JRuby, TruffleRuby
|
158
166
|
def now_allocations
|
159
|
-
|
167
|
+
0
|
160
168
|
end
|
161
169
|
end
|
162
170
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require "active_support/notifications/instrumenter"
|
4
4
|
require "active_support/notifications/fanout"
|
5
|
-
require "active_support/per_thread_registry"
|
6
5
|
|
7
6
|
module ActiveSupport
|
8
7
|
# = Notifications
|
@@ -38,6 +37,19 @@ module ActiveSupport
|
|
38
37
|
# payload # => Hash, the payload
|
39
38
|
# end
|
40
39
|
#
|
40
|
+
# Here, the +start+ and +finish+ values represent wall-clock time. If you are
|
41
|
+
# concerned about accuracy, you can register a monotonic subscriber.
|
42
|
+
#
|
43
|
+
# ActiveSupport::Notifications.monotonic_subscribe('render') do |name, start, finish, id, payload|
|
44
|
+
# name # => String, name of the event (such as 'render' from above)
|
45
|
+
# start # => Monotonic time, when the instrumented block started execution
|
46
|
+
# finish # => Monotonic time, when the instrumented block ended execution
|
47
|
+
# id # => String, unique ID for the instrumenter that fired the event
|
48
|
+
# payload # => Hash, the payload
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# The +start+ and +finish+ values above represent monotonic time.
|
52
|
+
#
|
41
53
|
# For instance, let's store all "render" events in an array:
|
42
54
|
#
|
43
55
|
# events = []
|
@@ -135,6 +147,16 @@ module ActiveSupport
|
|
135
147
|
# during the execution of the block. The callback is unsubscribed automatically
|
136
148
|
# after that.
|
137
149
|
#
|
150
|
+
# To record +started+ and +finished+ values with monotonic time,
|
151
|
+
# specify the optional <tt>:monotonic</tt> option to the
|
152
|
+
# <tt>subscribed</tt> method. The <tt>:monotonic</tt> option is set
|
153
|
+
# to +false+ by default.
|
154
|
+
#
|
155
|
+
# callback = lambda {|name, started, finished, unique_id, payload| ... }
|
156
|
+
# ActiveSupport::Notifications.subscribed(callback, "sql.active_record", monotonic: true) do
|
157
|
+
# ...
|
158
|
+
# end
|
159
|
+
#
|
138
160
|
# === Manual Unsubscription
|
139
161
|
#
|
140
162
|
# The +subscribe+ method returns a subscriber object:
|
@@ -155,7 +177,7 @@ module ActiveSupport
|
|
155
177
|
#
|
156
178
|
# Subscribers using a regexp or other pattern-matching object will remain subscribed
|
157
179
|
# to all events that match their original pattern, unless those events match a string
|
158
|
-
# passed to
|
180
|
+
# passed to +unsubscribe+:
|
159
181
|
#
|
160
182
|
# subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
|
161
183
|
# ActiveSupport::Notifications.unsubscribe('render_template.action_view')
|
@@ -175,6 +197,10 @@ module ActiveSupport
|
|
175
197
|
notifier.publish(name, *args)
|
176
198
|
end
|
177
199
|
|
200
|
+
def publish_event(event) # :nodoc:
|
201
|
+
notifier.publish_event(event)
|
202
|
+
end
|
203
|
+
|
178
204
|
def instrument(name, payload = {})
|
179
205
|
if notifier.listening?(name)
|
180
206
|
instrumenter.instrument(name, payload) { yield payload if block_given? }
|
@@ -208,12 +234,22 @@ module ActiveSupport
|
|
208
234
|
# ActiveSupport::Notifications.subscribe(/render/) do |event|
|
209
235
|
# @event = event
|
210
236
|
# end
|
211
|
-
|
212
|
-
|
237
|
+
#
|
238
|
+
# Raises an error if invalid event name type is passed:
|
239
|
+
#
|
240
|
+
# ActiveSupport::Notifications.subscribe(:render) {|*args| ...}
|
241
|
+
# #=> ArgumentError (pattern must be specified as a String, Regexp or empty)
|
242
|
+
#
|
243
|
+
def subscribe(pattern = nil, callback = nil, &block)
|
244
|
+
notifier.subscribe(pattern, callback, monotonic: false, &block)
|
245
|
+
end
|
246
|
+
|
247
|
+
def monotonic_subscribe(pattern = nil, callback = nil, &block)
|
248
|
+
notifier.subscribe(pattern, callback, monotonic: true, &block)
|
213
249
|
end
|
214
250
|
|
215
|
-
def subscribed(callback,
|
216
|
-
subscriber = subscribe(
|
251
|
+
def subscribed(callback, pattern = nil, monotonic: false, &block)
|
252
|
+
subscriber = notifier.subscribe(pattern, callback, monotonic: monotonic)
|
217
253
|
yield
|
218
254
|
ensure
|
219
255
|
unsubscribe(subscriber)
|
@@ -224,28 +260,13 @@ module ActiveSupport
|
|
224
260
|
end
|
225
261
|
|
226
262
|
def instrumenter
|
227
|
-
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
# This class is a registry which holds all of the +Instrumenter+ objects
|
232
|
-
# in a particular thread local. To access the +Instrumenter+ object for a
|
233
|
-
# particular +notifier+, you can call the following method:
|
234
|
-
#
|
235
|
-
# InstrumentationRegistry.instrumenter_for(notifier)
|
236
|
-
#
|
237
|
-
# The instrumenters for multiple notifiers are held in a single instance of
|
238
|
-
# this class.
|
239
|
-
class InstrumentationRegistry # :nodoc:
|
240
|
-
extend ActiveSupport::PerThreadRegistry
|
241
|
-
|
242
|
-
def initialize
|
243
|
-
@registry = {}
|
263
|
+
registry[notifier] ||= Instrumenter.new(notifier)
|
244
264
|
end
|
245
265
|
|
246
|
-
|
247
|
-
|
248
|
-
|
266
|
+
private
|
267
|
+
def registry
|
268
|
+
ActiveSupport::IsolatedExecutionState[:active_support_notifications_registry] ||= {}
|
269
|
+
end
|
249
270
|
end
|
250
271
|
|
251
272
|
self.notifier = Fanout.new
|
@@ -30,7 +30,7 @@ module ActiveSupport
|
|
30
30
|
# If set to true, precision will mean the number of significant digits instead
|
31
31
|
# of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
|
32
32
|
significant: false,
|
33
|
-
# If set, the zeros after the decimal separator will always be stripped (
|
33
|
+
# If set, the zeros after the decimal separator will always be stripped (e.g.: 1.200 will be 1.2)
|
34
34
|
strip_insignificant_zeros: false
|
35
35
|
},
|
36
36
|
|
@@ -174,9 +174,7 @@ module ActiveSupport
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def valid_float?
|
177
|
-
Float(number)
|
178
|
-
rescue ArgumentError, TypeError
|
179
|
-
false
|
177
|
+
Float(number, exception: false)
|
180
178
|
end
|
181
179
|
end
|
182
180
|
end
|
@@ -8,20 +8,21 @@ module ActiveSupport
|
|
8
8
|
self.namespace = :currency
|
9
9
|
|
10
10
|
def convert
|
11
|
-
number = self.number.to_s.strip
|
12
|
-
number_f = number.to_f
|
13
11
|
format = options[:format]
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
format = options[:negative_format]
|
13
|
+
number_f = valid_float?
|
14
|
+
if number_f
|
15
|
+
if number_f.negative?
|
16
|
+
number_f = number_f.abs
|
17
|
+
format = options[:negative_format] if (number_f * 10**options[:precision]) >= 0.5
|
20
18
|
end
|
19
|
+
number_s = NumberToRoundedConverter.convert(number_f, options)
|
20
|
+
else
|
21
|
+
number_s = number.to_s.strip
|
22
|
+
format = options[:negative_format] if number_s.sub!(/^-/, "")
|
21
23
|
end
|
22
24
|
|
23
|
-
|
24
|
-
format.gsub("%n", rounded_number).gsub("%u", options[:unit])
|
25
|
+
format.gsub("%n", number_s).gsub("%u", options[:unit])
|
25
26
|
end
|
26
27
|
|
27
28
|
private
|
@@ -4,7 +4,7 @@ require "active_support/number_helper/number_converter"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module NumberHelper
|
7
|
-
class NumberToDelimitedConverter < NumberConverter
|
7
|
+
class NumberToDelimitedConverter < NumberConverter # :nodoc:
|
8
8
|
self.validate_float = true
|
9
9
|
|
10
10
|
DEFAULT_DELIMITER_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
|
@@ -16,7 +16,7 @@ module ActiveSupport
|
|
16
16
|
@number = RoundingHelper.new(options).round(number)
|
17
17
|
@number = Float(number)
|
18
18
|
|
19
|
-
#
|
19
|
+
# For backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files.
|
20
20
|
unless options.key?(:strip_insignificant_zeros)
|
21
21
|
options[:strip_insignificant_zeros] = true
|
22
22
|
end
|
@@ -4,7 +4,7 @@ require "active_support/number_helper/number_converter"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module NumberHelper
|
7
|
-
class NumberToHumanSizeConverter < NumberConverter
|
7
|
+
class NumberToHumanSizeConverter < NumberConverter # :nodoc:
|
8
8
|
STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb, :pb, :eb]
|
9
9
|
|
10
10
|
self.namespace = :human
|
@@ -13,7 +13,7 @@ module ActiveSupport
|
|
13
13
|
def convert
|
14
14
|
@number = Float(number)
|
15
15
|
|
16
|
-
#
|
16
|
+
# For backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files.
|
17
17
|
unless options.key?(:strip_insignificant_zeros)
|
18
18
|
options[:strip_insignificant_zeros] = true
|
19
19
|
end
|
@@ -4,7 +4,7 @@ require "active_support/number_helper/number_converter"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module NumberHelper
|
7
|
-
class NumberToPhoneConverter < NumberConverter
|
7
|
+
class NumberToPhoneConverter < NumberConverter # :nodoc:
|
8
8
|
def convert
|
9
9
|
str = country_code(opts[:country_code]).dup
|
10
10
|
str << convert_to_phone_number(number.to_s.strip)
|
@@ -20,14 +20,18 @@ module ActiveSupport
|
|
20
20
|
end
|
21
21
|
|
22
22
|
formatted_string =
|
23
|
-
if
|
23
|
+
if rounded_number.finite?
|
24
24
|
s = rounded_number.to_s("F")
|
25
|
-
s << "0" * precision
|
26
25
|
a, b = s.split(".", 2)
|
27
|
-
|
28
|
-
|
26
|
+
if precision != 0
|
27
|
+
b << "0" * precision
|
28
|
+
a << "."
|
29
|
+
a << b[0, precision]
|
30
|
+
end
|
31
|
+
a
|
29
32
|
else
|
30
|
-
|
33
|
+
# Infinity/NaN
|
34
|
+
"%f" % rounded_number
|
31
35
|
end
|
32
36
|
else
|
33
37
|
formatted_string = rounded_number
|