smart_logger_wrapper 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f193215b0f2007b0861602a5169acd5b6f4fe8a2
4
- data.tar.gz: c6a426240e52e5f6d24fbfbe9151288f19115b57
3
+ metadata.gz: 558223eabf09d913bbcb7ff302e8324a898df644
4
+ data.tar.gz: 23d518a2d535c9fbd9a71ba4eb734d8402cff775
5
5
  SHA512:
6
- metadata.gz: 4545b47f0bc02df95cbc5699ae8243990851b894fd17569705b31d2a0369d95f0a6c02603f9e61c7ba3a5eb5dc3d85ace00b700e23aab555ac87a5352a623e86
7
- data.tar.gz: 45f5c6e4014e62913bba562bc61ed4b6da304ca091c53f0d08dbd274bf8f780a782c03917868a405849e4f4ec02b539dd0dcd8fa5ad0b8445a51dbc105426dff
6
+ metadata.gz: 8a5035037cd1fcde6dcd95fb7c8802c479ef11ade20dc8ebd9f11eb8c4e9f3f278e107f25b0bf8638fe3864708dd47a6114e193eeb1221a07b50d4e09a2ea8b5
7
+ data.tar.gz: e3c2fa794d687d95428e0c3a90a91a7d33a49a8dde282f42b1fd9a1448e40dc55aa09009e62cfce30be6ce15e591b67228ee30e15821f6344bfd991fc5ee26fc
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SmartLoggerWrapper
2
2
 
3
- SmartLoggerWrapper adds some useful features to the Ruby Logger or the compatibles. See Usage below to find out how it benefits your development.
3
+ SmartLoggerWrapper adds some useful features to the Ruby Logger or its subclasses. See Usage below to find out how it benefits your development.
4
4
 
