Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/v4.0.2 #127

Merged
merged 17 commits into from
May 12, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
✨ LambDart - DRY Class and Instance Loggers
- `error_handler_proc` support for method signatures with kwargs
pboling committed May 12, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit e9ef25ceb569810fa2dca638c2f3c45cbb2d5742
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -15,10 +15,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- More documentation
### Changed
- DRY logic for `DebugLogging::ClassLogger` & `DebugLogging::InstanceLogger` via `LambDart`
### Fixed
- Add undeclared runtime dependency `version_gem`
- `DebugLogging::Hooks` integration via `extend`
- `DebugLogging::ClassNotifier` support for method signatures with kwargs
- `error_handler_proc` support for method signatures with kwargs
### Removed

## [4.0.1] ([tag][4.0.1t]) - 2024-03-01
2 changes: 2 additions & 0 deletions lib/debug_logging.rb
Original file line number Diff line number Diff line change
@@ -15,6 +15,8 @@
require "debug_logging/finalize"
require "debug_logging/argument_printer"
require "debug_logging/hooks"
require "debug_logging/lamb_dart"
require "debug_logging/lamb_dartable"
require "debug_logging/instance_logger_modulizer"
require "debug_logging/instance_logger"
require "debug_logging/class_logger"
74 changes: 22 additions & 52 deletions lib/debug_logging/class_logger.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
module DebugLogging
module ClassLogger
class << self
def extended(base)
base.extend(LambDartable)
end
end

def logged(*methods_to_log)
methods_to_log, payload, config_opts = DebugLogging::Util.extract_payload_and_config(
method_names: methods_to_log,
@@ -14,59 +20,23 @@ def logged(*methods_to_log)
)
original_method = method(method_to_log)
(class << self; self; end).class_eval do
define_method(method_to_log) do |*args, &block|
config_proxy = DebugLogging::Util.config_proxy_finder(
scope: self,
config_opts: method_config_opts,
method_name: method_to_log,
proxy_ref: "kl",
define_method(method_to_log) do |*args, **kwargs, &block|
lamb_dart = LambDart.new(
klass: self,
method_config_opts:,
method_payload:,
args:,
kwargs:,
method_to_log:,
)
method_return_value = nil
log_prefix = nil
invocation_id = nil
begin
config_proxy.log do
paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
log_prefix = debug_invocation_to_s(
klass: to_s,
separator: "::",
method_to_log: method_to_log,
config_proxy: config_proxy,
)
invocation_id = debug_invocation_id_to_s(args: args, config_proxy: config_proxy)
signature = debug_signature_to_s(args: args, config_proxy: config_proxy)
paymud = debug_payload_to_s(payload: paydirt, config_proxy: config_proxy)
"#{log_prefix}#{signature}#{invocation_id} debug: #{paymud}"
end
if config_proxy.benchmarkable_for?(:debug_class_benchmarks)
tms = Benchmark.measure do
method_return_value = if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
original_method.call(**harsh, &block)
else
original_method.call(*args, &block)
end
end
config_proxy.log do
"#{log_prefix} #{debug_benchmark_to_s(tms: tms)}#{invocation_id}"
end
else
method_return_value = if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
original_method.call(**harsh, &block)
else
original_method.call(*args, &block)
end
if config_proxy.exit_scope_markable? && invocation_id && !invocation_id.empty?
config_proxy.log do
"#{log_prefix} completed#{invocation_id}"
end
end
end
method_return_value
rescue StandardError => e
if config_proxy.error_handler_proc
config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_log, args)
else
raise e
real_mccoy = ->() {
original_method.call(*args, **kwargs, &block)
}
_dl_ld_enter_log(lamb_dart) do
_dl_ld_error_handle(lamb_dart) do
return _dl_ld_benchmarked(lamb_dart) { real_mccoy.call } if lamb_dart.bench?

_dl_ld_exit_log(lamb_dart) { real_mccoy.call }
end
end
end
6 changes: 6 additions & 0 deletions lib/debug_logging/instance_logger.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
module DebugLogging
module InstanceLogger
class << self
def extended(base)
base.include(LambDartable)
end
end

