Skip to content

Commit

Permalink
Merge pull request #294 from truemail-rb/develop
Browse files Browse the repository at this point in the history
Truemail v3.3.0
  • Loading branch information
bestwebua authored Feb 26, 2024
2 parents ec7a9d0 + 0bed515 commit f3be34d
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 84 deletions.
9 changes: 4 additions & 5 deletions .reek.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ detectors:
- Truemail::Validate::Smtp#run
- Truemail::Validate::Smtp#not_includes_user_not_found_errors?
- Truemail::Validate::Mx#hosts_from_cname_records
- Truemail::Configuration#logger=
- Truemail::Validate::Smtp::Request#initialize
- Truemail::Validate::Smtp::Request::Session#initialize
- Truemail::RSpec::ValidatorHelper::ValidatorFactory#process_validator_params
Expand All @@ -40,7 +39,6 @@ detectors:
UtilityFunction:
exclude:
- Truemail::Audit::Base#verifier_domain
- Truemail::Configuration#logger_options
- Truemail::Configuration#match_regex?
- Truemail::Configuration#regex_by_method
- Truemail::Dns::Worker#nameserver_port
Expand All @@ -61,6 +59,7 @@ detectors:
- Truemail#raise_unless
- Truemail::Configuration#raise_unless
- Truemail#determine_configuration
- Truemail::Logger::Builder#raise_unless

FeatureEnvy:
exclude:
Expand All @@ -75,12 +74,12 @@ detectors:
NilCheck:
exclude:
- Truemail::Validator#result_not_changed?
- Truemail::Configuration#logger=
- Truemail::Logger::Builder#validate_logger_output
- Truemail::Validator#run

BooleanParameter:
ManualDispatch:
exclude:
- Truemail::Configuration#logger=
- Truemail::Logger::Builder#validate_logger_instance

TooManyConstants:
exclude:
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.3.0] - 2024.02.26

### Added