5
5
  [![Build Status](https://travis-ci.org/akeyhero/smart_logger_wrapper.svg?branch=master)](https://travis-ci.org/akeyhero/smart_logger_wrapper)
6
6
 
@@ -29,7 +29,7 @@ Wrap your logger with `SmartLoggerWrapper`, for example, in `config/environments
29
29
  + config.logger = SmartLoggerWrapper(Logger.new('log/production.log', 'daily')).with_position
30
30
  ```
31
31
 
32
- Note that it is strongly recommended to use the wrapper for all environments so that you can avoid exceptions such as `NoMethodError` due to the unique features of this library.
32
+ Note that it is strongly recommended to use the wrapper for all kind of environments so that you can avoid exceptions such as `NoMethodError` due to the unique features of this library.
33
33
 
34
34
  You may want to put log messages to `STDOUT` in your development environment. Then:
35
35
 
@@ -44,7 +44,9 @@ You may want to put log messages to `STDOUT` in your development environment. Th
44
44
 
45
45
  ### Basic
46
46
 
47
- Initialize with a Ruby `Logger` or an instance of the compatibles (e.g. `ActiveSupport::TaggedLogging`):
47
+ This wrapper mainly modifies the behaviors of the following methods: `debug`, `info`, `warn`, `error`, `fatal`, and `unknown`.
48
+
49
+ To use this wrapper, initialize with a Ruby `Logger` or an instance of its subclass:
48
50
 
49
51
  ```ruby
50
52
  require 'logger'
@@ -58,8 +60,6 @@ logger.info 'Call logging methods as usual.'
58
60
  logger2 = SmartLoggerWrapper.new(Logger.new('log/development.log'), Logger.new(STDOUT))
59
61
  ```
60
62
 
61
- The compatibles must respond to `#add` with the same arguments as `Logger#add`.
62
-
63
63
  ### Feature 1: Integrate multiple logger calls
64
64
 
65
65
  `SmartLoggerWrapper` accepts multiple arguments like `puts` method does. Then the wrapped logger will be called for each of the arguments.
@@ -1,22 +1,21 @@
1
+ require 'logger'
1
2
  require 'smart_logger_wrapper/options/base'
2
3
  require 'smart_logger_wrapper/utils/backtrace'
3
4
 
4
- class SmartLoggerWrapper
5
+ class SmartLoggerWrapper < Logger
5
6
  module Options
6
7
  class AppendBacktrace < Base
7
8
  include ::SmartLoggerWrapper::Utils::Backtrace
8
9
 
9
- def initialize(start)
10
- super()
11
- @start = start
12
- end
13
-
14
- def apply!(messages, value = nil)
10
+ def apply!(messages, value, logger)
15
11
  length = value.is_a?(Numeric) ? value : nil
16
- messages << "BACKTRACE:\n" + get_backtrace(@start + 1, length).join("\n")
12
+ messages << [
13
+ 'BACKTRACE:',
14
+ *get_backtrace(logger.offset + APPLY_CALLER_STACK_DEPTH + 1, length)
15
+ ].join("\n")
17
16
  end
18
17
  end
19
18
 
20
- define_appender :append_backtrace, AppendBacktrace.new(APPLY_CALLER_STACK_DEPTH + 1)
19
+ define_appender :append_backtrace, AppendBacktrace.new
21
20
  end
22
21
  end
@@ -1,7 +1,9 @@
1
- class SmartLoggerWrapper
1
+ require 'logger'
2
+
3
+ class SmartLoggerWrapper < Logger
2
4
  module Options
3
5
  class Base
4
- def apply!(messages, value)
6
+ def apply!(messages, value, logger)
5
7
  raise NotImplementedError, __callee__
6
8
  end
7
9
  end
@@ -1,9 +1,10 @@
1
+ require 'logger'
1
2
  require 'smart_logger_wrapper/options/base'
2
3
 
3
- class SmartLoggerWrapper
4
+ class SmartLoggerWrapper < Logger
4
5
  module Options
5
6
  class To < Base
6
- def apply!(messages, value)
7
+ def apply!(messages, value, logger)
7
8
  raise ApplicationError, 'No handler given' if value == nil
8
9
  value.puts messages.join("\n")
9
10
  rescue NoMethodError => e
@@ -1,20 +1,16 @@
1
+ require 'logger'
1
2
  require 'smart_logger_wrapper/options/base'
2
3
  require 'smart_logger_wrapper/utils/path'
3
4
 
4
- class SmartLoggerWrapper
5
+ class SmartLoggerWrapper < Logger
5
6
  module Options
6
7
  class WithPosition < Base
7
8
  include ::SmartLoggerWrapper::Utils::Path
8
9
 
9
- def initialize(start)
10
- super()
11
- @start = start
12
- end
13
-
14
- def apply!(messages, value = nil)
10
+ def apply!(messages, value, logger)
15
11
  return if value == false
16
12
  # add 1 to `start` because this method dug the backtrace by 1
17
- location = caller_locations(@start + 1, 1)
13
+ location = caller_locations(logger.offset + APPLY_CALLER_STACK_DEPTH + 1, 1)
18
14
  prefix =
19
15
  if location && location.length > 0
20
16
  method_name = location[0].label
@@ -28,6 +24,6 @@ class SmartLoggerWrapper
28
24
  end
29
25
  end
30
26
 
31
- define_tagger :with_position, WithPosition.new(APPLY_CALLER_STACK_DEPTH + 1)
27
+ define_tagger :with_position, WithPosition.new
32
28
  end
33
29
  end
@@ -1,15 +1,19 @@
1
- class SmartLoggerWrapper
1
+ require 'logger'
2
+
3
+ class SmartLoggerWrapper < Logger
2
4
  module Options
3
5
  class ApplicationError < StandardError; end
4
6
 
5
- # XXX: Be careful! This relies strongly on the implementation of this and the callers
6
- APPLY_CALLER_STACK_DEPTH = 4
7
+ # XXX: Be careful! This relies strongly on the implementation of this class
8
+ APPLY_CALLER_STACK_DEPTH = 2
7
9
 
8
10
  module_function
9
11
 
10
- def apply_all!(messages, options)
12
+ def apply_all!(messages, logger)
11
13
  [defined_appenders, defined_taggers, defined_redirectors].flatten.each do |option_key|
12
- defined_options[option_key].apply!(messages, options[option_key]) if options.include?(option_key)
14
+ if logger.options.include?(option_key)
15
+ defined_options[option_key].apply!(messages, logger.options[option_key], logger)
16
+ end
13
17
  end
14
18
  end
15
19
 
@@ -1,6 +1,7 @@
1
+ require 'logger'
1
2
  require 'smart_logger_wrapper/utils/path'
2
3
 
3
- class SmartLoggerWrapper
4
+ class SmartLoggerWrapper < Logger
4
5
  module Utils
5
6
  module Backtrace
6
7
  module_function
@@ -1,4 +1,6 @@
1
- class SmartLoggerWrapper
1
+ require 'logger'
2
+
3
+ class SmartLoggerWrapper < Logger
2
4
  module Utils
3
5
  module Path
4
6
  DIR_TRIMMER_PATTERN = /^#{Dir.pwd}\/?/
@@ -1,3 +1,5 @@
1
- class SmartLoggerWrapper
2
- VERSION = "0.2.1"
1
+ require 'logger'
2
+
3
+ class SmartLoggerWrapper < Logger
4
+ VERSION = "0.3.0"
3
5
  end
@@ -2,9 +2,11 @@ require 'logger'
2
2
  require 'smart_logger_wrapper/version'
3
3
  require 'smart_logger_wrapper/options'
4
4
 
5
- class SmartLoggerWrapper
5
+ class SmartLoggerWrapper < Logger
6
6
  include Logger::Severity
7
7
 
8
+ LOGGER_SHORTCUT_OFFSET = 3
9
+
8
10
  SEVERITY_MAPPING = {
9
11
  debug: DEBUG,
10
12
  info: INFO,
@@ -14,33 +16,53 @@ class SmartLoggerWrapper
14
16
  unknown: UNKNOWN
15
17
  }.freeze
16
18
 
17
- attr_reader :loggers, :options
19
+ attr_reader :loggers, :options, :offset
18
20
 
19
21
  def initialize(logger = Logger.new(STDOUT), *loggers, **options)
20
- @loggers = [logger, *loggers]
21
- @options = options
22
- end
23
-
24
- def add(severity, *args, &block)
25
- _add(severity, *args, &block)
22
+ @loggers = [logger, *loggers].freeze
23
+ @options = options.freeze
24
+ @offset = LOGGER_SHORTCUT_OFFSET
25
+ @_loggers_cache = {}
26
+ @_loggers_with_offset_cache = {}
26
27
  end
27
- alias log add
28
28
 
29
+ # For all methods with severity label, logger accepts multiple messages.
30
+ # The return value is the first logger's.
29
31
  SEVERITY_MAPPING.each do |severity_name, severity|
30
32
  define_method(severity_name) do |*args, &block|
31
- _add(severity, *args, &block)
33
+ format_messages(*args, &block).map do |message|
34
+ add(severity, nil, message)
35
+ end.first
36
+ end
37
+ end
38
+
39
+ # Aside from #debug, #info, etc., all Logger instance methods are called for all the wrapped loggers.
40
+ # The return value is the first logger's.
41
+ (Logger.instance_methods(false) - SEVERITY_MAPPING.keys).each do |method_name|
42
+ define_method(method_name) do |*args, &block|
43
+ loggers.map do |logger|
44
+ logger.public_send(method_name, *args, &block)
45
+ end.first
32
46
  end
33
47
  end
34
48
 
49
+ def with_offset(_offset)
50
+ @_loggers_with_offset_cache[_offset] ||= clone.tap do |logger_with_offset|
51
+ logger_with_offset.instance_variable_set(:@offset, _offset)
52
+ end
53
+ end
54
+
55
+ def overwrite_options(_options)
56
+ @options = options.merge(_options).freeze
57
+ end
58
+
35
59
  private
36
60
 
37
- # All methods calling this must have the synchronized call stack depth so that this can show neat positions and backtraces
38
- def _add(severity, *args, &block)
61
+ def format_messages(*args, &block)
39
62
  messages = args.map { |arg| to_message(arg) }
40
63
  messages << to_message(block.call) if block_given?
41
64
  begin
42
- Options.apply_all!(messages, options)
43
- true
65
+ Options.apply_all!(messages, self)
44
66
  rescue Options::ApplicationError => e
45
67
  loggers.each do |logger|
46
68
  logger.error(<<~EOM)
@@ -48,14 +70,8 @@ class SmartLoggerWrapper
48
70
  #{e.backtrace.join("\n")}
49
71
  EOM
50
72
  end
51
- false
52
- end.tap do |succeeded|
53
- messages.each do |message|
54
- loggers.each do |logger|
55
- logger.add(severity, nil, message)
56
- end
57
- end
58
73
  end
74
+ messages
59
75
  end
60
76
 
61
77
  def to_message(object)
@@ -74,15 +90,15 @@ class SmartLoggerWrapper
74
90
  def method_missing(method_name, *args, &block)
75
91
  if Options.defined_option?(method_name)
76
92
  # If there is an defined option with the same name as the method name, return a new logger with the option.
77
- new_logger = self.class.new(*loggers, **options.merge(method_name => args.first))
93
+ arg = args.first
94
+ @_loggers_cache[method_name] = {} unless @_loggers_cache.include?(method_name)
95
+ new_logger = @_loggers_cache[method_name][arg] ||= clone.tap do |cloned|
96
+ cloned.overwrite_options(method_name => arg)
97
+ end
78
98
  return block.(new_logger) if block_given?
79
99
  new_logger
80
100
  else
81
- # Otherwise, call the method of the warpped logger.
82
- # The reutrn value is that of the first one.
83
- loggers.map do |logger|
84
- logger.public_send(method_name, *args, &block)
85
- end.first
101
+ super
86
102
  end
87
103
  end
88
104
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_logger_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akihiro Katsura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-03-23 00:00:00.000000000 Z
11
+ date: 2018-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler