pboling/debug_logging

View on GitHub
lib/debug_logging.rb

Summary

Maintainability
A
0 mins
Test Coverage
# Std Lib
require "logger"
require "digest"

# External gems
require "version_gem"
require "colorized_string"

# This gem
require "debug_logging/constants"
require "debug_logging/version"
require "debug_logging/errors"
require "debug_logging/configuration"
require "debug_logging/util"
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"

####################
#                  #
# USAGE (see specs)#
#                  #
#     class Car
#
#       # adds the helper methods to the class, all are prefixed with debug_*,
#       #   except for the logged class method, which comes from extending DebugLogging::ClassLogger
#       extend DebugLogging
#
#       # per class configuration overrides!
#       self.debug_class_benchmarks = true
#       self.debug_instance_benchmarks = true
#
#       # For instance methods:
#       # Option 1: specify the exact method(s) to add logging to
#       extend DebugLogging::InstanceLogger
#       i_logged [:drive, :stop]
#
#       # Provides the `logged` method decorator
#       extend DebugLogging::ClassLogger
#
#       logged def debug_make; new; end
#       def design(*args); new; end
#       def safety(*args); new; end
#       logged :design, :safety
#
#       def drive(speed); speed; end
#       def stop; 0; end
#
#       # For instance methods:
#       # Option 2: add logging to all instance methods defined above (but *not* defined below)
#       extend DebugLogging::InstanceLogger
#       i_logged instance_methods(false)
#
#       def will_not_be_logged; false; end
#
#     end
#                  #
####################

