1
0
mirror of https://github.com/meineerde/rackstash.git synced 2025-10-17 14:01:01 +00:00

Pass the raw messages array in the event Hash to the encoder

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.
This commit is contained in:
Holger Just 2017-08-22 00:02:06 +02:00
parent 78466f9439
commit 99728842aa
9 changed files with 98 additions and 49 deletions

View File

@ -0,0 +1,42 @@
# 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.
module Rackstash
module Encoders
module Helpers
# Some useful helper methods for {Encoders} which help in normalizing and
# handling the message list in the event Hash.
module Message
# Normalize the `"message"` field of the given log event Hash.
#
# While the filters still had access to the array of {Message} objects
# for filtering, we now concatenate the raw message objects as a single
# string to get the final message which is set on the `event["message"]`
# key.
#
# We expect that the single messages already contain trailing newline
# characters is deemed useful. These are usually added by the formatter
# of the frontend {Logger}.
#
# @param event [Hash] a log event Hash
# @return [Hash] the given event with the `"message"` key set as a
# single string.
def normalize_message(event)
event[FIELD_MESSAGE] =
case event[FIELD_MESSAGE]
when Array
event[FIELD_MESSAGE].map!(&:to_s).join
when nil
''
else
event[FIELD_MESSAGE].to_s
end
event
end
end
end
end
end

View File

@ -6,6 +6,8 @@
require 'json'
require 'rackstash/encoders/helpers/message'
module Rackstash
module Encoders
# The JSON encoder formats the log event as a single-line JSON string. The
@ -13,9 +15,13 @@ module Rackstash
#
# Most {Adapters} default to use this codec.
class JSON
include Rackstash::Encoders::Helpers::Message
# @param event [Hash] a log event as produced by the {Flow}
# @return [String] the event as a single-line JSON string
def encode(event)
normalize_message(event)
::JSON.dump(event)
end
end

View File

@ -4,6 +4,8 @@
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE.txt file for details.
require 'rackstash/encoders/helpers/message'
module Rackstash
module Encoders
# The Message encoder only returns the message of log event. All other
@ -13,10 +15,14 @@ module Rackstash
# required, mostly during development where debug logs are directly consumed
# by humans
class Message
include Rackstash::Encoders::Helpers::Message
# @param event [Hash] a log event as produced by the {Flow}
# @return [String] the `"message"` field of the event. Trailing whitespace
# will be removed.
def encode(event)
normalize_message(event)
event[FIELD_MESSAGE].rstrip
end
end

View File

@ -200,15 +200,10 @@ module Rackstash
# 1. At first, we filter the event with the defined filters in their given
# order. If any of the filters returns `false`, the writing will be
# aborted. No further filters will be applied and the event will not be
# written to the adapter.
# 2. After the filters, we normalize the `event["message"]` field. While the
# filters still had access to the array of {Message} objects for
# filtering, we now concatenate the raw messages as a single string to
# get the final event. The `event["message"]` field now contains a single
# `String` object.
# 3. We encode the event to a format suitable for the adapter using the
# written to the adapter. See {FilterChain#call} for details.
# 2. We encode the event to a format suitable for the adapter using the
# configured {#encoder}.
# 4. Finally, the encoded event will be passed to the {#adapter} to be send
# 3. Finally, the encoded event will be passed to the {#adapter} to be send
# to the actual log target, e.g. a file or an external log receiver.
#
# @api private
@ -221,17 +216,6 @@ module Rackstash
# Silently abort writing if any filter (and thus the while filter chain)
# returns `false`.
return false unless @filter_chain.call(event)
event[FIELD_MESSAGE] =
case event[FIELD_MESSAGE]
when Array
event[FIELD_MESSAGE].map!(&:to_s).join
when nil
''
else
event[FIELD_MESSAGE].to_s
end
@adapter.write @encoder.encode(event)
true
end

View File

@ -0,0 +1,35 @@
# 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 'rackstash/encoders/helpers/message'
describe Rackstash::Encoders::Helpers::Message do
let(:helper) { Object.new.extend(described_class) }
let(:event) { {} }
describe '#normalize_message' do
it 'concatenates the message array' do
event['message'] = ["a\n", "b\n"]
expect(helper.normalize_message(event)).to eql 'message' => "a\nb\n"
end
it 'sets message to an empty string if not present' do
event['message'] = nil
expect(helper.normalize_message(event)).to eql 'message' => ''
end
it 'enforces to_s on other messages' do
foo = String.new('foo')
event['message'] = foo
expect(foo).to receive(:to_s).and_call_original
expect(helper.normalize_message(event)).to eql 'message' => 'foo'
end
end
end

View File

@ -13,8 +13,8 @@ describe Rackstash::Encoders::JSON do
describe '#encode' do
it 'formats the passed event hash as a JSON string' do
event = { 'hello' => 'world', 'message' => 'hello' }
expect(encoder.encode(event)).to eql '{"hello":"world","message":"hello"}'
event = { 'hello' => 'world', 'message' => ["hello\n", "world"] }
expect(encoder.encode(event)).to eql '{"hello":"world","message":"hello\nworld"}'
end
it 'formats newlines as \n' do

View File

@ -13,8 +13,8 @@ describe Rackstash::Encoders::Logstash do
describe '#encode' do
it 'formats the passed event hash as a JSON string and includes @version' do
event = { 'hello' => 'world', 'message' => 'hello' }
expect(encoder.encode(event)).to eql '{"hello":"world","message":"hello","@version":"1"}'
event = { 'hello' => 'world', 'message' => ["hello\n", "world"] }
expect(encoder.encode(event)).to eql '{"hello":"world","message":"hello\nworld","@version":"1"}'
end
end
end

View File

@ -13,8 +13,8 @@ describe Rackstash::Encoders::Message do
describe '#encode' do
it 'gets the message from the event hash' do
event = { 'hello' => 'world', 'message' => 'hello' }
expect(encoder.encode(event)).to eql 'hello'
event = { 'hello' => 'world', 'message' => ["hello\n", "world"] }
expect(encoder.encode(event)).to eql "hello\nworld"
end
it 'rstrips the message' do

View File

@ -277,30 +277,6 @@ describe Rackstash::Flow do
flow.write!(event)
end
it 'concatenates message array before encoding' do
event['message'] = ["a\n", "b\n"]
expect(flow.encoder).to receive(:encode).with('message' => "a\nb\n")
flow.write!(event)
end
it 'sets message to an emoty string if deleted' do
event['message'] = nil
expect(flow.encoder).to receive(:encode).with('message' => '')
flow.write!(event)
end
it 'enforces to_s on other messages' do
foo = String.new('foo')
event['message'] = foo
expect(foo).to receive(:to_s).and_call_original
expect(flow.encoder).to receive(:encode).with('message' => 'foo')
flow.write!(event)
end
it 'encodes the event' do
expect(flow.encoder).to receive(:encode).with(event)
flow.write!(event)