smart_logger_wrapper 0.4.3 → 0.5.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 +5 -5
- data/.ruby-version +1 -0
- data/README.md +14 -8
- data/lib/smart_logger_wrapper/options/append_backtrace.rb +2 -2
- data/lib/smart_logger_wrapper/options/base.rb +1 -1
- data/lib/smart_logger_wrapper/options/to.rb +4 -3
- data/lib/smart_logger_wrapper/options/with_position.rb +12 -3
- data/lib/smart_logger_wrapper/options.rb +3 -3
- data/lib/smart_logger_wrapper/version.rb +1 -1
- data/lib/smart_logger_wrapper.rb +44 -21
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d466f7e45ea8cef683330d3ac32cbe04e13b23e1887b36e4383999018778dbb7
|
4
|
+
data.tar.gz: 86b7a9d0f135905ce16d46e6e69131eec966f2486791c90d646bbb7cdf439aef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b299638a87014710a8a04ca9f54a43b6d4bf36dc53324e77fe1830a30634ffb5871efaca002f54ebd5a5edb320f5d8c8a7530873d1b4406c9e1f6cc628eaddf
|
7
|
+
data.tar.gz: 494b1d44d563486e4ee737da7bf0208be22c343893f2fb2bfe8b160d48e008d5816ad81ea6a39b453cea203f410dec021ff9deffd1c356764758f3636b342054
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.1
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ Wrap your logger with `SmartLoggerWrapper`, for example, in `config/environments
|
|
26
26
|
|
27
27
|
```diff
|
28
28
|
- config.logger = Logger.new('log/production.log', 'daily')
|
29
|
-
+ config.logger = SmartLoggerWrapper(Logger.new('log/production.log', 'daily')).with_position
|
29
|
+
+ config.logger = SmartLoggerWrapper.new(Logger.new('log/production.log', 'daily')).with_position
|
30
30
|
```
|
31
31
|
|
32
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.
|
@@ -105,7 +105,7 @@ logger.to(STDERR).info 'A message'
|
|
105
105
|
|
106
106
|
#### #with\_position
|
107
107
|
|
108
|
-
`with_position` option makes the logger tag the position where the logger is called.
|
108
|
+
`with_position` option makes the logger tag the position where the logger is called. On Rails, this information will be filtered by `Rails.backtrace_cleaner` not to bother you with annoying long file paths on logs generated by Rails.
|
109
109
|
|
110
110
|
```ruby
|
111
111
|
logger.with_position.info 'A message'
|
@@ -140,11 +140,11 @@ For instance, in the case you want to integrate a messenger, such as Slack, in a
|
|
140
140
|
|
141
141
|
```ruby
|
142
142
|
SmartLoggerWrapper::Options.define_redirector :to_messenger, Class.new(SmartLoggerWrapper::Options::Base) {
|
143
|
-
def apply!(messages,
|
144
|
-
channel =
|
143
|
+
def apply!(messages, arguments, severity, wrapper)
|
144
|
+
channel = arguments.first || 'general'
|
145
145
|
time = Time.now
|
146
146
|
severity_label = wrapper.format_severity(severity)
|
147
|
-
formatted_messages = messages.map { |message| wrapper.
|
147
|
+
formatted_messages = messages.map { |message| wrapper.format_message(severity_label, time, nil, message) }
|
148
148
|
Thread.new do
|
149
149
|
SomeMessenger.new(channel: channel).post(['```', *formatted_messages, '```'].join("\n"))
|
150
150
|
end
|
@@ -158,17 +158,23 @@ Then, you can post log messages as follows:
|
|
158
158
|
Rails.logger.to_messenger('channel').error('foo')
|
159
159
|
```
|
160
160
|
|
161
|
+
#### Implementation
|
162
|
+
|
163
|
+
Eash option is expected to be defined with a subclass of `SmartLoggerWrapper::Options::Base`. The class is required to respond to `#apply!` with the following arguments: `messages`, `argument`, `severity` and `wrapper`. Firstly, `messages` is an array of messages to be logged. In the case that you want to update the messages, you need to destructively update the array (because of its performance). Second, `argument` is the one which is passed as the option method argument. `severity` is an integer in response to `Logger::Severity`. Lastly, `wrapper` is the caller `SmartLoggerWrapper`.
|
164
|
+
|
165
|
+
#### Option priority
|
166
|
+
|
161
167
|
There are three categories for `SmartLoggerWrapper::Options`. Each option will be applied in the following order according to its category:
|
162
168
|
|
163
|
-
|
169
|
+
##### 1. Tagger
|
164
170
|
|
165
171
|
A tagger is expected to be used to tag each message. To define a tagger, you will call `SmartLoggerWrapper::Options.define_tagger`.
|
166
172
|
|
167
|
-
|
173
|
+
##### 2. Appender
|
168
174
|
|
169
175
|
An appender is expected to append some additinal information to the message list. To define an appender, you will call `SmartLoggerWrapper::Options.define_appender`.
|
170
176
|
|
171
|
-
|
177
|
+
##### 3. Redirector
|
172
178
|
|
173
179
|
A redirector should put messages to another location from the one where the wrapped logger specifies. To define a redirector, you will call `SmartLoggerWrapper::Options.define_redirector`.
|
174
180
|
|
@@ -7,8 +7,8 @@ class SmartLoggerWrapper < Logger
|
|
7
7
|
class AppendBacktrace < Base
|
8
8
|
include ::SmartLoggerWrapper::Utils::Backtrace
|
9
9
|
|
10
|
-
def apply!(messages,
|
11
|
-
length =
|
10
|
+
def apply!(messages, arguments, severity, wrapper)
|
11
|
+
length = arguments.first.is_a?(Numeric) ? arguments.first : nil
|
12
12
|
messages << [
|
13
13
|
'BACKTRACE:',
|
14
14
|
*get_backtrace(wrapper.offset + APPLY_CALLER_STACK_DEPTH + 1, length)
|
@@ -4,11 +4,12 @@ require 'smart_logger_wrapper/options/base'
|
|
4
4
|
class SmartLoggerWrapper < Logger
|
5
5
|
module Options
|
6
6
|
class To < Base
|
7
|
-
def apply!(messages,
|
8
|
-
raise ApplicationError, 'No handler given' if
|
7
|
+
def apply!(messages, arguments, severity, wrapper)
|
8
|
+
raise ApplicationError, 'No handler given' if arguments.empty?
|
9
|
+
out = arguments.first
|
9
10
|
time = Time.now
|
10
11
|
severity_label = wrapper.format_severity(severity)
|
11
|
-
|
12
|
+
out.puts messages.map { |message| wrapper.format_message(severity_label, time, nil, message) }.join("\n")
|
12
13
|
rescue NoMethodError => e
|
13
14
|
raise ApplicationError, e.message
|
14
15
|
end
|
@@ -1,18 +1,21 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'smart_logger_wrapper/options/base'
|
3
3
|
require 'smart_logger_wrapper/utils/path'
|
4
|
+
require 'smart_logger_wrapper/utils/backtrace'
|
4
5
|
|
5
6
|
class SmartLoggerWrapper < Logger
|
6
7
|
module Options
|
7
8
|
class WithPosition < Base
|
8
9
|
include ::SmartLoggerWrapper::Utils::Path
|
10
|
+
include ::SmartLoggerWrapper::Utils::Backtrace
|
9
11
|
|
10
|
-
def apply!(messages,
|
11
|
-
|
12
|
+
def apply!(messages, arguments, severity, wrapper)
|
13
|
+
enabled = arguments.first || true
|
14
|
+
return unless enabled
|
12
15
|
# add 1 to `start` because this method dug the backtrace by 1
|
13
16
|
location = caller_locations(wrapper.offset + APPLY_CALLER_STACK_DEPTH + 1, 1)
|
14
17
|
prefix =
|
15
|
-
if location && location.length > 0
|
18
|
+
if location && location.length > 0 && location_important?(location)
|
16
19
|
method_name = location[0].label
|
17
20
|
path = trim_dirname(location[0].absolute_path)
|
18
21
|
lineno = location[0].lineno
|
@@ -22,6 +25,12 @@ class SmartLoggerWrapper < Logger
|
|
22
25
|
end
|
23
26
|
messages.map! { |message| [prefix, message].compact.join(' ') }
|
24
27
|
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def location_important?(location)
|
32
|
+
! clean_backtrace(location.map(&:to_s)).empty?
|
33
|
+
end
|
25
34
|
end
|
26
35
|
|
27
36
|
define_tagger :with_position, WithPosition
|
@@ -9,10 +9,10 @@ class SmartLoggerWrapper < Logger
|
|
9
9
|
|
10
10
|
module_function
|
11
11
|
|
12
|
-
def apply_all!(messages, severity,
|
12
|
+
def apply_all!(messages, severity, wrapper)
|
13
13
|
[defined_appenders, defined_taggers, defined_redirectors].flatten.each do |option_key|
|
14
|
-
if
|
15
|
-
defined_options[option_key].apply!(messages,
|
14
|
+
if wrapper.options.include?(option_key)
|
15
|
+
defined_options[option_key].apply!(messages, wrapper.options[option_key], severity, wrapper)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/lib/smart_logger_wrapper.rb
CHANGED
@@ -5,7 +5,8 @@ require 'smart_logger_wrapper/options'
|
|
5
5
|
class SmartLoggerWrapper < Logger
|
6
6
|
include Logger::Severity
|
7
7
|
|
8
|
-
|
8
|
+
BASE_OFFSET = 3
|
9
|
+
NESTED_WRAPPER_OFFSET = 6
|
9
10
|
|
10
11
|
SEVERITY_MAPPING = {
|
11
12
|
debug: DEBUG,
|
@@ -15,16 +16,16 @@ class SmartLoggerWrapper < Logger
|
|
15
16
|
fatal: FATAL,
|
16
17
|
unknown: UNKNOWN
|
17
18
|
}.freeze
|
18
|
-
DELEGETING_METHODS = %i(<< reopen close log add level debug? level= progname datetime_format= datetime_format formatter sev_threshold sev_threshold= info? warn? error? fatal? progname= formatter=)
|
19
|
+
DELEGETING_METHODS = %i(<< reopen close log add level debug? level= progname datetime_format= datetime_format formatter sev_threshold sev_threshold= info? warn? error? fatal? progname= formatter=).freeze
|
19
20
|
|
20
|
-
attr_reader :loggers, :options, :
|
21
|
+
attr_reader :loggers, :options, :base_offset, :parent
|
21
22
|
|
22
|
-
def initialize(logger = Logger.new(STDOUT), *loggers, **options)
|
23
|
-
@
|
23
|
+
def initialize(logger = Logger.new(STDOUT), *loggers, base_offset: nil, parent: nil, **options)
|
24
|
+
@base_offset = base_offset || BASE_OFFSET
|
25
|
+
@parent = parent
|
26
|
+
@loggers = be_parent_of!(logger, *loggers).freeze
|
24
27
|
@options = options.freeze
|
25
|
-
@offset = LOGGER_SHORTCUT_OFFSET
|
26
28
|
@_loggers_cache = {}
|
27
|
-
@_loggers_with_offset_cache = {}
|
28
29
|
end
|
29
30
|
|
30
31
|
# For all methods with severity label, logger accepts multiple messages.
|
@@ -49,14 +50,13 @@ class SmartLoggerWrapper < Logger
|
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
52
|
-
def
|
53
|
-
@
|
54
|
-
logger_with_offset.instance_variable_set(:@offset, _offset)
|
55
|
-
end
|
53
|
+
def offset
|
54
|
+
@base_offset + depth * NESTED_WRAPPER_OFFSET
|
56
55
|
end
|
57
56
|
|
58
|
-
def
|
59
|
-
|
57
|
+
def depth
|
58
|
+
return 0 if root?
|
59
|
+
parent.depth + 1
|
60
60
|
end
|
61
61
|
|
62
62
|
def format_severity(severity)
|
@@ -67,6 +67,11 @@ class SmartLoggerWrapper < Logger
|
|
67
67
|
loggers.first.send(:format_message, severity, datetime, progname, msg)
|
68
68
|
end
|
69
69
|
|
70
|
+
def with_option(option_name, *args)
|
71
|
+
new_options = options.merge(option_name => args)
|
72
|
+
self.class.new(*loggers, base_offset: base_offset, **new_options)
|
73
|
+
end
|
74
|
+
|
70
75
|
private
|
71
76
|
|
72
77
|
def build_messages(severity, *args, &block)
|
@@ -98,18 +103,36 @@ class SmartLoggerWrapper < Logger
|
|
98
103
|
end
|
99
104
|
end
|
100
105
|
|
106
|
+
def set_parent!(new_parent)
|
107
|
+
@_loggers_cache.clear if new_parent != nil
|
108
|
+
@parent = new_parent == self ? nil : new_parent # to avoid stack overflow at #depth
|
109
|
+
end
|
110
|
+
|
111
|
+
def be_parent_of!(*loggers)
|
112
|
+
loggers.each do |logger|
|
113
|
+
# XXX: Calling a private method because it is an internal procedure
|
114
|
+
logger.is_a?(SmartLoggerWrapper) ? logger.send(:set_parent!, self) : logger
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def root?
|
119
|
+
parent == nil
|
120
|
+
end
|
121
|
+
|
101
122
|
def method_missing(method_name, *args, &block)
|
102
|
-
if Options.defined_option?(method_name)
|
103
|
-
#
|
104
|
-
|
123
|
+
if root? && Options.defined_option?(method_name)
|
124
|
+
# When the root wrapper receive an defined option with the same name as the method name,
|
125
|
+
# return a new logger wrapper with the option.
|
105
126
|
@_loggers_cache[method_name] = {} unless @_loggers_cache.include?(method_name)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
return block.(new_logger) if block_given?
|
110
|
-
new_logger
|
127
|
+
logger_with_option = @_loggers_cache[method_name][args] ||= with_option(method_name, *args)
|
128
|
+
return block.(logger_with_option) if block_given?
|
129
|
+
logger_with_option
|
111
130
|
else
|
112
131
|
super
|
113
132
|
end
|
114
133
|
end
|
134
|
+
|
135
|
+
def respond_to_missing?(method_name, includes_private)
|
136
|
+
root? && Options.defined_option?(method_name) || super
|
137
|
+
end
|
115
138
|
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.
|
4
|
+
version: 0.5.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-
|
11
|
+
date: 2018-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -61,6 +61,7 @@ extra_rdoc_files: []
|
|
61
61
|
files:
|
62
62
|
- ".gitignore"
|
63
63
|
- ".rspec"
|
64
|
+
- ".ruby-version"
|
64
65
|
- ".travis.yml"
|
65
66
|
- Gemfile
|
66
67
|
- LICENSE.txt
|
@@ -98,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
99
|
version: '0'
|
99
100
|
requirements: []
|
100
101
|
rubyforge_project:
|
101
|
-
rubygems_version: 2.6
|
102
|
+
rubygems_version: 2.7.6
|
102
103
|
signing_key:
|
103
104
|
specification_version: 4
|
104
105
|
summary: SmartLoggerWrapper adds some useful features to the Ruby Logger or a subclass.
|