mirror of
https://github.com/meineerde/rackstash.git
synced 2026-01-31 17:27:13 +00:00
Register encoders using a ClassRegistry
This commit is contained in:
parent
de6b60925a
commit
6eaeaedaf8
@ -173,6 +173,13 @@ require 'rackstash/adapter/logger'
|
||||
require 'rackstash/adapter/io'
|
||||
require 'rackstash/adapter/null'
|
||||
|
||||
require 'rackstash/encoder/hash'
|
||||
require 'rackstash/encoder/json'
|
||||
require 'rackstash/encoder/lograge'
|
||||
require 'rackstash/encoder/logstash'
|
||||
require 'rackstash/encoder/message'
|
||||
require 'rackstash/encoder/raw'
|
||||
|
||||
require 'rackstash/filter/clear_color'
|
||||
require 'rackstash/filter/default_fields'
|
||||
require 'rackstash/filter/default_tags'
|
||||
|
||||
@ -5,9 +5,80 @@
|
||||
# This software may be modified and distributed under the terms
|
||||
# of the MIT license. See the LICENSE.txt file for details.
|
||||
|
||||
require 'rackstash/encoder/hash'
|
||||
require 'rackstash/encoder/json'
|
||||
require 'rackstash/encoder/lograge'
|
||||
require 'rackstash/encoder/logstash'
|
||||
require 'rackstash/encoder/message'
|
||||
require 'rackstash/encoder/raw'
|
||||
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
|
||||
# @param encoder_class [Class] a class from which a new encoder can be
|
||||
# created. Filter objects must respond to `encode` and accept an event
|
||||
# hash.
|
||||
# @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 objects of type were passed
|
||||
# @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 filter object. When giving
|
||||
# a `Class`, we are using it as is to create a new filter object with
|
||||
# the supplied `args` and `block`. When giving a `String` or `Symbol`,
|
||||
# we first use the filter registry to find the matching class. With
|
||||
# that, we then create a filter object as before. When giving an object
|
||||
# which responds to `call` already (e.g. a `Proc`, we return it
|
||||
# unchanged, ignoring any additional passed `args`.
|
||||
# @param args [Array] an optional list of arguments which is passed to the
|
||||
# initializer for the new filter object.
|
||||
# @raise [TypeError] if we can not create a new filter object from the
|
||||
# given `filter_spec`, usually because it is an unsupported type
|
||||
# @raise [KeyError] if we could not find a filter class in the registry
|
||||
# for the specified class name
|
||||
# @return [Object] a new filter object
|
||||
def build(encoder_spec, *args, &block)
|
||||
if encoder_spec.respond_to?(:encode) && !encoder_spec.is_a?(String)
|
||||
encoder_spec
|
||||
else
|
||||
registry[encoder_spec].new(*args, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
# This software may be modified and distributed under the terms
|
||||
# of the MIT license. See the LICENSE.txt file for details.
|
||||
|
||||
require 'rackstash/encoder'
|
||||
require 'rackstash/encoder/helper/message'
|
||||
require 'rackstash/encoder/helper/timestamp'
|
||||
|
||||
@ -26,5 +27,7 @@ module Rackstash
|
||||
event
|
||||
end
|
||||
end
|
||||
|
||||
register Hash, :hash
|
||||
end
|
||||
end
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
require 'json'
|
||||
|
||||
require 'rackstash/encoder'
|
||||
require 'rackstash/encoder/helper/message'
|
||||
require 'rackstash/encoder/helper/timestamp'
|
||||
|
||||
@ -29,5 +30,7 @@ module Rackstash
|
||||
::JSON.dump(event)
|
||||
end
|
||||
end
|
||||
|
||||
register JSON, :json, :JSON
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
# This software may be modified and distributed under the terms
|
||||
# of the MIT license. See the LICENSE.txt file for details.
|
||||
|
||||
require 'rackstash/encoder'
|
||||
require 'rackstash/encoder/helper/timestamp'
|
||||
|
||||
module Rackstash
|
||||
@ -136,5 +137,7 @@ module Rackstash
|
||||
"#{key}=#{value}"
|
||||
end
|
||||
end
|
||||
|
||||
register Lograge, :lograge
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
# This software may be modified and distributed under the terms
|
||||
# of the MIT license. See the LICENSE.txt file for details.
|
||||
|
||||
require 'rackstash/encoder'
|
||||
require 'rackstash/encoder/json'
|
||||
|
||||
module Rackstash
|
||||
@ -26,5 +27,7 @@ module Rackstash
|
||||
super(event)
|
||||
end
|
||||
end
|
||||
|
||||
register Logstash, :logstash
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
# This software may be modified and distributed under the terms
|
||||
# of the MIT license. See the LICENSE.txt file for details.
|
||||
|
||||
require 'rackstash/encoder'
|
||||
require 'rackstash/encoder/helper/message'
|
||||
|
||||
module Rackstash
|
||||
@ -70,5 +71,7 @@ module Rackstash
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
register Message, :message
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
# This software may be modified and distributed under the terms
|
||||
# of the MIT license. See the LICENSE.txt file for details.
|
||||
|
||||
require 'rackstash/encoder'
|
||||
|
||||
module Rackstash
|
||||
module Encoder
|
||||
# The Raw encoder passes along the raw unformatted event hash. It still
|
||||
@ -20,5 +22,7 @@ module Rackstash
|
||||
event
|
||||
end
|
||||
end
|
||||
|
||||
register Raw, :raw
|
||||
end
|
||||
end
|
||||
|
||||
88
spec/rackstash/encoder_spec.rb
Normal file
88
spec/rackstash/encoder_spec.rb
Normal file
@ -0,0 +1,88 @@
|
||||
# frozen_string_literal: true
|
||||
#
|
||||
# Copyright 2017 Holger Just
|
||||
#
|
||||
# This software may be modified and distributed under the terms
|
||||
# of the MIT license. See the LICENSE.txt file for details.
|
||||
|
||||
require 'spec_helper'
|
||||
require 'securerandom'
|
||||
|
||||
require 'rackstash/encoder'
|
||||
|
||||
describe Rackstash::Encoder do
|
||||
let(:registry) { Rackstash::ClassRegistry.new('encoder') }
|
||||
|
||||
let(:encoder_class) {
|
||||
Class.new do
|
||||
def encode(event)
|
||||
'encoded'
|
||||
end
|
||||
end
|
||||
}
|
||||
let(:encoder_name) { :"encoder_class_#{SecureRandom.hex(6)}" }
|
||||
|
||||
describe '.build' do
|
||||
before do
|
||||
allow(described_class).to receive(:registry).and_return(registry)
|
||||
described_class.register(encoder_class, encoder_name)
|
||||
end
|
||||
|
||||
it 'builds an encoder from a class' do
|
||||
args = ['arg1', foo: 'bar']
|
||||
expect(encoder_class).to receive(:new).with(*args)
|
||||
|
||||
described_class.build(encoder_class, *args)
|
||||
end
|
||||
|
||||
it 'builds a encoder from a Symbol' do
|
||||
args = ['arg1', foo: 'bar']
|
||||
expect(encoder_class).to receive(:new).with(*args)
|
||||
|
||||
p described_class.registry
|
||||
|
||||
described_class.build(encoder_name.to_sym, *args)
|
||||
end
|
||||
|
||||
it 'builds a encoder from a String' do
|
||||
args = ['arg1', foo: 'bar']
|
||||
expect(encoder_class).to receive(:new).with(*args)
|
||||
|
||||
described_class.build(encoder_name.to_s, *args)
|
||||
end
|
||||
|
||||
it 'returns an existing encoder' do
|
||||
encoder = Class.new do
|
||||
def encode(event)
|
||||
'custom'
|
||||
end
|
||||
end.new
|
||||
|
||||
expect(described_class.build(encoder)).to equal encoder
|
||||
expect(described_class.build(encoder, :ignored, 42)).to equal encoder
|
||||
end
|
||||
|
||||
it 'raises a TypeError with invalid spec types' do
|
||||
expect { described_class.build(123) }
|
||||
.to raise_error(TypeError, '123 can not be used to describe encoders')
|
||||
expect { described_class.build(nil) }
|
||||
.to raise_error(TypeError, 'nil can not be used to describe encoders')
|
||||
expect { described_class.build(true) }
|
||||
.to raise_error(TypeError, 'true can not be used to describe encoders')
|
||||
end
|
||||
|
||||
it 'raises a KeyError for undefined encoders' do
|
||||
expect { described_class.build('MissingEncoder') }
|
||||
.to raise_error(KeyError, 'No encoder was registered for "MissingEncoder"')
|
||||
expect { described_class.build(:missing_encoder) }
|
||||
.to raise_error(KeyError, 'No encoder was registered for :missing_encoder')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'registry' do
|
||||
it 'returns the encoder registry' do
|
||||
expect(described_class.registry).to be_instance_of Rackstash::ClassRegistry
|
||||
expect(described_class.registry.object_type).to eql 'encoder'
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user