# NOTE: These params can be passed in / hidden in a last hash of *args
# NOTE: They can also be passed in discretely for each method, by passing *args as an array of arrays
# TODO: Refactor to use modern Ruby 3 *args, **kwargs instead
60 changes: 15 additions & 45 deletions lib/debug_logging/instance_logger_modulizer.rb
Original file line number Diff line number Diff line change
@@ -15,54 +15,24 @@ def to_mod(methods_to_log: nil, payload: nil, config: nil)
config: config_opts,
)
define_method(method_to_log) do |*args, **kwargs, &block|
method_return_value = nil
config_proxy = DebugLogging::Util.config_proxy_finder(
scope: self.class,
config_opts: method_config_opts,
method_name: method_to_log,
proxy_ref: "ilm",
lamb_dart = LambDart.new(
instance: self,
method_config_opts:,
method_payload:,
args:,
kwargs:,
method_to_log:,
)
log_prefix = self.class.debug_invocation_to_s(
klass: self.class.to_s,
separator: "#",
method_to_log: method_to_log,
config_proxy: config_proxy,
)
start_at = Time.now
start_timestamp = self.class.debug_time_to_s(start_at, config_proxy:)
invocation_id = self.class.debug_invocation_id_to_s(args:, kwargs:, start_at:, config_proxy:)
config_proxy.log do
paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
signature = self.class.debug_signature_to_s(args:, kwargs:, config_proxy:)
paymud = debug_payload_to_s(payload: paydirt, config_proxy:)
"#{start_timestamp}#{log_prefix}#{signature}#{invocation_id} debug: #{paymud}"
end
if config_proxy.benchmarkable_for?(:debug_instance_benchmarks)
tms = Benchmark.measure do
method_return_value = super(*args, **kwargs, &block)
end
end_timestamp = self.class.debug_time_to_s(Time.now, config_proxy:)
config_proxy.log do
"#{end_timestamp}#{log_prefix} #{self.class.debug_benchmark_to_s(tms: tms)}#{invocation_id}"
end
else
begin
method_return_value = super(*args, **kwargs, &block)
rescue StandardError => e
if config_proxy.error_handler_proc
config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_log, args, kwargs)
else
raise e
end
end
if config_proxy.exit_scope_markable? && invocation_id && !invocation_id.empty?
end_timestamp = self.class.debug_time_to_s(Time.now, config_proxy:)
config_proxy.log do
"#{end_timestamp}#{log_prefix} completed#{invocation_id}"
end
real_mccoy = ->() {
super(*args, **kwargs, &block)
}
_dl_ld_enter_log(lamb_dart) do
_dl_ld_error_handle(lamb_dart) do
return _dl_ld_benchmarked(lamb_dart) { real_mccoy.call } if lamb_dart.bench?

_dl_ld_exit_log(lamb_dart) { real_mccoy.call }
end
end
method_return_value
end
end
end
2 changes: 1 addition & 1 deletion lib/debug_logging/instance_notifier_modulizer.rb
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ def to_mod(methods_to_notify: nil, payload: nil, config: nil)
super(*args, **kwargs, &block)
rescue StandardError => e
if config_proxy.error_handler_proc
config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_notify, args, kwargs)
config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_notify, *args, **kwargs)
else
raise e
end
64 changes: 64 additions & 0 deletions lib/debug_logging/lamb_dart.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module DebugLogging
class LambDart
extend Forwardable

attr_reader :instance, # For ClassLogger, this will be the same as klass
:klass,
:config_proxy,
:method_payload,
:args,
:kwargs,
:method_to_log,
:log_prefix,
:invocation_id,
:start_at,
:scope_term

def_delegator :@config_proxy, :error_handler_proc

