-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #56 from dwbutler/formatters
Support for different formatters
- Loading branch information
Showing
19 changed files
with
385 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,3 +14,4 @@ gemfile: | |
matrix: | ||
allow_failures: | ||
- rbx-2 | ||
sudo: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,48 @@ | ||
require 'logger' | ||
require 'socket' | ||
require 'time' | ||
require 'logstash-logger/formatter/base' | ||
|
||
module LogStashLogger | ||
HOST = ::Socket.gethostname | ||
module Formatter | ||
DEFAULT_FORMATTER = :json_lines | ||
|
||
class Formatter < ::Logger::Formatter | ||
include TaggedLogging::Formatter | ||
autoload :LogStashEvent, 'logstash-logger/formatter/logstash_event' | ||
autoload :Json, 'logstash-logger/formatter/json' | ||
autoload :JsonLines, 'logstash-logger/formatter/json_lines' | ||
autoload :Cee, 'logstash-logger/formatter/cee' | ||
autoload :CeeSyslog, 'logstash-logger/formatter/cee_syslog' | ||
|
||
def call(severity, time, progname, message) | ||
event = build_event(message, severity, time) | ||
"#{event.to_json}\n" | ||
def self.new(formatter_type) | ||
build_formatter(formatter_type) | ||
end | ||
|
||
protected | ||
def self.build_formatter(formatter_type) | ||
formatter_type ||= DEFAULT_FORMATTER | ||
|
||
def build_event(message, severity, time) | ||
data = message | ||
if data.is_a?(String) && data.start_with?('{') | ||
data = (JSON.parse(message) rescue nil) || message | ||
if custom_formatter_instance?(formatter_type) | ||
formatter_type | ||
elsif custom_formatter_class?(formatter_type) | ||
formatter_type.new | ||
else | ||
formatter_klass(formatter_type).new | ||
end | ||
end | ||
|
||
event = case data | ||
when LogStash::Event | ||
data.clone | ||
when Hash | ||
event_data = data.merge("@timestamp" => time) | ||
LogStash::Event.new(event_data) | ||
else | ||
LogStash::Event.new("message" => msg2str(data), "@timestamp" => time) | ||
end | ||
|
||
event['severity'] ||= severity | ||
#event.type = progname | ||
|
||
event['host'] ||= HOST | ||
def self.formatter_klass(formatter_type) | ||
case formatter_type.to_sym | ||
when :json_lines then JsonLines | ||
when :json then Json | ||
when :logstash_event then LogStashEvent | ||
when :cee then Cee | ||
when :cee_syslog then CeeSyslog | ||
else fail ArgumentError, 'Invalid formatter' | ||
end | ||
end | ||
|
||
current_tags.each { |tag| event.tag(tag) } | ||
|
||
LogStashLogger.configuration.customize_event_block.call(event) if LogStashLogger.configuration.customize_event_block.respond_to?(:call) | ||
def self.custom_formatter_instance?(formatter_type) | ||
formatter_type.respond_to?(:call) | ||
end | ||
|
||
# In case Time#to_json has been overridden | ||
if event.timestamp.is_a?(Time) | ||
event.timestamp = event.timestamp.iso8601(3) | ||
end | ||
|
||
event | ||
def self.custom_formatter_class?(formatter_type) | ||
formatter_type.is_a?(Class) && formatter_type.method_defined?(:call) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
require 'logger' | ||
require 'socket' | ||
require 'time' | ||
|
||
module LogStashLogger | ||
module Formatter | ||
HOST = ::Socket.gethostname | ||
|
||
class Base < ::Logger::Formatter | ||
include ::LogStashLogger::TaggedLogging::Formatter | ||
|
||
def call(severity, time, progname, message) | ||
@event = build_event(message, severity, time) | ||
end | ||
|
||
protected | ||
|
||
def build_event(message, severity, time) | ||
data = message | ||
if data.is_a?(String) && data.start_with?('{'.freeze) | ||
data = (JSON.parse(message) rescue nil) || message | ||
end | ||
|
||
event = case data | ||
when LogStash::Event | ||
data.clone | ||
when Hash | ||
event_data = data.merge("@timestamp".freeze => time) | ||
LogStash::Event.new(event_data) | ||
else | ||
LogStash::Event.new("message".freeze => msg2str(data), "@timestamp".freeze => time) | ||
end | ||
|
||
event['severity'.freeze] ||= severity | ||
#event.type = progname | ||
|
||
event['host'.freeze] ||= HOST | ||
|
||
current_tags.each { |tag| event.tag(tag) } | ||
|
||
LogStashLogger.configuration.customize_event_block.call(event) if LogStashLogger.configuration.customize_event_block.respond_to?(:call) | ||
|
||
# In case Time#to_json has been overridden | ||
if event.timestamp.is_a?(Time) | ||
event.timestamp = event.timestamp.iso8601(3) | ||
end | ||
|
||
event | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module LogStashLogger | ||
module Formatter | ||
class Cee < Base | ||
def call(severity, time, progname, message) | ||
super | ||
"@cee:#{@event.to_json}" | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module LogStashLogger | ||
module Formatter | ||
class CeeSyslog < Cee | ||
def call(severity, time, progname, message) | ||
@cee = super | ||
@progname = progname | ||
|
||
"#{facility}:#{@cee}\n" | ||
end | ||
|
||
protected | ||
|
||
def facility | ||
@facility = "#{@event['host']}" | ||
@facility << " #{@progname}" if @progname | ||
@facility | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module LogStashLogger | ||
module Formatter | ||
class Json < Base | ||
def call(severity, time, progname, message) | ||
super | ||
@event.to_json | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module LogStashLogger | ||
module Formatter | ||
class JsonLines < Base | ||
def call(severity, time, progname, message) | ||
super | ||
"#{@event.to_json}\n" | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module LogStashLogger | ||
module Formatter | ||
class LogStashEvent < Base | ||
def call(severity, time, progname, message) | ||
super | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
require 'logstash-logger' | ||
|
||
describe LogStashLogger::Formatter::Base do | ||
include_context "formatter" | ||
|
||
describe "#build_event" do | ||
let(:event) { formatted_message } | ||
|
||
describe "message type" do | ||
context "string" do | ||
it "puts the message into the message field" do | ||
expect(event['message']).to eq(message) | ||
end | ||
end | ||
|
||
context "JSON string" do | ||
let(:message) do | ||
{ message: 'test', foo: 'bar' }.to_json | ||
end | ||
|
||
it "parses the JSON and merges into the event" do | ||
expect(event['message']).to eq('test') | ||
expect(event['foo']).to eq('bar') | ||
end | ||
end | ||
|
||
context "hash" do | ||
let(:message) do | ||
{ 'message' => 'test', 'foo' => 'bar' } | ||
end | ||
|
||
it "merges into the event" do | ||
expect(event['message']).to eq('test') | ||
expect(event['foo']).to eq('bar') | ||
end | ||
end | ||
|
||
context "LogStash::Event" do | ||
let(:message) { LogStash::Event.new("message" => "foo") } | ||
|
||
it "returns a clone of the original event" do | ||
expect(event['message']).to eq("foo") | ||
expect(event).to_not equal(message) | ||
end | ||
end | ||
|
||
context "fallback" do | ||
let(:message) { [1, 2, 3] } | ||
|
||
it "calls inspect" do | ||
expect(event['message']).to eq(message.inspect) | ||
end | ||
end | ||
end | ||
|
||
describe "extra fields on the event" do | ||
it "adds severity" do | ||
expect(event['severity']).to eq(severity) | ||
end | ||
|
||
it "adds host" do | ||
expect(event['host']).to eq(hostname) | ||
end | ||
end | ||
|
||
describe "timestamp" do | ||
it "ensures time is in ISO8601 format" do | ||
expect(event.timestamp).to eq(time.iso8601(3)) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
require 'logstash-logger' | ||
|
||
describe LogStashLogger::Formatter::Cee do | ||
include_context "formatter" | ||
|
||
it "outputs in CEE format" do | ||
expect(formatted_message).to match(/\A@cee:/) | ||
end | ||
|
||
it "serializes the LogStash::Event data as JSON" do | ||
json_data = formatted_message[/\A@cee:\s?(.*)\z/, 1] | ||
json_message = JSON.parse(json_data) | ||
expect(json_message["message"]).to eq(message) | ||
end | ||
end |
Oops, something went wrong.