Skip to content

Commit

Permalink
Refactor to allow configurable logger and formatter classes
Browse files Browse the repository at this point in the history
  • Loading branch information
dickdavis committed Aug 11, 2024
1 parent 1a783db commit d2117da
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 43 deletions.
20 changes: 14 additions & 6 deletions lib/event_logger_rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

require 'rails'
require 'active_support/dependencies'
require 'event_logger_rails/engine'
require 'event_logger_rails/current_request'
require 'event_logger_rails/event'
require 'event_logger_rails/engine'
require 'event_logger_rails/emitter'
require 'event_logger_rails/event'
require 'event_logger_rails/event_logger'
require 'event_logger_rails/exceptions/invalid_logger_level'
require 'event_logger_rails/exceptions/unregistered_event'
require 'event_logger_rails/extensions/loggable'
require 'event_logger_rails/json_logger'
require 'event_logger_rails/formatters/json'
require 'event_logger_rails/message'
require 'event_logger_rails/middleware/capture_request_details'
require 'event_logger_rails/output'
Expand All @@ -22,10 +23,18 @@ module EventLoggerRails
# @return [Symbol] The default level of the events logged by EventLoggerRails.
mattr_accessor :default_level

# @!attribute [r] formatter
# @return [Class] The formatter to use for logging.
mattr_accessor :formatter

# @!attribute [r] logdev
# @return [IO, #write] The log device used by EventLoggerRails.
mattr_accessor :logdev

# @!attribute [r] logger_class
# @return [Class] The logger class used by EventLoggerRails.
mattr_accessor :logger_class

# @!attribute [r] registered_events
# @return [Array<Hash>] The events registry defined in the config/event_logger_rails.yml file.
mattr_accessor :registered_events
Expand All @@ -48,18 +57,17 @@ def self.setup

# Returns or initializes the Emitter instance for EventLoggerRails.
#
# @note The emitter is initialized with the configured log device.
# @return [Emitter] The Emitter instance used for logging events.
def self.emitter
@emitter ||= Emitter.new(logdev:)
@emitter ||= Emitter.new
end

# Forwards the arguments to the Emitter's log method.
#
# @example
# EventLoggerRails.log('foo.bar.baz', level: :info, data: { foo: 'bar' })
# @param (see Emitter#log)
# @return [void]
# @return (see Emitter#log)
def self.log(...)
emitter.log(...)
end
Expand Down
10 changes: 4 additions & 6 deletions lib/event_logger_rails/emitter.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# frozen_string_literal: true

module EventLoggerRails
##
# Processes events, sending data to logger.
class Emitter
## Initializes the emitter using the given log device for log output.
#
# @param logdev [IO, #write] The log device for log output.
def initialize(logdev:)
@logger = JsonLogger.new(logdev)
def initialize
logdev = EventLoggerRails.logdev
@logger = EventLoggerRails.logger_class.constantize.new(logdev)
end

# Validates and logs an event with the given level and data.
Expand All @@ -20,7 +18,7 @@ def initialize(logdev:)
# @param data [Hash] Additional data to log.
# @return [Integer] The number of bytes written to the log.
# @example
# emitter = EventLoggerRails::Emitter.new(logdev: $stdout)
# emitter = EventLoggerRails::Emitter.new
# emitter.log('foo.bar.baz', level: :info, data: { foo: 'bar' })
def log(event, level:, data: {})
Event.new(event).validate! do |validated_event|
Expand Down
11 changes: 7 additions & 4 deletions lib/event_logger_rails/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ class Engine < ::Rails::Engine

# Initialize the EventLoggerRails configuration.
config.event_logger_rails = ActiveSupport::OrderedOptions.new
config.event_logger_rails.formatter = 'EventLoggerRails::Formatters::JSON'
config.event_logger_rails.logdev = "log/event_logger_rails.#{Rails.env}.log"
config.event_logger_rails.logger_class = 'EventLoggerRails::JsonLogger'
config.event_logger_rails.logger_class = 'EventLoggerRails::EventLogger'
config.event_logger_rails.default_level = :warn

