1
0
mirror of https://github.com/meineerde/rackstash.git synced 2026-02-06 00:53:22 +00:00
rackstash/lib/rackstash/encoder.rb

92 lines
4.2 KiB
Ruby

# frozen_string_literal: true
#
# Copyright 2017 - 2018 Holger Just
#
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE.txt file for details.
module Rackstash
# An Encoder is part of a {Flow} where they are responsible to transform the
# filtered event into a format suitable for writing by the final log
# {Adapter}.
#
# The encoder needs to be selected together with the log {Adapter}. While many
# adapters support different encoders, some require a specific format to be
# sent over a wire. Please consult the documentation of your desired adapter
# for details.
#
# Each adapter can define their common default encoder. In a flow, you can
# optionally overwrite the used encoder to select a different log format (e.g.
# to log using the {Lograge} key-value syntax instead of the common default of
# {JSON}.
#
# An encoder can be any object responding to `encode`, e.g. a Proc or an
# instance of a class inside this module. Note that although Strings respond
# to the `encode` method, they are not suitable encoders since Strings can not
# deal with events on their own.
module Encoder
class << self
# Register an encoder with one or more given names. These names can then
# be used in {.build} to fetch the registered class and build a new
# encoder object for it.
#
# @param encoder_class [Class] a class from which a new encoder can be
# created. Encoder classes must implement the `encode` instance method
# which accepts an event hash and returns encoded event.
# @param names [Array<String,Symbol>] one or more names for the
# registered `encoder_class`. Using these names, the user can create a
# new encoder object from the registered class in {.build}.
# @raise [TypeError] if invalid arguments were passed, e.g. an unsuitable
# class or invalid names
# @return [Class] the passed `filter_class`
def register(encoder_class, *names)
unless encoder_class.is_a?(Class) &&
encoder_class.instance_methods.include?(:encode)
raise TypeError, 'Can only register encoder classes'
end
names.flatten.each do |name|
registry[name] = encoder_class
end
encoder_class
end
# @return [ClassRegistry] the registry object which allows to register and
# retrieve available encoder classes
def registry
@registry ||= Rackstash::ClassRegistry.new('encoder'.freeze)
end
# Create a new encoder instance from the specified class and the given
# arguments. The class can be given as an actual class or as the name of
# an encoder in which case we are resolving it to a class registered to
# the {.registry}.
#
# @param encoder_spec [Class, Symbol, String, #encode] a description of
# the class from which we are creating a new encoder object. When giving
# a `Class`, we are using it as is to create a new encoder object with
# the supplied `encoder_args` and `block`. When giving a `String` or
# `Symbol`, we first use the {Encoder.registry} to find the matching
# class. With that, we then create an encoder object as before. When
# giving an object which responds to `encode` already, we return it
# unchanged, ignoring any additional passed `encoder_args`.
# @param encoder_args [Array] an optional list of arguments which is
# passed to the initializer for the new encoder object.
# @param block an optional block passed to the initializer for the new
# encoder object.
# @raise [TypeError] if we can not create a new encoder object from the
# given `encoder_spec`, usually because it is an unsupported type
# @raise [KeyError] if we could not find an encoder class in the registry
# for the specified class name
# @return [Object] a new encoder object
def build(encoder_spec, *encoder_args, &block)
if encoder_spec.respond_to?(:encode) && !encoder_spec.is_a?(String)
encoder_spec
else
registry.fetch(encoder_spec).new(*encoder_args, &block)
end
end
end
end
end