This adds a `:urlsafe` option to the `MessageEncryptor` constructor.
When enabled, this option ensures that messages use a URL-safe encoding.
This matches the `MessageVerifier` `:urlsafe` option added in #45419.
Follow-up to #43924.
This commit refactors the logic around assembling and extracting the
parts of a message (namely: the encrypted data, the IV, and the auth
tag). It also provides a small but reproducible performance increase
for a roundtrip.
Benchmark:
```ruby
require "benchmark/ips"
require "active_support/message_encryptor"
DATA = "x" * 100
ENCRYPTOR = ActiveSupport::MessageEncryptor.new(SecureRandom.random_bytes(32))
Benchmark.ips do |x|
x.report("roundtrip") do
ENCRYPTOR.decrypt_and_verify(ENCRYPTOR.encrypt_and_sign(DATA))
end
end
```
Before:
```
Warming up --------------------------------------
roundtrip 1.342k i/100ms
Calculating -------------------------------------
roundtrip 13.525k (± 1.5%) i/s - 68.442k in 5.061532s
```
After:
```
Warming up --------------------------------------
roundtrip 1.409k i/100ms
Calculating -------------------------------------
roundtrip 14.125k (± 1.4%) i/s - 71.859k in 5.088419s
```
The `test_urlsafe` test could not fail when `urlsafe: false` because the
serialized input data did not contain a bit sequence that would encode
to a non-URL-safe character. The `test_no_padding` *could* fail when
`urlsafe: false`, except when the default serializer uses JSON, because
the serialized input data would be a multiple of 3 bytes, thus not
requiring any padding.
This commit replaces those tests with a falsifiable test using a
carefully chosen input string.
In minitest/minitest@6e06ac9 minitest changed such that it now accepts
`kwargs` instead of requiring kwargs to be shoved into the args array.
This is a good change but required some updates to our test code to get
the new version of minitest passing.
Changes are as follows:
1) Lock minitest to 5.15 for Ruby 2.7. We don't love this change but
it's pretty difficult to get 2.7 and 3.0 to play nicely together with
the new kwargs changes. Dropping 2.7 support isn't an option right
now for Rails. This is safe because all of the code changes here are
internal methods to Rails like assert_called_with. Applications
shouldn't be consuming them as they are no-doc'd.
2) Update the `assert_called_with` method to take any kwargs but also
the returns kwarg.
3) Update callers of `assert_called_with` to move the kwargs outside the
args array.
4) Update the message from marshaled exceptions. In 5.16 the exception
message is "result not reported" instead of "Wrapped undumpable
exception".
Co-authored-by: Matthew Draper <matthew@trebex.net>
urlsafe option was introduced to MessageVerifier in
09c3f36a96 but it can generate strings
containing padding character ("=") which is not urlsafe.
Fix not to pad when base64 encode.
MessageVerifier uses Base64.strict_encode64 and generated strings are
not urlsafe. Though the goal is to make MessageVerifier generated
strings urlsafe, We can not simply switch to Base64.urlsafe_encode64
because it will be a breaking change. Thus, as a first step, urlsafe
option is added to the MessageVerifier initializer.
The `assert_called_with` helper allows passing a multi-dimensional array to
mock multiple calls to the same method for a given block. This works
fine now, but when adding support for real kwargs arguments to line up with
recent upgrades in Minitest, this approach is no longer workable because
we can't pass multiple sets of differing kwargs.
Rather than complicated this method further, this commit removes the
multi-call form of `assert_called_with` and modifies the tests that
currently make use of that functionality to just use the underlying
`Minitest::Mock` calls.
Co-authored-by: Eileen M. Uchitelle <eileencodes@gmail.com>
The logic for shortening long keys in MemCacheStore
is broken since the time it stopped using MD5 checksumming.
Memcached supports keys up to 250 chars length. The reason
things worked I believe is because the underlying Dalli
library is doing it's own key shortening. Which uses its own
hashing function and in fact limits keys to 249 chars, see
petergoldstein/dalli@74b2625f11
This patch in a similar way properly truncates keys to 250
characters and avoids double hashing on Dalli side. Also
makes key name more predictable and independent from the
underlying Dalli version.
Previously, including/prepending/extending one of these deprecated
constants would silently succeed, since it is a module.
This adds a defintion for append_features/prepend_features/extended so
that it can forward the inclusion onto the target module.
This commit aims to improve ActiveSupport::Notifications::Fanout. There
are three main goals here: backwards compatibility, safety, and
performance.
* Backwards compatibility
This ActiveSupport::Notifications is an old and well used interface.
Over time it has collected a lot of features and flexibility, much of
which I suspect is not used anywhere by anyone, but it is hard to know
specifics and we would at minimum need a deprecation cycle.
For this reason this aims to fully maintain compatibility. This includes
both the ability to use an alternate notification implementation instead
of Fanout, the signatures received by all types of listeners, and the
interface used on the Instrumenter and Fanout itself (including the
sometimes problematic start/finish).
* Safety
There have been issues (both recent and past) with the "timestacks"
becoming invalid, particularly when subscribing and unsubscribing within
events. This is an issue when topics are subscribed/unsubscribed to
while they are in flight.
The previous implementation would record a separate timestamp or event
object for each listener in a thread local stack. This meant that it was
essential that the listeners to start and finish were identical.
This issue is avoided by passing the listeners used to `start` the event
to `finish` (`finish_with_state` in the Instrumenter), to ensure they
are the same set in `start`/`finish`.
This commit further avoids this issue. Instead of pushing individual
times onto a stack, we now push a single object, `Handle`, onto the
stack for an event. This object holds all the subscribers (recorded at
start time) and all their associated data. This means that as long as
start/stop calls are not interleaved.
This commit also exposes `build_handle` as a public interface. This
returns the Handle object which can have start/stop called at any time
and any order safely. The one reservation I have with making this public
is that existing "evented" listeners (those receiving start/stop) may
not be ready for that (ex. if they maintain an internal thread-local
stack).
* Performance
This aims to be faster and make fewer allocations then the existing
implementation.
For time-based and event-object-based listeners, the previous
implementation created a separate object for each listener, pushing
and popping it on a thread-local stack. This is slower both because we
need to access the thread local repeatedly (hash lookups) and because
we're allocating duplicate objects.
The new implementation works by grouping similar types of listeners
together and shares either the `Event` or start/stop times between all
of them. The grouping was done so that we didn't need to allocate Events
or Times for topics which did have a listener of that type.
This implementation is significantly faster for all cases, except for
evented, which is slower.
For topics with 10 subscriptions:
*main*:
timed 66.739k (± 2.5%) i/s - 338.800k in 5.079883s
timed_monotonic 138.265k (± 0.6%) i/s - 699.261k in 5.057575s
event_object 48.650k (± 0.2%) i/s - 244.250k in 5.020614s
evented 366.559k (± 1.0%) i/s - 1.851M in 5.049727s
unsubscribed 3.696M (± 0.5%) i/s - 18.497M in 5.005335s
*This branch*:
timed 259.031k (± 0.6%) i/s - 1.302M in 5.025612s
timed_monotonic 327.439k (± 1.7%) i/s - 1.665M in 5.086815s
event_object 228.991k (± 0.3%) i/s - 1.164M in 5.083539s
evented 296.057k (± 0.3%) i/s - 1.501M in 5.070315s
unsubscribed 3.670M (± 0.3%) i/s - 18.376M in 5.007095s
Co-authored-by: John Crepezzi <john.crepezzi@gmail.com>
Co-authored-by: Theo Julienne <theojulienne@github.com>
Because these strings contain no HTML elements and the basic entities
are escaped, they are safe to be included as-is as PCDATA in HTML
content. Tagging them as html-safe avoids double-escaping entities
when being concatenated to a SafeBuffer during rendering.
Fixes https://github.com/rails/rails-html-sanitizer/issues/124
An ArgumentError was being raised when methods were called with (proc,
options) inside a with_options block:
def my_method(arg1, **kwargs)
[arg1, kwargs]
end
# this would raise instead of merging options
with_options(hello: "world") do
my_method(proc {}, {fizz: "buzz"})
end
Fixes#45183
The previous documentation hints that the return value if `other` `acts_like` time is seconds with the example, but it doesn't explicitly say "seconds" anywhere. Just trying to make it more obvious that the value is seconds, and not something like milliseconds or nanoseconds, etc.
Without some help, failures in a forked process make for some noise in
the output, but won't fail the build.
Instead of trying to transfer the whole exception back, I've gone for a
simpler solution of just sending _something_ (the exception class name)
back so we'll fail; the full failure will be visible in the child
process's stderr output.
Vue.js, alpinejs, and potentially other JS libraries support tags
starting with `@` symbols. This was broken by the recent security release in
649516ce0f
I've only added `@` to the list even though there are potentially other
safe characters. We can add more if necessary (and if safe).
Fixes:
* #45014
* #44972
Clarify to users what objects may be cached, and highlight the option used to cache default non-serializable data.
Purpose: Improving new-to-Rails users' experience, as this detail may not be obvious, costing them time and effort spent debugging.
Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
Add the method ERB::Util.xml_name_escape to escape dangerous characters
in names of tags and names of attributes, following the specification of
XML.
Use that method in the tag helpers of ActionView::Helpers. Rename the option
:escape_attributes to :escape, to simplify by applying the option to the whole
tag.
The stdlib Logger::new allows passing a :formatter keyword argument to
set the logger's formatter. ActiveSupport::Logger::new ignores this
argument by always setting the formatter to an instance of
SimpleFormatter. Instead, we should only set it when none is yet set.
Every time I write `config.cache_classes` I have to pause for a moment to make
sure I get it right. It makes you think.
On the other hand, if you read `config.enable_reloading = true`, does the
application reload? You do not need to spend 1 cycle of brain CPU to nod.
The default message would not tell you what the actual value is, just
what it expected it to have changed to or from.
It now tells you what the actual value is, similar to the output you'd
get from a matcher such as `assert_equal`
- `#first` raises an error when called on a beginless range.
Using `#begin` to get the first element instead.
- Adding additional equality condition to cover the case when both
ranges are beginless
With Ruby 2.4+ the default for +to_time+ changed from converting to the
local system time to preserving the offset of the receiver. At the time
Rails supported older versions of Ruby so a compatibility layer was
added to assist in the migration process. From Rails 5.0 new applications
have defaulted to the Ruby 2.4+ behavior and since Rails 7.0 now only
supports Ruby 2.7+ this compatibility layer can be safely removed.
To minimize any noise generated the deprecation warning only appears when
the setting is configured to `false` as that is the only scenario where
the removal of the compatibility layer has any effect.
The tests for the redis cache store are hard-coded to use redis://localhost:6379/0
and redis://localhost:6379/1. This prevents them from running within a docker compose
environment where typically the url would be redis://redis:6379/0.
- This PR fixes two issues with the Tagged Logging feature in
conjunction with broadcasting logs.
For the sake of clarity I'll define the "main logger" and
the "broadcasted logger" in this snippet:
```ruby
main_logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(io))
broadcaster_logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(io))
main_logger.extend(Activesupport::Logger.broadcast(broadcasted_logger))
```
1) The first issue that this PR fixes, is that the tags on the "main logger"
don't propagate to the "broadcasted logger" when you pass in a block.
```ruby
main_logger.tagged("FOO") { |logger| logger.info("Hello") }
# Outputs:
# [Foo] Hello <- By the main logger
# Hello <- By the broadcasted logger
```
A fix was made in 70af536b5d
but that only works for the non block version
2) It's quite common for the "broadcasted logger" to have a diffent
log formatter that the "main logger". In example you'd want to
output JSON logs in one and raw text in the other.
That wasn't possible before. All loggers had to have the same
instance of the formatter. The formatter was set on all loggers
thanks to [this](3fc9d12875/activesupport/lib/active_support/logger.rb (L45-L48)) and it's [associated test](3fc9d12875/activesupport/test/broadcast_logger_test.rb (L58-L64))
This requirement was needed to make the Tagged Logging feature
work; the tags being set in a thread variable whose name
uses the `object_id` 3fc9d12875/activesupport/lib/active_support/tagged_logging.rb (L59)
(different formatter instance -> different object_id -> different variables)
In this PR, I have removed the code that sets the same formatter
instance on all logger. The "broadcaster logger" just need to
have the `current_tags` point to the `current_tags` of the
"main logger", I'm doing that by redefing the `current_tags`
method each time the "main logger" uses a different formatter.
The advantages by doing so is that custom made formatter
can now call this `current_tags` method, which will return
all the tags and process them the way they want.
```ruby
class JSONLogFormatter
def call(_, _, _, msg)
tags = current_tags # Can now retrieve the tags
{ message: msg, tags: tags }.to_json
end
end
broadcasted_logger = Logger.new(io)
broadcaster_logger.formatter = JSONLogFormatter.new
main_logger = Logger.new(io)
main_logger.extend(ActiveSupport::Logger.broadcast(broadcasted_logger))
```
The behavior remains the same as before if a logger uses the
Rails vanilla formatter or the Tagged Logging formatter.
activerecord/lib/active_record/connection_adapters/postgresql/column.rb
- usage added in 64fd666
- unneeded because of active_support/rails: 8f58d6e
railties/lib/rails/rack/logger.rb
- usage added in c83d9a1
- usage removed in c131211
activesupport/lib/active_support/number_helper/number_converter.rb
- the NumberHelper was split into multiple classes in 2da9d67, however
the require was left in NumberConverter even though
NumberToPhoneConverter is the only class where it's used
activesupport/lib/active_support/duration/iso8601_serializer.rb
- usage added in 04c512d
- usage removed in 51e991f
Ref: https://github.com/rails/rails/pull/43625#discussion_r809532572
It can be used by error reporting service integration when they wish
to handle the error higher in the stack.
For instance Sidekiq has its own error handling interface with a
little bit of extra context information.
Ref: https://github.com/aws/aws-sdk-ruby/pull/2670
Some gems like aws-sdk-core use `Object#extend(Enumerable)`.
It's not a very good pattern, but it's somehwat handled ok by Ruby.
However if Enumerable has constants, then any time the module is
extended, the global constant cache is flushed and this has a very
negative impact on performance for the virtual machine, and even
worse for JITs.
We no longer need to define instance variables to avoid uninitialized
instance variable warnings.
Also rather than to keep a hash of `constant -> path` forever, we
can simply keep a list of constants and call `const_get` for each of
them.
And finally we can clear the list we kept, as it's just wasted memory.
core_ext/array/wrap
- added in b1164adda1
- usage removed in fa986ae0ca
core_ext/numeric/time
- added in ee51b51b60, but usage was only
in mem_cache_store so moved require there
RDoc will automatically format and link API references as long as they
are not already marked up as inline code.
This commit removes markup from various API references so that those
references will link to the relevant API docs.
"Overwrite" means "destructively replace", and is more suitable when,
for example, talking about writing data to a location.
"Override" means "supersede", and is more suitable when, for example,
talking about redifining methods in a subclass.
Fix: https://github.com/rails/rails/issues/44496
It's really unfortunate, but since thread locals were copied
since a decade and we moved most of them into IsolatedExecutionState
we now need to copy it too to keep backward compatibility.
However I think it's one more sign that AC::Live should be
rethought.
Fix: https://github.com/rails/rails/issues/44452
We don't ignore blank path strings because as surprising as it is, they
are valid paths:
```ruby
>> path = Pathname.new(" ")
=> #<Pathname: >
>> path.write("test")
=> 4
>> path.exist?
=> true
```
Previously it would end up calling `Pathname#empty?` which returned true
if the path existed and was an empty directory or file.
That behavior was unlikely to be expected.
This file is required when `active_support` is required. That should
avoid to load core_ext if possible, so if there is no good reason to
use the blank core_ext, better to not use it.
Previously ActiveSupport::Subscriber would manage its own events, keep
them in a thread-local stack, and track "child" events of the same
subscriber.
I don't think this was particularly useful, since it only considered
notifications delivered to the same subscriber, and I can't find
evidence of this being used in the wild. I think this was intended to
support tracing, but any uch tool would want to do this itself (at
minimum in order to support multiple namespaces).
Additionally, this has caused a few users to OOM in production
environments, notably when queueing many jobs from another job.
A few classes hold a reference to this object (anything with a
subscription), causing the `inspect` or pretty print output to be
unreasonably large and slow.
This implements a simple representation for the Notifications::Fanout
object as users usually don't care about its internals.
Co-authored-by: Daniel Colson <danieljamescolson@gmail.com>
The stub wasn't called because it was defined on the `@cache` client
rather than on `cache`'s client.
This should reduce `MemCacheStoreTest` flakiness a bit.
Under certain circumstances, the middleware isn't informed that the
response body has been fully closed which result in request state not
being fully reset before the next request.
[CVE-2022-23633]
In cache stores prepending `LocalCache`, serialized `Entry`
instances are stored in `LocalCache::LocalStore`. This
speeds up hot key lookups without a network roundtrip in a
context of a single given request.
However, with these entries being stored in their serialized
form, `#read_multi_entries` returns them directly to cache
consumers.
Instead, we will now deserialize these entries first.
These changes include adding a hybrid serializer class
named JsonWithMarshalFallback in order for existing apps
to have an upgrade path from Marshal to JSON.
* [ci skip] Refer to Rails.application.message_verifier in MessageVerifier docs
* [ci skip] Clarify authentication example
* [ci skip] Use meaningful example data for message verifier docs
* [ci skip] Link to Rails.application.message_verifier docs
* [ci skip] Clarify order of message signing and verification
* [ci skip] Re-order sections in order of expected use
* [ci skip] Recommend using a purpose to reduce risks
* [ci skip] More consistent parentheses
Replaces a few hard-wired references to Thread/Thread.current within
ActiveRecord::ConnectionPool with IsolationExecutionState.
A few tweaks were required to IsolationExecutionState so that
I could implement the various cache key methods with a reference
to the current thread/fiber.
`Array#to_h` is substantially faster than `Hash::[]` because having a stricter interface
it can preallocate the hash with the right size.
We also freeze the strings early so that `Hash#[]` doesn't have to dup them.
```ruby
require 'benchmark/ips'
puts RUBY_VERSION
class Object
def instance_values
Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
end
def instance_values_opt
instance_variables.to_h do |ivar|
[ivar[1..-1].freeze, instance_variable_get(ivar)]
end
end
end
SMALL = Object.new
2.times { |i| SMALL.instance_variable_set(:"@variable_#{i}", i) }
LARGE = Object.new
15.times { |i| LARGE.instance_variable_set(:"@variable_#{i}", i) }
{
'SMALL' => SMALL,
'LARGE' => LARGE
}.each do |size, object|
puts "=== #{size} ==="
Benchmark.ips do |x|
x.report('original') { object.instance_values }
x.report('patched') { object.instance_values_opt }
x.compare!
end
end
```
```
3.1.0
=== SMALL ===
Warming up --------------------------------------
original 95.429k i/100ms
patched 116.046k i/100ms
Calculating -------------------------------------
original 963.241k (± 1.3%) i/s - 4.867M in 5.053433s
patched 1.246M (± 0.8%) i/s - 6.266M in 5.031372s
Comparison:
patched: 1245570.0 i/s
original: 963240.9 i/s - 1.29x (± 0.00) slower
=== LARGE ===
Warming up --------------------------------------
original 15.799k i/100ms
patched 18.285k i/100ms
Calculating -------------------------------------
original 157.163k (± 1.3%) i/s - 789.950k in 5.027176s
patched 181.587k (± 1.1%) i/s - 914.250k in 5.035344s
Comparison:
patched: 181587.4 i/s
original: 157163.4 i/s - 1.16x (± 0.00) slower
```
The `travel_to` helper didn’t support subsecond time traveling in order
to prevent problems with external services, such as MySQL. This,
however, makes it impossible to test features that use durations less
than a second ("subsecond").
This therefore allows `travel_to` to stub `Time.now` with the accurate
time passed to it as `date_or_time` if the `with_usec` optional argument
is set to true:
Time.now.inspect # => 2022-01-05 22:36:54.613371959 +0000
travel_to(0.1.seconds.from_now, with_usec: true)
Time.now.inspect # => 2022-01-05 22:36:54.713371959 +0000
Ref: https://bugs.ruby-lang.org/issues/14394#note-38
Based on Matz's last comment, it's not so clear whether `Class#descendants`
will come back in the same form or at all. So let's not assume anything.
We can avoid using String#split by calculating the indexes of the
encrypted data, IV, and auth tag in the payload. This increases the
resistance of the solution against ill-formed payloads that don't
include the separator.
This is a follow up to the work in PR #42919.
Since `#subclasses` was introduced a bit after `#descendants`, the feature testing
code assumed that if the former was present, the later would be too.
However it was decided to revert `#descendants` for now, but to keep `#subclasses`
https://bugs.ruby-lang.org/issues/14394#note-33
Since this was totally unexpected, the `#descendants` core_ext and `DescendantsTracker#descendants`
are broken on Active Support 7.0.0 / Ruby 3.1.0-dev.
We now test the existence of both methods to handle this new situation. Since
for now it's planned for `#descendants` to make it back in Ruby 3.2, we keep
checking for it.
* bug: illustrate negative durations don't add to the same time
* fix: equivalent negative durations add to the same time
Co-authored-by: Caleb <me@cpb.ca>
Co-authored-by: Braden Staudacher <braden.staudacher@chime.com>
* Updates CHANGELOG with fix to `ActiveSupport::Duration.build`
`[].all?(Array)` returns `true`. Thus when an empty `args` array was
passed to `assert_called_with`, `expect` would not be called on the mock
object, eventually leading to an "unmocked method" error.
This commit allows an empty array to be passed as `args`, which behaves
the same as passing `[[]]`.
ActiveSupport::MessageVerifier#verified is causing signed_message to be
split twice: first inside #valid_message? and then inside #verified.
This is ultimately unnecessary.
We can avoid String#split all together by calculating the indexes of the
data and the digest in the payload. This increases the resistance of the
solution against ill-formed payloads that don't include the separator.
Ruby 3.1 is going to introduce an [optimization][] that makes interpolation
of some types of objects faster, unless there is a custom implementation
of to_s. Since Rails is overriding `to_s` for a bunch of core classes it
means that this optimization in Rails applications will be disabled.
In order to allow Rails applications to use this optimization in
the future we are deprecating all the reasons we override `to_s` in
those core classes in favor of using `to_formatted_s`.
[optimization]: b08dacfea3
Ruby 3.1 introduced an optimization to string interpolation for some
core classes in b08dacfea3.
But since we override `to_s` in some of those core classes to add behavior
like `to_s(:db)`, all Rails applications will not be able to take advantage
of that improvement.
Since we can use the `to_formatted_s` alias for the Rails specific behavior
it is best for us to deprecate the `to_s` core extension and allow Rails
applications to get the proformace improvement.
This commit starts removing all the `to_s(:db)` calls inside the framework
so we can deprecate the core extension in the next commit.
Example failure: https://buildkite.com/rails/rails/builds/82905#80d6c6ec-943d-4ba3-b360-1ef6c4aa5d89/1012-1022
The test designates the event end time as 0.01 seconds (i.e. 10
milliseconds) after the start time. It then asserts that the event
duration is 10 ± 0.0001 milliseconds. This sometimes fails due to
floating point precision errors.
This commit changes the assertion to instead check that the duration is
within 1% of the expected value.
This reverts commit 0181f0edd5.
Users of Active Support should always require the top level file of
the framework before requiring anything else inside it, so we don't
need to require that top level file here.
Previously I assumed it was useless, however I was wrong.
The method is called by the reloader to give the illusion that
the GC is precise. Meaning a class that will be unloaded is
immediately made invisible without waiting for it to be garbage collected.
This is easy to do up to Ruby 3.0 because `DescendantTracker` keeps
a map of all tracked classes.
However on 3.1 we need to use the inverse strategy, we keep a WeakMap
of all the classes we cleared, and we filter the return value of `descendants`
and `subclasses`.
Since `clear` is private API and is only used when reloading is enabled,
to reduce the performance impact in production mode, we entirely remove
this behavior when `config.cache_classes` is enabled.
By doing so we avoid a lot of extra work.
```
baseline: 4092604.4 i/s
opt-method: 693204.7 i/s - 5.90x (± 0.00) slower
method: 614761.0 i/s - 6.66x (± 0.00) slower
```
Baseline is calling `run_callbacks` with no callbacks registered.
Full benchmark: https://gist.github.com/casperisfine/837a7a665c6b232dadcf980d73694748
Ref: https://github.com/rails/rails/issues/43472
We swallow these exceptions because it makes sense for a cache to
fallback to a cache miss in case of transcient failures.
However there's value in reporting these to the application
owners so that they can be alerted that something undesirable happened.