def initialize(instance: nil, klass: nil, method_config_opts:, method_payload:, args:, kwargs:, method_to_log:)
@start_at = Time.now
@instance = instance || klass
@klass = klass || instance.class
@method_payload = method_payload
@args = args
@kwargs = kwargs
@method_to_log = method_to_log
is_class = (self.klass == self.instance)
@scope_term = is_class ? "class" : "instance"
@config_proxy = DebugLogging::Util.config_proxy_finder(
scope: self.klass,
config_opts: method_config_opts,
method_name: self.method_to_log,
proxy_ref: is_class ? "kl" : "ilm",
)
@log_prefix = self.klass.debug_invocation_to_s(
klass: self.klass.to_s,
separator: is_class ? "::" : "#",
method_to_log: self.method_to_log,
config_proxy: config_proxy,
)
@invocation_id = self.klass.debug_invocation_id_to_s(args: self.args, config_proxy: config_proxy)
end

def end_timestamp
klass.debug_time_to_s(Time.now, config_proxy:)
end

def benchmarked(tms)
klass.debug_benchmark_to_s(tms: tms)
end

def mark_exit_scope?
config_proxy.exit_scope_markable? && invocation_id && !invocation_id.empty?
end

def bench_scope
"debug_#{scope_term}_benchmarks".to_sym
end

def bench?
config_proxy.benchmarkable_for?(bench_scope)
end
end
end
24 changes: 24 additions & 0 deletions lib/debug_logging/lamb_dartable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require_relative "lamb_darts/benchmarked"
require_relative "lamb_darts/enter_log"
require_relative "lamb_darts/error_handle"
require_relative "lamb_darts/exit_log"

module DebugLogging
module LambDartable
class << self
def included(base)
base.include(LambDarts::Benchmarked)
base.include(LambDarts::EnterLog)
base.include(LambDarts::ErrorHandle)
base.include(LambDarts::ExitLog)
end

def extended(base)
base.extend(LambDarts::Benchmarked)
base.extend(LambDarts::EnterLog)
base.extend(LambDarts::ErrorHandle)
base.extend(LambDarts::ExitLog)
end
end
end
end
19 changes: 19 additions & 0 deletions lib/debug_logging/lamb_darts/benchmarked.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module DebugLogging
module LambDarts
module Benchmarked
def _dl_ld_benchmarked(ld)
brv = nil
# Benchmarking as close to the real mccoy as possible,
# so as to not pollute performance tracking with the effects of debug_logging,
# which may be removed once data has been gathered, or turned off.
tms = Benchmark.measure do
brv = yield
end
ld.config_proxy.log do
"#{ld.end_timestamp}#{ld.log_prefix} #{ld.benchmarked(tms)}#{ld.invocation_id}"
end
brv
end
end
end
end
16 changes: 16 additions & 0 deletions lib/debug_logging/lamb_darts/enter_log.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module DebugLogging
module LambDarts
module EnterLog
def _dl_ld_enter_log(ld)
start_timestamp = ld.klass.debug_time_to_s(ld.start_at, config_proxy: ld.config_proxy)
ld.config_proxy.log do
paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: ld.instance, payload: ld.method_payload)
signature = ld.klass.debug_signature_to_s(args: ld.args, kwargs: ld.kwargs, config_proxy: ld.config_proxy)
paymud = ld.instance.debug_payload_to_s(payload: paydirt, config_proxy: ld.config_proxy)
"#{start_timestamp}#{ld.log_prefix}#{signature}#{ld.invocation_id} debug: #{paymud}"
end
yield
end
end
end
end
28 changes: 28 additions & 0 deletions lib/debug_logging/lamb_darts/error_handle.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module DebugLogging
module LambDarts
module ErrorHandle
def _dl_ld_error_handle(ld)
if ld.config_proxy.error_handler_proc
begin
yield
rescue StandardError => e
if ld.error_handler_proc
ld.error_handler_proc.call(
ld.config_proxy,
e,
self,
ld.method_to_log,
*ld.args,
**ld.kwargs,
)
else
raise e
end
end
else
yield
end
end
end
end
end
15 changes: 15 additions & 0 deletions lib/debug_logging/lamb_darts/exit_log.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module DebugLogging
module LambDarts
module ExitLog
def _dl_ld_exit_log(ld)
hrv = yield
return hrv unless ld.mark_exit_scope?

ld.config_proxy.log do
"#{ld.end_timestamp}#{ld.log_prefix} completed#{ld.invocation_id}"
end
hrv
end
end
end
end