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

Release/v4.0.2 #127

merged 17 commits into from
May 12, 2024

Conversation

pboling
Copy link
Owner

@pboling pboling commented May 12, 2024

4.0.2 (tag) - 2024-05-12

Added

  • More documentation

Changed

  • DRY logic for DebugLogging::ClassLogger & DebugLogging::InstanceLogger via LambDart
  • Refactored test suite; increased test coverage to 97%
  • Refactored ActiveSupport::Notification integration (DRY)

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

@jgillson refactored your work on ActiveSupport::Notifications. 💟 Would love any comments you have!

@coveralls
Copy link

coveralls commented May 12, 2024

Coverage Status

coverage: 95.493% (+3.0%) from 92.479%
when pulling dc3651f on release/v4.0.2
into 05cf4a0 on main.

@pboling pboling merged commit 1aa5193 into main May 12, 2024
11 checks passed
@pboling pboling deleted the release/v4.0.2 branch May 12, 2024 18:56
Comment on lines +23 to +39
define_method(decorated_method) do |*args, **kwargs, &block|
lamb_dart = LambDart::Log.new(
klass: self,
method_config_opts:,
method_payload:,
args:,
kwargs:,
decorated_method:,
)
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 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pboling - In this loop over the methods_to_log, could we extract this to a separate method (perhaps call it define_decorated_method); this way the code is a bit cleaner and potentially faster as it reduces the complexity inside each iteration of the loop.

def define_decorated_method(decorated_method, original_method, method_payload, method_config_opts)
    define_method(decorated_method) do |*args, **kwargs, &block|
      lamb_dart = LambDart::Log.new(
        klass: self,
        method_config_opts: method_config_opts,
        method_payload: method_payload,
        args: args,
        kwargs: kwargs,
        decorated_method: decorated_method
      )
      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
  end

And it would be called like this:

Array(methods_to_log).each do |decorated_method|

 ...

  (class << self; self; end).class_eval do
      define_decorated_method(decorated_method, original_method, method_payload, method_config_opts)
  end

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I've considered doing something like that. Attacking that complexity is a logical next step.

Comment on lines +15 to +34
Array(methods_to_notify).each do |decorated_method|
decorated_method, method_payload, method_config_opts = DebugLogging::Util.extract_payload_and_config(
method_names: decorated_method,
payload: payload,
config: config_opts,
)
original_method = method(method_to_notify)
original_method = method(decorated_method)
(class << self; self; end).class_eval do
define_method(method_to_notify) do |*args, &block|
config_proxy = DebugLogging::Util.config_proxy_finder(
scope: self,
config_opts: method_config_opts,
method_name: method_to_notify,
proxy_ref: "kn",
) do |proxy|
ActiveSupport::Notifications.subscribe(
DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify),
) do |*debug_args|
proxy.log do
DebugLogging::LogSubscriber.log_event(ActiveSupport::Notifications::Event.new(*debug_args))
end
end
end
paydirt = DebugLogging::Util.payload_instance_variable_hydration(scope: self, payload: method_payload)
ActiveSupport::Notifications.instrument(
DebugLogging::ArgumentPrinter.debug_event_name_to_s(method_to_notify: method_to_notify),
{
debug_args: args,
config_proxy: config_proxy,
**paydirt,
},
) do
if args.size == 1 && (harsh = args[0]) && harsh.is_a?(Hash)
original_method.call(**harsh, &block)
else
original_method.call(*args, &block)
end
rescue StandardError => e
if config_proxy.error_handler_proc
config_proxy.error_handler_proc.call(config_proxy, e, self, method_to_notify, args)
else
raise e
define_method(decorated_method) do |*args, **kwargs, &block|
lamb_dart = LambDart::Note.new(
klass: self,
method_config_opts:,
method_payload:,
args:,
kwargs:,
decorated_method:,
)
_dl_ld_notify(lamb_dart) do
_dl_ld_error_handle(lamb_dart) do
original_method.call(*args, **kwargs, &block)
Copy link
Contributor

@jgillson jgillson May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can do the same here as mentioned in the above comment. Perhaps with instance_logger_modularizer.rb, instance_notifier_modularizer.rb, and simple_debug_logging.rb as well.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, ideally we could normalize them all, and DRY them up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants