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