lib/semantic_logger/base.rb in semantic_logger-3.0.1 vs lib/semantic_logger/base.rb in semantic_logger-3.1.0

- old
+ new

@@ -19,11 +19,11 @@ # # Must be one of the values in SemanticLogger::LEVELS, or # nil if this logger instance should use the global default level def level=(level) @level_index = SemanticLogger.level_to_index(level) - @level = level + @level = SemanticLogger.send(:index_to_level, @level_index) end # Returns the current log level if set, otherwise it returns the global # default log level def level @@ -57,14 +57,14 @@ # # # Enable trace level logging # SemanticLogger.default_level = :info # # # Log to screen - # SemanticLogger.add_appender(STDOUT) + # SemanticLogger.add_appender(io: STDOUT, formatter: :color) # # # And log to a file at the same time - # SemanticLogger.add_appender('application.log') + # SemanticLogger.add_appender(file: 'application.log', formatter: :color) # # logger = SemanticLogger['MyApplication'] # logger.debug("Only display this if log level is set to Debug or lower") # # # Log semantic information along with a text message @@ -86,30 +86,40 @@ def #{level}? level_index <= #{index} end + def measure_#{level}(message, params = {}, &block) + if level_index <= #{index} + measure_internal(:#{level}, #{index}, message, params, &block) + else + block.call(params) if block + end + end + def benchmark_#{level}(message, params = {}, &block) if level_index <= #{index} - benchmark_internal(:#{level}, #{index}, message, params, &block) + measure_internal(:#{level}, #{index}, message, params, &block) else block.call(params) if block end end EOT end - # Dynamically supply the log level with every benchmark call - def benchmark(level, message, params = {}, &block) + # Dynamically supply the log level with every measurement call + def measure(level, message, params = {}, &block) index = SemanticLogger.level_to_index(level) if level_index <= index - benchmark_internal(level, index, message, params, &block) + measure_internal(level, index, message, params, &block) else block.call(params) if block end end + alias_method :benchmark, :measure + # If the tag being supplied is definitely a string then this fast # tag api can be used for short lived tags def fast_tag(tag) (Thread.current[:semantic_logger_tags] ||= []) << tag yield @@ -182,16 +192,10 @@ # Returns nil if no payload is currently set def payload Thread.current[:semantic_logger_payload] end - # Semantic Logging does not support :unknown level since these - # are not understood by the majority of the logging providers - # Map it to :error - alias :unknown :error - alias :unknown? :error? - # Silence noisy log levels by changing the default_level within the block # # This setting is thread-safe and only applies to the current thread # # Any threads spawned within the block will not be affected by this setting @@ -244,10 +248,17 @@ def self.default_level warn '[DEPRECATION] SemanticLogger::Logger.default_level is deprecated. Please use SemanticLogger.default_level instead.' SemanticLogger.default_level end + protected + + # Write log data to underlying data storage + def log(log_) + raise NotImplementedError.new('Logging Appender must implement #log(log)') + end + private # Initializer for Abstract Class SemanticLogger::Base # # Parameters @@ -273,50 +284,47 @@ @filter = filter.is_a?(Regexp) ? filter.freeze : filter @name = klass.is_a?(String) ? klass : klass.name self.level = level unless level.nil? end - # Write log data to underlying data storage - def log(log_) - raise NotImplementedError.new('Logging Appender must implement #log(log)') - end - # Return the level index for fast comparisons # Returns the global default level index if the level has not been explicitly # set for this instance def level_index @level_index || SemanticLogger.default_level_index end # Whether to log the supplied message based on the current filter if any - def include_message?(struct) + def include_message?(log) return true if @filter.nil? if @filter.is_a?(Regexp) - (@filter =~ struct.name) != nil + (@filter =~ log.name) != nil elsif @filter.is_a?(Proc) - @filter.call(struct) == true + @filter.call(log) == true end end # Log message at the specified level def log_internal(level, index, message=nil, payload=nil, exception=nil) - # Detect exception being logged - if exception.nil? && payload.nil? && message.kind_of?(Exception) + # Exception being logged? + # Under JRuby a java exception is not a Ruby Exception + # Java::JavaLang::ClassCastException.new.is_a?(Exception) => false + if exception.nil? && payload.nil? && message.respond_to?(:backtrace) && message.respond_to?(:message) exception = message message = nil elsif exception.nil? && payload && payload.respond_to?(:backtrace) && payload.respond_to?(:message) - # Under JRuby a java exception is not a Ruby Exception - # Java::JavaLang::ClassCastException.new.is_a?(Exception) => false exception = payload payload = nil end # Add result of block as message or payload if not nil if block_given? && (result = yield) if result.is_a?(String) message = message.nil? ? result : "#{message} -- #{result}" + elsif message.nil? && result.is_a?(Hash) + message = result elsif payload && payload.respond_to?(:merge) payload.merge(result) else payload = result end @@ -328,12 +336,29 @@ end # Add caller stack trace backtrace = extract_backtrace if index >= SemanticLogger.backtrace_level_index - struct = Log.new(level, Thread.current.name, name, message, payload, Time.now, nil, tags, index, exception, nil, backtrace) - log(struct) if include_message?(struct) + log = Log.new(level, Thread.current.name, name, message, payload, Time.now, nil, tags, index, exception, nil, backtrace) + + # Logging Hash only? + # logger.info(name: 'value') + if payload.nil? && exception.nil? && message.is_a?(Hash) + payload = message.dup + min_duration = payload.delete(:min_duration) || 0.0 + log.exception = payload.delete(:exception) + log.message = payload.delete(:message) + log.metric = payload.delete(:metric) + log.metric_amount = payload.delete(:metric_amount) || 1 + if duration = payload.delete(:duration) + return false if duration <= min_duration + log.duration = duration + end + log.payload = payload if payload.size > 0 + end + + self.log(log) if include_message?(log) end SELF_PATTERN = File.join('lib', 'semantic_logger') # Extract the callers backtrace leaving out Semantic Logger @@ -344,11 +369,11 @@ end stack end # Measure the supplied block and log the message - def benchmark_internal(level, index, message, params) + def measure_internal(level, index, message, params) start = Time.now exception = nil begin if block_given? result = @@ -405,19 +430,19 @@ else # Log the message with its duration but leave out the exception that was raised logged_exception = nil backtrace = exception.backtrace end - struct = Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, logged_exception, metric, backtrace) - log(struct) if include_message?(struct) + log = Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, logged_exception, metric, backtrace) + self.log(log) if include_message?(log) raise exception elsif duration >= min_duration # Only log if the block took longer than 'min_duration' to complete # Add caller stack trace backtrace = extract_backtrace if index >= SemanticLogger.backtrace_level_index - struct = Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, nil, metric, backtrace) - log(struct) if include_message?(struct) + log = Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, nil, metric, backtrace) + self.log(log) if include_message?(log) end end end end