The encoder is then responsible to format it as it pleases. Commonly,
encoders can use Rackstash::Encoders::Helpers::Message#normalize_message
to create a single combined message string.
If the encoder is not interested in using the message, it can jsut get
rid if it without incuring any overhead.
With the change to allow ading fields to the Buffer with a Logger
interface in the previous commit, we should also flush those Buffers
with fields set that way by default.
With this interface, the user adds fields the same way they would add
messages. The implicit assumption here is that the buffer is handled the
same way. Thus, if the current buffer is non-buffering, we will
automatically flush it to the sink and clear it, just the same way as we
would have done it for a message.
This new name better reflects what this option actually does: it allows
to flush a Buffer even if there were just added fields or tags. A tryely
empty Buffer, i.e., one which has neither added messages, fields, or
tags is never flushed.
This field is only relevant when actually sending JSON to Logstash.
Other formats don't need it. It is thus more desireable to only include
this field in a specific logstash JSON encoder.
Most of the time, these methods should be used. They are only required
for special cases where the Buffer needs to be flushed later than when
its poped. In this case, special precautions need to be made to ensure
that the Buffer is always reliably poped and flushed to avoid loosing
logs.
With this move, we can also optimize the sinplest case where there are
no fields or tags on the Buffer and no defines default_fields or
default_tags on the Sink. In that case, we don't need to merge them,
avoiding the creation of several unecessary objects on Buffer flush.
Since the fields are (through the thread-local BufferStack) only ever
accessed from a single Thread, there is no need to accept the additional
locking overhead of the Concurrent raw values.
We can just use simple Hashes and Arrays here for higher performance.
Using the core `NotInmplementedError` is not desireable since its
documentation includes:
> Note that if `fork` raises a `NotImplementedError`, then
> `respond_to?(:fork)` returns `false`.
Since we are responding to the method but still raise an error, our
usage of the exception does not fulfill its documentation.
A custom error instead of a default `NoMethodError` is still desireable
since it significantly helps with debugging. With a different Exception,
we make it clear that a method is expected to be there and just wasn't
implemented by a subclass as opposed to the caller just using an object
wrong and calling entirely unexpected methods on it.
During normal operation, the Flows will rescue all exceptions and log
them to the special error_flow. By default, we will write JSON logs to
STDERR.
The log location and format can either be change globally by setting (or
changing) the Rackstash.error_flow or for each Flow for a Logger
individually by setting Flow#error_flow.
These methods do not rescue any thrown errors. The usual loggers will
always want to use the non-bang methods which rescue errors and attempt
to log them.