This encoder is useful for local consumption of the raw log stream, e.g.
during development where the developer might not care for any additional
fields. With this encoder, the log output can mostly resemble a "classic"
line-based log feed.
With this, we optimize the common case where we do have valid UTF-8
strings to begin with. If the given String is already frozen, as is
common for e.g. Hash keys, we don't even need to create a new object.
With this change, we also always return frozen strings from
`Rackstash::Fields::AbstractCollection#utf9_encode`. This avoids an
unecessary object copy when inserting it in a Hash and still ensures
that values are always frozen anyway.
Users can provide a "callable", i.e. a proc or block which will be
called for each written log. This allows users to custom handle the
logs without having to write a full adapter.
Usually, users should still write a full adapter to handle all cases of
their wrapped log device.
The global default (unless overwritten by an adapter class) is to use
the JSON encoder since it's the most versatile and flexible option for a
logger today.
An ada pert wraps a log device (e.g. a file, an underlying logger, ...)
and provides an uniform interface to write the encoded log event to its
final target.
By using a registry, we can create the required adapter instance for a
provided log device automatically.
This makes the Rackstash::Fields::Tags class thread safe while still
mantaining its existing semantincs, given that Ruby's set is also build
on top of a simple Hash.
Similar to the previous commit, we avoid the unnecessary allocation of
a temporary array when looping over the `@raw` value. In addition to
that, we ensure thread-safety by always operating on a copy of the raw
data so that other threads can not change anything under our feet
anymore.
`each_with_object` allocates an array for each kv pair. Switching to
the slightly more verbose but less allocatey `each_pair` eliminates
array allocations.
This follows the similar change in Rails:
960de47f0e
Since a flow will significantly affect the representation of a log event
over its life before being persistet by the final adapter, the new term
better reflects what it is responsible for.
It also helps to avoid the dupliction of meaning between Sink, Target,
Adapter.
Since an AbstractCollection can in principal contain any raw value, we
want to make sure that we only handle known values. Others will probably
still be catched by the fallback converter calls at the bottom of
AbstractCollection#normalize.
Since the Message class now formats the passed message on initialization
anyways, there is no need anymore to retain the formatter there.
Instead, we can just format the message string in the Logger before
creating the Message instance.
This significantly simplifies the Message class and better encapsulates
the knowledge about the line formatter into the Logger class.
Since we can not guarantee that a user-supplied formatter is side-effect
free, a delayed formatting might result in unexpected results. An
example of such a formatter is the one used by
ActiveSupport::TaggedLogging.
This helps in ensuring thread-safety when flushing unbuffered Buffers.
Previously, it was possibly for client code to still hold references to
fields on a flushed and cleared buffer, potentially resulting in
unintended side-effects if the client code was not aware that the buffer
was cleared.
By creating ompletely new object instances, existing references only
point to data from before the clear. This ensures a clean cut.
This is functionally equivalent. However, the previous behavior resulted
in the block being materialized as a proc which is quite expensive, both
during materialization as well as when calling it. By using
`block_given?`, we can avoid this materialization.
These methods are useful convenience methods to add (nested) fields to a
hash while optionally retaining existing values. Usually, `#deep_merge!`
or `#set` will be the commonly used ways to set fields to a hash.
This follows the rule that two objects which are eql? also have the same
hash value. It is also required to ensure that we can use collections in
sets, hashes and arrays where the hash-equality is checked for certain
operations.