ougai-formatters-customizable 0.1.0 → 1.0.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 +4 -4
- data/README.md +311 -39
- data/lib/ougai/formatters/colors.rb +28 -6
- data/lib/ougai/formatters/colors/configuration.rb +24 -13
- data/lib/ougai/formatters/customizable.rb +160 -145
- data/lib/ougai/formatters/customizable/version.rb +8 -7
- metadata +29 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9ac580c652c5578865e731227f1488dfb95bec37644f78366414bc69268424c
|
4
|
+
data.tar.gz: b8afc7c9c56f01bcd742987e08c4e0daa201aad503fd86c9950061169bb3a440
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92ae20d2af4f58607ceaebc80197d3195441a5b2e54733ec2bdc094c0a479425e7c5f85403a80c194455cdfbbd1bf7080b9c55ddd746dba6c680fec7ec454602
|
7
|
+
data.tar.gz: 9e1adbf551fc7f260a92155da26d5959c2819d8905f0be3495b96a133338a2da6489036f23ca427bf64826106ec3adacb9fc1798032aa06a572476ff45480ade
|
data/README.md
CHANGED
@@ -1,39 +1,311 @@
|
|
1
|
-
# Ougai
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
1
|
+
# Ougai-formatters-customizable
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/ougai-formatters-customizable)
|
4
|
+
[](https://travis-ci.com/Al-un/ougai-formatters-customizable)
|
5
|
+
[](https://codeclimate.com/github/Al-un/ougai-formatters-customizable/maintainability)
|
6
|
+
[](https://codeclimate.com/github/Al-un/ougai-formatters-customizable/test_coverage)
|
7
|
+
|
8
|
+
A fully customizable formatters for [Ougai](https://github.com/tilfin/ougai)
|
9
|
+
library. Customization is about formatting and colorization
|
10
|
+
|
11
|
+
**Formatting**
|
12
|
+
|
13
|
+
Ougai log printing can be split in three components:
|
14
|
+
|
15
|
+
1. Main log message: usually timestamp, log severity and a message
|
16
|
+
2. Data: the structured logging, represented by a Hash
|
17
|
+
3. Errors
|
18
|
+
|
19
|
+
**Colorization**
|
20
|
+
|
21
|
+
Each part of the main log message can be colored independently. Colorization can
|
22
|
+
be extended to custom formatters as well.
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
In your Gemfile, add *ougai-formatters-customizable* and its dependencies:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem 'awesome_print'
|
30
|
+
gem 'ougai'
|
31
|
+
gem 'ougai-formatters-customizable'
|
32
|
+
```
|
33
|
+
|
34
|
+
Then initialize a formatter and assign it to your logger:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
formatter = Ougai::Formatters::Customizable.new
|
38
|
+
# See Ougai documentation about how to initialize a Ougai logger
|
39
|
+
logger.formatter = formatter
|
40
|
+
```
|
41
|
+
|
42
|
+
The default *Customizable* configuration is exactly identical to a
|
43
|
+
*Ougai::Formatters::Readable* as-of Ougai 1.7.0.
|
44
|
+
|
45
|
+
#### Datetime format
|
46
|
+
|
47
|
+
Inherited from Ruby logger formatters, you can assign a datetime format:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
formatter.datetime_format = '%H:%M:%S.%L' # print time only such as '15:42:36.246'
|
51
|
+
```
|
52
|
+
|
53
|
+
#### Message formatter: `format_msg`
|
54
|
+
|
55
|
+
Main log message formatter is a `proc` which takes four arguments:
|
56
|
+
|
57
|
+
- [String] severity: log severity. Is in capital letters
|
58
|
+
- [String] datetime: log timestamp. Is already formatted according to `datetime_format`.
|
59
|
+
Has to be treated like a String
|
60
|
+
- [String] progname: optional program name
|
61
|
+
- [Hash] data: structured log data. The main message is logged under the `:msg` key.
|
62
|
+
|
63
|
+
Custom message formatter can be assigned at initialization via the key `format_msg`:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
formatter = Ougai::Formatters::Customizable.new(
|
67
|
+
format_msg: proc do |severity, datetime, _progname, data|
|
68
|
+
msg = data.delete(:msg)
|
69
|
+
format('%s %s: %s', severity, datetime, msg)
|
70
|
+
end
|
71
|
+
)
|
72
|
+
```
|
73
|
+
|
74
|
+
**Notes**
|
75
|
+
|
76
|
+
- It is recommended that this proc removes the `:msg` key from `data` to avoid
|
77
|
+
duplicates
|
78
|
+
- Although not mandatory, this formatter aims at outputting a single line String
|
79
|
+
|
80
|
+
#### Data formatter: `format_data`
|
81
|
+
|
82
|
+
Data formatter is a `proc` which takes only `data` as argument. Custom data
|
83
|
+
formatter can be assigned at initialization via `format_data` key:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
formatter = Ougai::Formatters::Customizable.new(
|
87
|
+
format_data: proc do |data|
|
88
|
+
data.ai # Awesome-print printing
|
89
|
+
end
|
90
|
+
)
|
91
|
+
```
|
92
|
+
|
93
|
+
**Notes**
|
94
|
+
|
95
|
+
- Data formatter must return `nil` if `data` is empty.
|
96
|
+
- Default data formatter takes the `excluded_fields` option into account. You
|
97
|
+
need to add it to your custom formatter if you want to keep it.
|
98
|
+
|
99
|
+
#### Error formatter: `format_err`
|
100
|
+
|
101
|
+
Error formatter is a `proc` with only `data` as argument and can be assigned at
|
102
|
+
initialization via the `format_err` key:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
formatter = Ougai::Formatters::Customizable.new(
|
106
|
+
format_err: proc do |data|
|
107
|
+
next nil unless data.key?(:err)
|
108
|
+
|
109
|
+
err = data.delete(:err)
|
110
|
+
" #{err[:name]} (#{err[:message]})"
|
111
|
+
end
|
112
|
+
)
|
113
|
+
```
|
114
|
+
|
115
|
+
**Notes**
|
116
|
+
|
117
|
+
- Error formatter must return `nil` if `data` does not contain the `:err` key
|
118
|
+
- Error formatter must remove `:err` key
|
119
|
+
- Default error formatter takes the `trace_indent` option into account. You need
|
120
|
+
to add it to your custom formatter if you want to keep it
|
121
|
+
|
122
|
+
#### Colorization
|
123
|
+
|
124
|
+
Colorization is handled by an instance of `Ougai::Formatters::Colors::Configuration`
|
125
|
+
and is basically a mapping *subject => value* to define the colors. Default subject
|
126
|
+
are:
|
127
|
+
|
128
|
+
- `:severity`: log severity coloring
|
129
|
+
- `:datetime`: datetime coloring
|
130
|
+
- `:msg`: log main message coloring
|
131
|
+
|
132
|
+
You can add your own subject if you need it in your custom formatters.
|
133
|
+
|
134
|
+
Values can have three types:
|
135
|
+
|
136
|
+
- String: this color is applied to the subject regardless the situation
|
137
|
+
- Hash: the color is defined by log severity. Non defined severity colors are
|
138
|
+
fetched from the `default` severity
|
139
|
+
- Symbol: the color is copied from the referenced symbol
|
140
|
+
|
141
|
+
Example:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
color_configuration = Ougai::Formatters::Colors::Configuration.new(
|
145
|
+
severity: {
|
146
|
+
trace: Ougai::Formatters::Colors::WHITE,
|
147
|
+
debug: Ougai::Formatters::Colors::GREEN,
|
148
|
+
info: Ougai::Formatters::Colors::CYAN,
|
149
|
+
warn: Ougai::Formatters::Colors::YELLOW,
|
150
|
+
error: Ougai::Formatters::Colors::RED,
|
151
|
+
fatal: Ougai::Formatters::Colors::PURPLE
|
152
|
+
},
|
153
|
+
msg: :severity,
|
154
|
+
datetime: {
|
155
|
+
default: Ougai::Formatters::Colors::PURPLE,
|
156
|
+
error: Ougai::Formatters::Colors::RED,
|
157
|
+
fatal: Ougai::Formatters::Colors::RED
|
158
|
+
},
|
159
|
+
custom: Ougai::Formatters::Colors::BLUE
|
160
|
+
)
|
161
|
+
```
|
162
|
+
|
163
|
+
- *Severity* has a different color dependending on log severity
|
164
|
+
- Main log *message* color is identical to severity color
|
165
|
+
- *Datetime* has a red color for *error* and *fatal* logs. Otherwise it is
|
166
|
+
colored in purple.
|
167
|
+
- A *custom* subject is always colored in blue regardless log severity
|
168
|
+
|
169
|
+
**Notes**
|
170
|
+
|
171
|
+
- If `:severity` is not defined, it is loaded from a default configuration
|
172
|
+
- If `:severity` is partially defined, missing severities are fetched from
|
173
|
+
default configuration
|
174
|
+
- Circular references are not checked and infinite loops can then be triggered.
|
175
|
+
|
176
|
+
## Integration
|
177
|
+
|
178
|
+
#### Lograge / Lograge-sql
|
179
|
+
|
180
|
+
I initially made this gem to couple Ougai with [lograge](https://github.com/roidrage/lograge)/[lograge-sql](https://github.com/iMacTia/lograge-sql). Lograge logs has to be
|
181
|
+
formatted in a way so that our custom formatters can catch it:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
# config/initializers/lograge.rb
|
185
|
+
config.lograge.formatter = Class.new do |fmt|
|
186
|
+
def fmt.call(data)
|
187
|
+
{ request: data }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
```
|
191
|
+
|
192
|
+
I chose this format because I am also using Loggly and it is pretty convenient
|
193
|
+
to filter by `json.request.*` to fetch Lograge logs.
|
194
|
+
|
195
|
+
If using lograge-sql, make sure that Lograge format it as a Hash so that we can
|
196
|
+
leverage our main message formatter and data formatter:
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
# config/initializers/lograge.rb
|
200
|
+
config.lograge_sql.extract_event = proc do |event|
|
201
|
+
{
|
202
|
+
name: event.payload[:name],
|
203
|
+
duration: event.duration.to_f.round(2),
|
204
|
+
sql: event.payload[:sql]
|
205
|
+
}
|
206
|
+
end
|
207
|
+
config.lograge_sql.formatter = proc do |sql_queries|
|
208
|
+
sql_queries
|
209
|
+
end
|
210
|
+
```
|
211
|
+
|
212
|
+
Wrap everything together example:
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
# Define our colors
|
216
|
+
color_configuration = Ougai::Formatters::Colors::Configuration.new(
|
217
|
+
severity: {
|
218
|
+
trace: Ougai::Formatters::Colors::WHITE,
|
219
|
+
debug: Ougai::Formatters::Colors::GREEN,
|
220
|
+
info: Ougai::Formatters::Colors::CYAN,
|
221
|
+
warn: Ougai::Formatters::Colors::YELLOW,
|
222
|
+
error: Ougai::Formatters::Colors::RED,
|
223
|
+
fatal: Ougai::Formatters::Colors::PURPLE
|
224
|
+
},
|
225
|
+
msg: :severity,
|
226
|
+
datetime: {
|
227
|
+
default: Ougai::Formatters::Colors::PURPLE,
|
228
|
+
error: Ougai::Formatters::Colors::RED,
|
229
|
+
fatal: Ougai::Formatters::Colors::RED
|
230
|
+
}
|
231
|
+
)
|
232
|
+
|
233
|
+
# Lograge specific configuration
|
234
|
+
EXCLUDED_FIELD = [:credit_card] # example only
|
235
|
+
LOGRAGE_REJECT = [:sql_queries, :sql_queries_count]
|
236
|
+
|
237
|
+
# Console formatter configuration
|
238
|
+
console_formatter = Ougai::Formatters::Customizable.new(
|
239
|
+
format_msg: proc do |severity, datetime, _progname, data|
|
240
|
+
# Remove :msg regardless the outcome
|
241
|
+
msg = data.delete(:msg)
|
242
|
+
# Lograge specfic stuff: do not print sql queries in main log message
|
243
|
+
if data.key?(:request)
|
244
|
+
lograge = data[:request].reject { |k, _v| LOGRAGE_REJECT.include?(k) }
|
245
|
+
.map { |key, val| "#{key}: #{val}" }
|
246
|
+
.join(', ')
|
247
|
+
msg = color_config.color(:msg, lograge, severity)
|
248
|
+
# Standard text
|
249
|
+
else
|
250
|
+
msg = color_config.color(:msg, msg, severity)
|
251
|
+
end
|
252
|
+
|
253
|
+
# Standardize output
|
254
|
+
format('%s %s: %s',
|
255
|
+
color_config.color(:severity, severity, severity),
|
256
|
+
color_config.color(:datetime, datetime, severity),
|
257
|
+
msg)
|
258
|
+
end,
|
259
|
+
format_data: proc do |data|
|
260
|
+
# Lograge specfic stuff: main controller output handled by msg formatter
|
261
|
+
if data.key?(:request)
|
262
|
+
lograge_data = data[:request]
|
263
|
+
# concatenate SQL queries
|
264
|
+
if lograge_data.key?(:sql_queries)
|
265
|
+
lograge_data[:sql_queries].map do |sql_query|
|
266
|
+
format('%<duration>6.2fms %<name>25s %<sql>s', sql_query)
|
267
|
+
end
|
268
|
+
.join("\n")
|
269
|
+
# no queries: nothing to print
|
270
|
+
else
|
271
|
+
nil
|
272
|
+
end
|
273
|
+
# Default styling
|
274
|
+
else
|
275
|
+
# report excluded field parameter here: no need to add it to options
|
276
|
+
EXCLUDED_FIELD.each { |field| data.delete(field) }
|
277
|
+
next nil if data.empty?
|
278
|
+
|
279
|
+
# report plain parameter here: no need to add it to options
|
280
|
+
data.ai(plain: false)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
)
|
284
|
+
console_formatter.datetime_format = '%H:%M:%S.%L' # local development: need only time
|
285
|
+
|
286
|
+
# Define console logger
|
287
|
+
console_logger = Log::Ougai::Logger.new(STDOUT)
|
288
|
+
console_logger.formatter = console_formatter
|
289
|
+
|
290
|
+
# Not this gem related: define file logger
|
291
|
+
file_logger = Log::Ougai::Logger.new(Rails.root.join('log/ougai.log'))
|
292
|
+
file_logger.formatter = Ougai::Formatters::Bunyan.new
|
293
|
+
|
294
|
+
# Extend console logger to file logger
|
295
|
+
console_logger.extend(Ougai::Logger.broadcast(file_logger))
|
296
|
+
|
297
|
+
# Assign Ougai logger
|
298
|
+
config.logger = console_logger
|
299
|
+
```
|
300
|
+
|
301
|
+
Output looks like
|
302
|
+

|
303
|
+
|
304
|
+
|
305
|
+
## Contributing
|
306
|
+
|
307
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Al-un/ougai-formatters-customizable.
|
308
|
+
|
309
|
+
## License
|
310
|
+
|
311
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -16,30 +16,51 @@ module Ougai
|
|
16
16
|
|
17
17
|
# Reset formatting. To be appended after every formatted text
|
18
18
|
RESET = "\e[0m"
|
19
|
-
#
|
19
|
+
# Font black color
|
20
20
|
BLACK = "\e[30m"
|
21
|
+
# Font red color
|
21
22
|
RED = "\e[31m"
|
23
|
+
# Font green color
|
22
24
|
GREEN = "\e[32m"
|
25
|
+
# Font yello color
|
23
26
|
YELLOW = "\e[33m"
|
27
|
+
# Font blue color
|
24
28
|
BLUE = "\e[34m"
|
29
|
+
# Font purple color
|
25
30
|
PURPLE = "\e[35m"
|
31
|
+
# Font cyan color
|
26
32
|
CYAN = "\e[36m"
|
33
|
+
# Font white color
|
27
34
|
WHITE = "\e[37m"
|
35
|
+
# Font bright/bold red color
|
28
36
|
BOLD_RED = "\e[1;31m"
|
37
|
+
# Font bright/bold green color
|
29
38
|
BOLD_GREEN = "\e[1;32m"
|
39
|
+
# Font bright/bold yellow color
|
30
40
|
BOLD_YELLOW = "\e[1;33m"
|
41
|
+
# Font bright/bold blue color
|
31
42
|
BOLD_BLUE = "\e[1;34m"
|
32
|
-
|
43
|
+
# Font bright/bold purple color
|
44
|
+
BOLD_PURPLE = "\e[1;35m"
|
45
|
+
# Font bright/bold cyan color
|
33
46
|
BOLD_CYAN = "\e[1;36m"
|
47
|
+
# Font bright/bold white color
|
34
48
|
BOLD_WHITE = "\e[1;37m"
|
35
|
-
# Background
|
49
|
+
# Background black color
|
36
50
|
BG_BLACK = "\e[40m"
|
51
|
+
# Background red color
|
37
52
|
BG_RED = "\e[41m"
|
53
|
+
# Background green color
|
38
54
|
BG_GREEN = "\e[42m"
|
55
|
+
# Background yellow color
|
39
56
|
BG_YELLOW = "\e[43m"
|
57
|
+
# Background blue color
|
40
58
|
BG_BLUE = "\e[44m"
|
41
|
-
|
59
|
+
# Background purple color
|
60
|
+
BG_PURPLE = "\e[45m"
|
61
|
+
# Background cyan color
|
42
62
|
BG_CYAN = "\e[46m"
|
63
|
+
# Background white color
|
43
64
|
BG_WHITE = "\e[47m"
|
44
65
|
|
45
66
|
class << self
|
@@ -53,8 +74,9 @@ module Ougai
|
|
53
74
|
# above or have a complete custom String value depending on the
|
54
75
|
# terminal. If +nil+, text is not modified.
|
55
76
|
# @param [String] text text to be colored
|
56
|
-
# @param [String] reset reset font styling escape sequence
|
57
|
-
#
|
77
|
+
# @param [String] reset reset font styling escape sequence
|
78
|
+
#
|
79
|
+
# @return [String] colored or uncolored text
|
58
80
|
def color_text(color, text, reset = Ougai::Formatters::Colors::RESET)
|
59
81
|
return text if color.nil?
|
60
82
|
|
@@ -9,10 +9,11 @@ module Ougai
|
|
9
9
|
# The configuration,split by subject such as +level+, +msg+,
|
10
10
|
# or +datetime+ is basically a Hash: +config+ with the subject as key
|
11
11
|
# and values. Values can be have three types:
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
12
|
+
#
|
13
|
+
# - +String+: the color escape sequence for the subject
|
14
|
+
# - +Hash+: the color escape sequence per severity. If not all severities
|
15
|
+
# are defined, a +:default+ value must be defined
|
16
|
+
# - +Symbol+: refers to another key and same coloring is applied
|
16
17
|
class Configuration
|
17
18
|
class << self
|
18
19
|
# list default color configuration
|
@@ -20,6 +21,7 @@ module Ougai
|
|
20
21
|
# +Ougai::Logging::Severity#to_label+
|
21
22
|
# @note values are copied from +Ougai::Formatters::Readable+ coloring
|
22
23
|
# values
|
24
|
+
# @return [Hash] default color configuration is severities only
|
23
25
|
def default_configuration
|
24
26
|
{
|
25
27
|
severity: {
|
@@ -35,10 +37,14 @@ module Ougai
|
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
40
|
+
# Configuration accept following keys:
|
41
|
+
# - +:load_default_config+ If true, then default configuration
|
42
|
+
# values is fetched to fill missing value from the provided
|
43
|
+
# configuration. Default is true.
|
44
|
+
# - any remaining key is considered to be color-related and is translated
|
45
|
+
# into a *subject => color rule* mapping
|
46
|
+
#
|
47
|
+
# @param [Hash] configuration color configuration. Cannot be nil
|
42
48
|
def initialize(configuration = {})
|
43
49
|
# check if loading or not from default configuration
|
44
50
|
if configuration.fetch(:load_default_config) { true }
|
@@ -62,10 +68,13 @@ module Ougai
|
|
62
68
|
end
|
63
69
|
end
|
64
70
|
|
71
|
+
# Convenience method to color a subject for a given log severity
|
72
|
+
#
|
65
73
|
# @param [Symbol] subject_key to fetch the color to color the text
|
66
74
|
# @param [String] text to be colored text
|
67
75
|
# @param [Symbol] severity log level
|
68
|
-
#
|
76
|
+
#
|
77
|
+
# @return [String] a colored text depending on the subject
|
69
78
|
def color(subject_key, text, severity)
|
70
79
|
color = get_color_for(subject_key, severity)
|
71
80
|
Ougai::Formatters::Colors.color_text(color, text)
|
@@ -78,12 +87,14 @@ module Ougai
|
|
78
87
|
# +get_color_for+ handles color inheritance: if a subject inherit color
|
79
88
|
# from another subject, subject value is the symbol refering to the
|
80
89
|
# other subject.
|
81
|
-
#
|
90
|
+
#
|
91
|
+
# @note !!WARNING!!: Circular references are not checked and lead to infinite
|
82
92
|
# loop
|
83
93
|
#
|
84
|
-
# @param [Symbol] subject_key
|
85
|
-
# @param [Symbol] severity
|
86
|
-
#
|
94
|
+
# @param [Symbol] subject_key to define the color to color the text
|
95
|
+
# @param [Symbol] severity log level
|
96
|
+
#
|
97
|
+
# @return [String,nil] requested color String value or +nil+ if not colored
|
87
98
|
def get_color_for(subject_key, severity)
|
88
99
|
# no colorization
|
89
100
|
return nil unless @config.key?(subject_key)
|
@@ -1,145 +1,160 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'ougai/formatters/base'
|
4
|
-
require 'ougai/formatters/colors/configuration'
|
5
|
-
|
6
|
-
module Ougai
|
7
|
-
module Formatters
|
8
|
-
# Ougai log printing can be split in three components:
|
9
|
-
# 1. Main log message: usually with timestamp, log severity and a single
|
10
|
-
# line message
|
11
|
-
# 2. Log data: the structured logging component. Can be represented by
|
12
|
-
# a Hash
|
13
|
-
# 3. Errors: errors require specific log formatting
|
14
|
-
#
|
15
|
-
# Customizable offers a flexible way to handle each component
|
16
|
-
# independently
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# +
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
#
|
79
|
-
#
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
@
|
102
|
-
Customizable.
|
103
|
-
}
|
104
|
-
|
105
|
-
#
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
#
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ougai/formatters/base'
|
4
|
+
require 'ougai/formatters/colors/configuration'
|
5
|
+
|
6
|
+
module Ougai
|
7
|
+
module Formatters
|
8
|
+
# Ougai log printing can be split in three components:
|
9
|
+
# 1. Main log message: usually with timestamp, log severity and a single
|
10
|
+
# line message
|
11
|
+
# 2. Log data: the structured logging component. Can be represented by
|
12
|
+
# a Hash
|
13
|
+
# 3. Errors: errors require specific log formatting
|
14
|
+
#
|
15
|
+
# Customizable offers a flexible way to handle each component
|
16
|
+
# independently by assigning a proc to the following keys:
|
17
|
+
#
|
18
|
+
# 1. +:format_msg+ Format message. Proc arguments are +|level, datetime, progname, data|+. This block must remove the key +:msg+ from +data+
|
19
|
+
# 2. +:format_data+ Format data. Proc argument is +|data|+.
|
20
|
+
# 3. +:format_err+ Format err. Proc argument is +|data|+. The proc must remove the key +:err+
|
21
|
+
class Customizable < Ougai::Formatters::Base
|
22
|
+
class << self
|
23
|
+
# Define the default main log message formatting to use. A non-null
|
24
|
+
# color configuration has to be provided. The configuration can however
|
25
|
+
# be empty
|
26
|
+
#
|
27
|
+
# @param [Ougai::Formatters::Colors::Configuration] color_config the
|
28
|
+
# color configuration to use
|
29
|
+
#
|
30
|
+
# @return [Proc] main message formatter
|
31
|
+
def default_msg_format(color_config)
|
32
|
+
proc do |severity, datetime, _progname, data|
|
33
|
+
msg = data.delete(:msg)
|
34
|
+
severity = color_config.color(:severity, severity, severity)
|
35
|
+
datetime = color_config.color(:datetime, datetime, severity)
|
36
|
+
msg = color_config.color(:msg, msg, severity)
|
37
|
+
|
38
|
+
"[#{datetime}] #{severity}: #{msg}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Define the default error formatting to use which handles field
|
43
|
+
# exclusion and plain mode for awesome-print
|
44
|
+
#
|
45
|
+
# @param [Array<Symbol>] excluded_fields list of key to exclude from
|
46
|
+
# +data+ before printing logs
|
47
|
+
# @param [Boolean] plain parameter to define if Awesome-Print renders
|
48
|
+
# in plain mode or not
|
49
|
+
#
|
50
|
+
# @return [Proc] data formatter
|
51
|
+
def default_data_format(excluded_fields, plain)
|
52
|
+
proc do |data|
|
53
|
+
excluded_fields.each { |field| data.delete(field) }
|
54
|
+
next nil if data.empty?
|
55
|
+
|
56
|
+
data.ai(plain: plain)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Define the default error formatting to use.
|
61
|
+
#
|
62
|
+
# @param [Integer] trace_indent space indentation to prepend before
|
63
|
+
# trace content
|
64
|
+
#
|
65
|
+
# @return [Proc] error formatter
|
66
|
+
def default_err_format(trace_indent = 4)
|
67
|
+
proc do |data|
|
68
|
+
next nil unless data.key?(:err)
|
69
|
+
|
70
|
+
err = data.delete(:err)
|
71
|
+
err_str = " #{err[:name]} (#{err[:message]}):"
|
72
|
+
err_str += "\n" + (' ' * trace_indent) + err[:stack] if err.key?(:stack)
|
73
|
+
err_str
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Intialize a formatter
|
79
|
+
#
|
80
|
+
# @param [String] app_name application name (execution program name if nil)
|
81
|
+
# @param [String] hostname hostname (hostname if nil)
|
82
|
+
# @param [Hash] opts the initial values of attributes
|
83
|
+
# @option opts [String] :trace_max_lines (100) the value of
|
84
|
+
# trace_max_lines attribute
|
85
|
+
# @option opts [String] :plain (false) the value of plain attribute
|
86
|
+
# @option opts [String] :excluded_fields ([]) the value of
|
87
|
+
# excluded_fields attribute
|
88
|
+
# @option opts [Ougai::Formatters::Colors::Configuration] :color_config
|
89
|
+
# assign a color configuration.
|
90
|
+
# @option opts [Proc] :format_msg main message formatter
|
91
|
+
# @option opts [Proc] :format_data data formatter
|
92
|
+
# @option opts [Proc] :format_err error formatter
|
93
|
+
def initialize(app_name = nil, hostname = nil, opts = {})
|
94
|
+
aname, hname, opts = Base.parse_new_params([app_name, hostname, opts])
|
95
|
+
super(aname, hname, opts)
|
96
|
+
|
97
|
+
# Message logging
|
98
|
+
color_config = opts.fetch(:color_config) {
|
99
|
+
color_config = Ougai::Formatters::Colors::Configuration.new({})
|
100
|
+
}
|
101
|
+
@format_msg = opts.fetch(:format_msg) {
|
102
|
+
Customizable.default_msg_format(color_config)
|
103
|
+
}
|
104
|
+
|
105
|
+
# Data logging
|
106
|
+
plain = opts.fetch(:plain) { false }
|
107
|
+
excluded_fields = opts[:excluded_fields] || []
|
108
|
+
@format_data = opts.fetch(:format_data) {
|
109
|
+
Customizable.default_data_format(excluded_fields, plain)
|
110
|
+
}
|
111
|
+
|
112
|
+
# Error logging
|
113
|
+
trace_indent = opts.fetch(:trace_indent) { 4 }
|
114
|
+
@format_err = opts.fetch(:format_err) {
|
115
|
+
Customizable.default_err_format(trace_indent)
|
116
|
+
}
|
117
|
+
|
118
|
+
# Ensure dependency are present
|
119
|
+
load_dependent
|
120
|
+
end
|
121
|
+
|
122
|
+
# Format a log entry
|
123
|
+
#
|
124
|
+
# @param [String] severity log severity, in capital letters
|
125
|
+
# @param [Time] time timestamp of the log. Is formatted by +strftime+
|
126
|
+
# @param [String] progname optional program name
|
127
|
+
# @param [Hash] data log data. Main message is stored under the key +:msg+
|
128
|
+
# while errors are logged under the key +:err+.
|
129
|
+
#
|
130
|
+
# @return [String] log text, ready to be printed out
|
131
|
+
def _call(severity, time, progname, data)
|
132
|
+
strs = ''.dup
|
133
|
+
# Main message
|
134
|
+
dt = format_datetime(time)
|
135
|
+
msg_str = @format_msg.call(severity, dt, progname, data)
|
136
|
+
strs.concat(msg_str)
|
137
|
+
|
138
|
+
# Error: displayed before additional data
|
139
|
+
err_str = @format_err.call(data)
|
140
|
+
strs.concat("\n").concat(err_str) unless err_str.nil?
|
141
|
+
|
142
|
+
# Additional data
|
143
|
+
data_str = @format_data.call(data)
|
144
|
+
strs.concat("\n").concat(data_str) unless data_str.nil?
|
145
|
+
|
146
|
+
strs.concat("\n")
|
147
|
+
end
|
148
|
+
|
149
|
+
protected
|
150
|
+
|
151
|
+
# Ensure +awesompe_print+ is loaded
|
152
|
+
def load_dependent
|
153
|
+
require 'awesome_print'
|
154
|
+
rescue LoadError
|
155
|
+
puts 'You must install the awesome_print gem to use this output.'
|
156
|
+
raise
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Ougai
|
4
|
-
module Formatters
|
5
|
-
|
6
|
-
|
7
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ougai
|
4
|
+
module Formatters
|
5
|
+
# Customizable extension version
|
6
|
+
CUSTOMIZABLE_VERSION = '1.0.0'
|
7
|
+
end
|
8
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ougai-formatters-customizable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Al-un
|
@@ -92,6 +92,34 @@ dependencies:
|
|
92
92
|
- - "~>"
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '3.0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: simplecov
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: simplecov-console
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
type: :development
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
95
123
|
description: |2
|
96
124
|
This library aims at providing a fully flexible formatter compatible with the
|
97
125
|
Ougai library. Customization is about colorization and log formatting.
|