module DebugLogging
  # We can't compare with nil to check for no arguments passed as a configuration value,
  #   because nil can be an argument passed, hence:
  ACTUAL_NOTHING = Object.new

  class << self
    def extended(base)
      base.send(:extend, ArgumentPrinter)
      base.send(:include, ArgumentPrinter)
      base.send(:extend, ApiClassMethods)
      base.send(:extend, ConfigClassMethods)
      base.debug_config_reset(Configuration.new(**debug_logging_configuration.to_hash))
      base.class_eval do
        def base.inherited(subclass)
          subclass.debug_config_reset(Configuration.new(**debug_config.to_hash))
        end
      end
    end

    #### API ####

    # For single statement global config in an initializer
    # e.g. DebugLogging.configuration.ellipsis = "..."
    def configuration
      self.debug_logging_configuration ||= Configuration.new
    end

    # For global config in an initializer with a block
    def configure
      yield(configuration)
    end
  end

  module ApiClassMethods
    # Not used by this gem internally, but provides an external interface for
    #   classes to also use this logging tool directly,
    #   with configured options like benchmarking, colors, or leg level.
    def debug_log(message = nil, config_proxy = nil, &block)
      # If a, instance-method-level, or class-method-level custom config is not
      #   passed in, then fall back to the class' default config, which is a
      #   potentially customized copy of the default config for the whole app.
      config_proxy ||= debug_config
      config_proxy.log(message, &block)
    end

    # There are times when the class will need access to the configuration object,
    #   such as to override it per instance method
    def debug_config
      @debug_logging_configuration
    end
  end

  #### CONFIG ####
  class << self
    attr_accessor :debug_logging_configuration
  end

  module ConfigClassMethods
    include Constants

    # For per-class config with a block
    def debug_logging_configure
      @debug_logging_configuration ||= Configuration.new
      yield(@debug_logging_configuration)
    end

    def debug_config_reset(config = Configuration.new)
      @debug_logging_configuration = config
    end

    def debug_enabled
      @debug_logging_configuration.enabled
    end

    def debug_enabled=(value)
      @debug_logging_configuration.enabled = value
    end

    def debug_logger
      @debug_logging_configuration.logger
    end

    def debug_logger=(logger)
      @debug_logging_configuration.logger = logger
    end

    def debug_log_level
      @debug_logging_configuration.log_level
    end

    def debug_log_level=(log_level)
      @debug_logging_configuration.log_level = log_level
    end

    def debug_multiple_last_hashes
      @debug_logging_configuration.multiple_last_hashes
    end

    def debug_multiple_last_hashes=(multiple_last_hashes)
      @debug_logging_configuration.multiple_last_hashes = multiple_last_hashes
    end

    def debug_last_hash_to_s_proc
      @debug_logging_configuration.last_hash_to_s_proc
    end

    def debug_last_hash_to_s_proc=(last_hash_to_s_proc)
      @debug_logging_configuration.last_hash_to_s_proc = last_hash_to_s_proc
    end

    def debug_last_hash_max_length
      @debug_logging_configuration.last_hash_max_length
    end

    def debug_last_hash_max_length=(last_hash_max_length)
      @debug_logging_configuration.last_hash_max_length = last_hash_max_length
    end

    def debug_args_to_s_proc
      @debug_logging_configuration.args_to_s_proc
    end

    def debug_args_to_s_proc=(args_to_s_proc)
      @debug_logging_configuration.args_to_s_proc = args_to_s_proc
    end

    def debug_args_max_length
      @debug_logging_configuration.args_max_length
    end

    def debug_args_max_length=(args_max_length)
      @debug_logging_configuration.args_max_length = args_max_length
    end

    def debug_instance_benchmarks
      @debug_logging_configuration.instance_benchmarks
    end

    def debug_instance_benchmarks=(instance_benchmarks)
      @debug_logging_configuration.instance_benchmarks = instance_benchmarks
    end

    def debug_class_benchmarks
      @debug_logging_configuration.class_benchmarks
    end

    def debug_class_benchmarks=(class_benchmarks)
      @debug_logging_configuration.class_benchmarks = class_benchmarks
    end

    def debug_colorized_chain_for_method
      @debug_logging_configuration.colorized_chain_for_method
    end

    def debug_colorized_chain_for_method=(colorized_chain_for_method)
      @debug_logging_configuration.colorized_chain_for_method = colorized_chain_for_method
    end

    def debug_colorized_chain_for_class
      @debug_logging_configuration.colorized_chain_for_class
    end

    def debug_colorized_chain_for_class=(colorized_chain_for_class)
      @debug_logging_configuration.colorized_chain_for_class = colorized_chain_for_class
    end

    def debug_add_timestamp
      @debug_logging_configuration.add_timestamp
    end

    def debug_add_timestamp=(add_timestamp)
      @debug_logging_configuration.add_timestamp = add_timestamp
    end

    def debug_time_formatter_proc
      @debug_logging_configuration.time_formatter_proc
    end

    def debug_time_formatter_proc=(time_formatter_proc)
      @debug_logging_configuration.time_formatter_proc = time_formatter_proc
    end

    def debug_add_invocation_id
      @debug_logging_configuration.add_invocation_id
    end

    def debug_add_invocation_id=(add_invocation_id)
      @debug_logging_configuration.add_invocation_id = add_invocation_id
    end

    def debug_ellipsis
      @debug_logging_configuration.ellipsis
    end

    def debug_ellipsis=(ellipsis)
      @debug_logging_configuration.ellipsis = ellipsis
    end

    def debug_mark_scope_exit
      @debug_logging_configuration.mark_scope_exit
    end

    def debug_mark_scope_exit=(mark_scope_exit)
      @debug_logging_configuration.mark_scope_exit = mark_scope_exit
    end

    def debug_add_payload
      @debug_logging_configuration.add_payload
    end

    def debug_add_payload=(add_payload)
      @debug_logging_configuration.add_payload = add_payload
    end

    def debug_payload_max_length
      @debug_logging_configuration.payload_max_length
    end

    def debug_payload_max_length=(payload_max_length)
      @debug_logging_configuration.payload_max_length = payload_max_length
    end

    def debug_error_handler_proc
      @debug_logging_configuration.error_handler_proc
    end

    def debug_error_handler_proc=(error_handler_proc)
      @debug_logging_configuration.error_handler_proc = error_handler_proc
    end
  end

  self.debug_logging_configuration = Configuration.new # setup defaults
end

DebugLogging::Version.class_eval do
  extend VersionGem::Basic
end