mirror of
https://github.com/meineerde/rackstash.git
synced 2025-12-19 15:01:12 +00:00
Add Callable adapter to handle a log in a custom way
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.
This commit is contained in:
parent
0aa39483dd
commit
aad1660135
@ -56,3 +56,4 @@ end
|
||||
require 'rackstash/logger'
|
||||
|
||||
require 'rackstash/adapters/io'
|
||||
require 'rackstash/adapters/callable'
|
||||
|
||||
69
lib/rackstash/adapters/callable.rb
Normal file
69
lib/rackstash/adapters/callable.rb
Normal file
@ -0,0 +1,69 @@
|
||||
# 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 'rackstash/adapters/adapter'
|
||||
require 'rackstash/encoders/raw'
|
||||
|
||||
module Rackstash
|
||||
module Adapters
|
||||
# This adapter calls a user-provided "callable", i.e., a `Proc` or block for
|
||||
# each written log line. This allows users to custom handle the logs without
|
||||
# having to write a full custom adapter class.
|
||||
#
|
||||
# You can pass the callable as a block to {#initialize} or as a Proc or any
|
||||
# other object responding to `call`. For each written log, we call the block
|
||||
# once.
|
||||
#
|
||||
# Note that we do not ensure that the calls are sequentially. If multiple
|
||||
# threads are concurrently writing logs to the logger, the calable might be
|
||||
# called concurrently from multiple threads too.
|
||||
#
|
||||
# To create an adapter instance, you can use this example:
|
||||
#
|
||||
# Rackstash::Adapters::Callable.new do |log|
|
||||
# # handle the log as required
|
||||
# end
|
||||
class Callable < Adapter
|
||||
register_for ::Proc, :call
|
||||
|
||||
# Create a new Callable adapter by wrapping a proc. You can pass the proc
|
||||
# either as the firat parameter to {#initialize} or as a block which is
|
||||
# then transformed into a proc internally.
|
||||
#
|
||||
# @param callable [Proc, #call] a callable object, usually a proc or
|
||||
# lambda
|
||||
def initialize(callable = nil, &block)
|
||||
if callable.respond_to?(:call)
|
||||
@callable = callable
|
||||
elsif block_given?
|
||||
@callable = block
|
||||
else
|
||||
raise TypeError, "#{callable.inspect} does not appear to be callable"
|
||||
end
|
||||
end
|
||||
|
||||
# By default, we use an {Rackstash::Encoders::Raw} to encode the events.
|
||||
# This ensures that the raw event is passed through to to the callable by
|
||||
# default.
|
||||
#
|
||||
# You can define a custom encoder in the responsible {Flow}.
|
||||
#
|
||||
# @return [Rackstash::Encoders::Raw] a new Raw encoder
|
||||
def default_encoder
|
||||
Rackstash::Encoders::Raw.new
|
||||
end
|
||||
|
||||
# Write a single log line by calling the defined `callable` given in
|
||||
# {#initialize}.
|
||||
#
|
||||
# @param log [Object] the encoded log event
|
||||
# @return [nil]
|
||||
def write_single(log)
|
||||
@callable.call(log)
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
63
spec/rackstash/adapters/callable_spec.rb
Normal file
63
spec/rackstash/adapters/callable_spec.rb
Normal file
@ -0,0 +1,63 @@
|
||||
# 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 'rackstash/adapters/callable'
|
||||
|
||||
describe Rackstash::Adapters::Callable do
|
||||
let(:callable) { ->(log) { log } }
|
||||
let(:adapter) { Rackstash::Adapters::Callable.new(callable) }
|
||||
|
||||
describe '#initialize' do
|
||||
it 'accepts a callable' do
|
||||
expect { Rackstash::Adapters::Callable.new(->{}) }.not_to raise_error
|
||||
expect { Rackstash::Adapters::Callable.new(proc {}) }.not_to raise_error
|
||||
expect { Rackstash::Adapters::Callable.new(Struct.new(:call).new) }.not_to raise_error
|
||||
|
||||
expect { Rackstash::Adapters::Callable.new { |log| log } }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'rejects non-IO objects' do
|
||||
expect { Rackstash::Adapters::Callable.new(nil) }.to raise_error TypeError
|
||||
expect { Rackstash::Adapters::Callable.new('hello') }.to raise_error TypeError
|
||||
expect { Rackstash::Adapters::Callable.new(Object.new) }.to raise_error TypeError
|
||||
expect { Rackstash::Adapters::Callable.new([]) }.to raise_error TypeError
|
||||
expect { Rackstash::Adapters::Callable.new(Struct.new(:foo).new) }.to raise_error TypeError
|
||||
end
|
||||
end
|
||||
|
||||
describe '.default_encoder' do
|
||||
it 'returns a Raw encoder' do
|
||||
expect(adapter.default_encoder).to be_instance_of Rackstash::Encoders::Raw
|
||||
end
|
||||
end
|
||||
|
||||
describe '#close' do
|
||||
it 'does nothing' do
|
||||
expect(callable).not_to receive(:close)
|
||||
adapter.close
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reopen' do
|
||||
it 'does nothing' do
|
||||
expect(callable).not_to receive(:close)
|
||||
adapter.reopen
|
||||
end
|
||||
end
|
||||
|
||||
describe '#write_single' do
|
||||
it 'calls the callable with the log' do
|
||||
expect(callable).to receive(:call).with('a log line')
|
||||
adapter.write('a log line')
|
||||
end
|
||||
|
||||
it 'passes through the original object' do
|
||||
expect(callable).to receive(:call).with([123, 'hello'])
|
||||
adapter.write([123, 'hello'])
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user