smart_logger_wrapper 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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