- Added ability to use custom logger instance in event logger. Thanks [@n-rodriguez](https://github.com/n-rodriguez) for report
- Added `Truemail::Logger::Builder`, tests

### Updated

- Updated `Truemail::Configuration#logger=`, tests
- Updated `Truemail::Logger`, tests
- Updated `circleci`/`lefthook` configs
- Updated gem version

### Removed

- Removed `Truemail::Configuration#logger_options`

## [3.2.0] - 2024.02.24

### Added
Expand Down
19 changes: 7 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,11 @@ Truemail.configure do |config|
config.smtp_safe_check = true

# Optional parameter. This option will enable tracking events. You can print tracking
# events to stdout, write to file or both of these. Logger class by default is Logger
# from Ruby stdlib. Tracking event by default is :error
# events to stdout, write to file or both of these. Logger instance by default is Logger
# instance from Ruby stdlib. You can override this behavior. See how to do it in the
# examples below. Tracking event by default is :error
# Available tracking event: :all, :unrecognized_error, :recognized_error, :error
config.logger = {
logger_class: MyCustomLogger,
tracking_event: :all,
stdout: true,
log_absolute_path: '/home/app/log/truemail.log'
Expand Down Expand Up @@ -292,7 +292,7 @@ Truemail.configuration
@smtp_fail_fast=true,
@smtp_safe_check=true,
@logger=#<Truemail::Logger:0x0000557f837450b0
@event=:all, @file="/home/app/log/truemail.log", @logger_class=MyCustomLogger, @stdout=true>>
@event=:all, @file="/home/app/log/truemail.log", @custom_logger=nil @stdout=true>>
```

##### Update global configuration
Expand Down Expand Up @@ -328,7 +328,7 @@ Truemail.configuration
@smtp_fail_fast=true,
@smtp_safe_check=true,
@logger=#<Truemail::Logger:0x0000557f837450b0
@event=:all, @file="/home/app/log/truemail.log", @logger_class=MyCustomLogger, @stdout=true>>
@event=:all, @file="/home/app/log/truemail.log", @custom_logger=nil @stdout=true>>
```

##### Reset global configuration
Expand Down Expand Up @@ -1263,16 +1263,11 @@ end

#### Using custom logger

By default Truemail uses `Logger`, default logger class from Ruby stdlib. But you can override this behavior passing your own class in logger configuration. Please note, your own logger class should have the same interface as builtin stdlib `Logger` class.
By default Truemail uses `Logger`, default logger instance from Ruby stdlib. But you can override this behavior passing your logger instance in event logger configuration. Please note, your own logger instance should have the same interface as builtin stdlib `Logger` instance. In this case `custom_logger` is only one required field for logger configuration (you don't have to use `stdout` and `log_absolute_path`).

```ruby
Truemail.configure do |config|
config.logger = {
logger_class: MyCustomLogger,
tracking_event: :all,
stdout: true,
log_absolute_path: '/home/app/log/truemail.log'
}
config.logger = { custom_logger: MyCustomLogger.new }
end
```

Expand Down
19 changes: 2 additions & 17 deletions lib/truemail/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@

module Truemail
class Configuration
require 'logger'

DEFAULT_CONNECTION_TIMEOUT = 2
DEFAULT_RESPONSE_TIMEOUT = 2
DEFAULT_CONNECTION_ATTEMPTS = 2
DEFAULT_VALIDATION_TYPE = :smtp
DEFAULT_SMTP_PORT = 25
DEFAULT_LOGGER_OPTIONS = {
logger_class: ::Logger,
tracking_event: :error,
stdout: false,
log_absolute_path: nil
Expand Down Expand Up @@ -82,17 +79,9 @@ def argument_consistent?(method, argument)
end
end

def logger=(options) # rubocop:disable Metrics/AbcSize
def logger=(options)
raise_unless(options, __method__, options.is_a?(::Hash))
logger_class, tracking_event, stdout, log_absolute_path = logger_options(options)
raise_unless(logger_class, __method__, logger_class.is_a?(::Class))
valid_event = Truemail::Log::Event::TRACKING_EVENTS.key?(tracking_event)
stdout_only = stdout && log_absolute_path.nil?
file_only = log_absolute_path.is_a?(::String)
both_types = stdout && file_only
argument_info = valid_event ? log_absolute_path : tracking_event
raise_unless(argument_info, __method__, valid_event && (stdout_only || file_only || both_types))
@logger = Truemail::Logger.new(logger_class, tracking_event, stdout, log_absolute_path)
@logger = Truemail::Logger::Builder.call(Truemail::Configuration::DEFAULT_LOGGER_OPTIONS, **options)
end

def complete?
Expand Down Expand Up @@ -163,9 +152,5 @@ def validate_validation_type(settings)
check_validation_type(validation_type)
end
end

def logger_options(current_options)
Truemail::Configuration::DEFAULT_LOGGER_OPTIONS.merge(current_options).values
end
end
end
76 changes: 71 additions & 5 deletions lib/truemail/logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,67 @@

module Truemail
class Logger
attr_reader :logger_class, :event, :stdout, :file
require 'logger'

def initialize(logger_class, event, error_stdout, log_absolute_path)
@logger_class = logger_class
BUILDER_ATTRS = %i[tracking_event stdout log_absolute_path custom_logger].freeze

Builder = ::Struct.new(*BUILDER_ATTRS, keyword_init: true) do
private_class_method :new

def self.call(default_settings, **logger_attributes)
new(default_settings, **logger_attributes).validate_attributes.build_instance
end

def initialize(default_settings, **args)
super(**default_settings.merge(**args))
end

def validate_attributes
validate_logger_event
return validate_logger_instance if custom_logger
validate_logger_output
self
end

def build_instance
Truemail::Logger.new(tracking_event, stdout, log_absolute_path, custom_logger)
end

private

def raise_unless(argument_context, argument_name, condition)
raise Truemail::ArgumentError.new(argument_context, argument_name) unless condition
end

def validate_logger_instance
raise_unless(custom_logger, :custom_logger=, custom_logger && custom_logger.respond_to?(:add))
self
end

def validate_logger_event
raise_unless(tracking_event, :tracking_event=, Truemail::Log::Event::TRACKING_EVENTS.key?(tracking_event))
end

def validate_logger_output
stdout_only = stdout && log_absolute_path.nil?
file_only = log_absolute_path.is_a?(::String)
both_types = stdout && file_only
raise_unless(
{ stdout: stdout, log_absolute_path: log_absolute_path },
'stdout=, log_absolute_path=',
both_types || stdout_only || file_only
)
end
end

attr_reader :event, :stdout, :file, :custom_logger, :stdout_logger, :file_logger

def initialize(event, error_stdout, log_absolute_path, custom_logger)
@event = event
@stdout = error_stdout
@file = log_absolute_path
@custom_logger = custom_logger
init_builtin_loggers
end

def push(validator_instance)
Expand All @@ -26,10 +80,22 @@ def init_log_file
output_file
end

def create_logs(log_level, serialized_object)
def init_builtin_loggers
return if custom_logger
%i[stdout file].each do |output_type|
next unless public_send(output_type)
logger_class.new(output_type.eql?(:stdout) ? $stdout : init_log_file).add(log_level) { serialized_object }
instance_variable_set(
:"@#{output_type}_logger",
::Logger.new(output_type.eql?(:stdout) ? $stdout : init_log_file)
)
end
end

def create_logs(log_level, serialized_object)
%i[custom_logger stdout_logger file_logger].each do |getter|
logger_instance = public_send(getter)
next unless logger_instance
logger_instance.add(log_level) { serialized_object }
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/truemail/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Truemail
VERSION = '3.2.0'
VERSION = '3.3.0'
end
36 changes: 22 additions & 14 deletions spec/truemail/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@

specify do
expect(described_class::DEFAULT_LOGGER_OPTIONS).to eq(
logger_class: ::Logger,
tracking_event: :error,
stdout: false,
log_absolute_path: nil
Expand Down Expand Up @@ -645,6 +644,7 @@
end

let(:default_tracking_events_expectation) { expect(configuration_instance.logger.event).to eq(:error) }
let(:file) { Pathname(::File.expand_path('../support/tmp/log', ::File.dirname(__FILE__))) }

context 'when stdout only' do
let(:logger_params) { { stdout: true } }
Expand All @@ -659,7 +659,9 @@
end

context 'when file only' do
let(:logger_params) { { log_absolute_path: 'some_absolute_path' } }
let(:logger_params) { { log_absolute_path: file.to_s } }

after { ::FileUtils.rm_rf(file.dirname) }

include_examples 'sets logger instance'

Expand All @@ -671,7 +673,9 @@
end

context 'when stdout and file outputs' do
let(:logger_params) { { stdout: true, log_absolute_path: 'some_absolute_path' } }
let(:logger_params) { { stdout: true, log_absolute_path: file.to_s } }

after { ::FileUtils.rm_rf(file.dirname) }

include_examples 'sets logger instance'

Expand Down Expand Up @@ -702,12 +706,12 @@
end

context 'with valid logger class' do
let(:logger_class) { ::Class }
let(:logger_params) { { logger_class: logger_class, stdout: true } }
let(:custom_logger) { instance_double('LoggerClassInstance', add: 42) }
let(:logger_params) { { custom_logger: custom_logger, stdout: true } }

it 'sets logger class' do
set_logger
expect(configuration_instance.logger.logger_class).to eq(logger_class)
expect(configuration_instance.logger.custom_logger).to eq(custom_logger)
end
end
end
Expand All @@ -717,6 +721,10 @@
specify { expect { set_logger }.to raise_error(Truemail::ArgumentError, error_message) }
end

let(:error_message_wrong_logger_output) do
'{:stdout=>false, :log_absolute_path=>nil} is not a valid stdout=, log_absolute_path='
end

context 'with wrong params type' do
let(:logger_params) { 42 }
let(:error_message) { "#{logger_params} is not a valid logger=" }
Expand All @@ -726,39 +734,39 @@

context 'with empty params' do
let(:logger_params) { {} }
let(:error_message) { ' is not a valid logger=' }
let(:error_message) { error_message_wrong_logger_output }

include_examples 'raises logger argument error'
end

context 'with log_absolute_path wrong type' do
let(:log_absolute_path) { true }
let(:logger_params) { { log_absolute_path: log_absolute_path } }
let(:error_message) { "#{log_absolute_path} is not a valid logger=" }
let(:error_message) { '{:stdout=>false, :log_absolute_path=>true} is not a valid stdout=, log_absolute_path=' }

include_examples 'raises logger argument error'
end

context 'when attempt configure logger without output' do
let(:stdout) { false }
let(:logger_params) { { stdout: stdout } }
let(:error_message) { ' is not a valid logger=' }
let(:error_message) { error_message_wrong_logger_output }

include_examples 'raises logger argument error'
end

context 'with not existing tracking event' do
let(:tracking_event) { :not_existing_tracking_event }
let(:logger_params) { { tracking_event: tracking_event } }
let(:error_message) { "#{tracking_event} is not a valid logger=" }
let(:error_message) { "#{tracking_event} is not a valid tracking_event=" }

include_examples 'raises logger argument error'
end

context 'with valid logger class' do
let(:logger_class) { 42 }
let(:logger_params) { { logger_class: logger_class, stdout: true } }
let(:error_message) { "#{logger_class} is not a valid logger=" }
context 'with invalid logger class' do
let(:custom_logger_instance) { 42 }
let(:logger_params) { { custom_logger: custom_logger_instance, stdout: true } }
let(:error_message) { "#{custom_logger_instance} is not a valid custom_logger=" }

include_examples 'raises logger argument error'
end
Expand Down
Loading

0 comments on commit f3be34d

Please sign in to comment.