# Add the EventLoggerRails middleware.
Expand All @@ -28,13 +29,15 @@ class Engine < ::Rails::Engine
EventLoggerRails.setup do |engine|
# Set the default logging level from the registration.
engine.default_level = app.config.event_logger_rails.default_level
# Set the log device from the registration.
# Set the formatter.
engine.formatter = app.config.event_logger_rails.formatter
# Set the log device.
engine.logdev = app.config.event_logger_rails.logdev
# Set the logger class from the registration.
# Set the logger class.
engine.logger_class = app.config.event_logger_rails.logger_class
# Set the registered events from the registration.
engine.registered_events = Rails.application.config_for(:event_logger_rails)
# Set the sensitive fields from the registration.
# Set the sensitive fields.
engine.sensitive_fields = app.config.filter_parameters
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
# frozen_string_literal: true

module EventLoggerRails
# Writes log entries in JSON format
class JsonLogger < ::Logger
# Writes log entries in configured format.
class EventLogger < ::Logger
include ActiveSupport::LoggerSilence

# Initializes the logger with a JSON formatter.
#
# @param logdev [IO, #write] The log device for log output.
def initialize(...)
super(...)
@formatter = proc do |level, timestamp, _progname, message|
output = Output.new(level:, timestamp:, message:)
"#{output.to_json}\n"
end
@formatter = EventLoggerRails.formatter.constantize.new || EventLoggerRails::Formatters::JSON.new
end
end
end
16 changes: 16 additions & 0 deletions lib/event_logger_rails/formatters/json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module EventLoggerRails
module Formatters
# Writes log entries in JSON format
class JSON < ActiveSupport::Logger::SimpleFormatter
# Initializes the logger with a JSON formatter.
#
# @param logdev [IO, #write] The log device for log output.
def call(level, timestamp, _progname, message)
output = Output.new(level:, timestamp:, message:)
"#{output.to_json}\n"
end
end
end
end
9 changes: 8 additions & 1 deletion spec/lib/event_logger_rails/emitter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@

RSpec.describe EventLoggerRails::Emitter do
subject(:emitter) do
described_class.new(logdev: File.open(File::NULL, 'w'))
described_class.new
end

before do
EventLoggerRails.setup do |config|
config.formatter = 'EventLoggerRails::Formatters::JSON'
config.logger_class = 'EventLoggerRails::EventLogger'
end
end

describe '#log' do
Expand Down
22 changes: 22 additions & 0 deletions spec/lib/event_logger_rails/event_logger_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe EventLoggerRails::EventLogger do
subject(:event_logger) { described_class.new(File.open(File::NULL, 'w')) }

let(:message) { { foo: 'bar' } }
let(:buffer) { StringIO.new }

before do
allow(IO).to receive(:open).and_return(buffer)
end

context 'when default formatter is configured' do
it 'outputs the provided message in JSON format' do
event_logger.info(message)
log_output = JSON.parse(buffer.string, symbolize_names: true)
expect(log_output).to include(**message)
end
end
end
21 changes: 21 additions & 0 deletions spec/lib/event_logger_rails/formatters/json_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe EventLoggerRails::Formatters::JSON do
subject(:formatter) { described_class.new }

describe '#call' do
subject(:method_call) { formatter.call(level, timestamp, progname, message) }

let(:level) { :foo }
let(:timestamp) { Time.now }
let(:progname) { 'bar' }
let(:message) { { foo: 'bar' } }

it 'returns the event reserved for the exception' do
expected_output = EventLoggerRails::Output.new(level:, timestamp:, message:).to_json
expect(method_call).to eq("#{expected_output}\n")
end
end
end
20 changes: 0 additions & 20 deletions spec/lib/event_logger_rails/json_logger_spec.rb

This file was deleted.

30 changes: 30 additions & 0 deletions spec/lib/event_logger_rails_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,36 @@
end
end

describe 'formatter' do
subject(:engine_setup) do
engine.setup do |config|
config.formatter = formatter_class
end
end

let(:formatter_class) { 'EventLoggerRails::Formatters::JSON' }

it 'configures the formatter to use for initializing the logger' do
engine_setup
expect(described_class.formatter).to eq(formatter_class)
end
end

describe 'logger_class' do
subject(:engine_setup) do
engine.setup do |config|
config.logger_class = logger_class
end
end

let(:logger_class) { 'EventLoggerRails::EventLogger' }

it 'configures the output device to use for initializing the logger' do
engine_setup
expect(described_class.logger_class).to eq(logger_class)
end
end

describe 'registered events' do
subject(:engine_setup) do
engine.setup do |config|
Expand Down

0 comments on commit d2117da

Please sign in to comment.