tty-logger 0.0.0 → 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 +4 -4
- data/CHANGELOG.md +51 -1
- data/README.md +769 -4
- data/lib/tty/logger.rb +332 -0
- data/lib/tty/logger/config.rb +128 -0
- data/lib/tty/logger/data_filter.rb +118 -0
- data/lib/tty/logger/event.rb +40 -0
- data/lib/tty/logger/formatters/json.rb +63 -0
- data/lib/tty/logger/formatters/text.rb +130 -0
- data/lib/tty/logger/handlers/base.rb +73 -0
- data/lib/tty/logger/handlers/console.rb +178 -0
- data/lib/tty/logger/handlers/null.rb +16 -0
- data/lib/tty/logger/handlers/stream.rb +63 -0
- data/lib/tty/logger/levels.rb +68 -0
- data/lib/tty/logger/version.rb +3 -3
- metadata +28 -22
- data/Rakefile +0 -8
- data/spec/spec_helper.rb +0 -14
- data/spec/unit/log_spec.rb +0 -7
- data/tasks/console.rake +0 -11
- data/tasks/coverage.rake +0 -11
- data/tasks/spec.rake +0 -29
- data/tty-logger.gemspec +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0594c7ef471a07571e5621e8535469fcb50edeeb10d7ffa58b194ef8fe4f8350'
|
4
|
+
data.tar.gz: 42a3b6c20b756754723c42c5b0ce85490b403978ffe566cb267dc6f18811f1c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fb46bcc0515d4f4762dc9c601b65131a493153ed85e48e83ac64ae70b0b2060d0780d867560bfc8e50ed4c461ea62e1aeba5b4e1b6b55572656196e9958840b
|
7
|
+
data.tar.gz: 235421d689aa362a858a813fd369cef67673b0c6b13ccf50f6733a603746c3dfc00bde16fdd73fb1dd4358e9457c70d61c033c60d409e3f721eb0b34cc5c40bd
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,57 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
-
## [v0.
|
3
|
+
## [v0.5.0] - 2020-09-27
|
4
|
+
|
5
|
+
### Added
|
6
|
+
* Add :message_format option to customize how messages are displayed in the console
|
7
|
+
by Josh Greenwood (@JoshTGreenwood)
|
8
|
+
|
9
|
+
### Fixed
|
10
|
+
* Fix to select event name from valid log types or current level
|
11
|
+
by Ryan Schlesinger (@ryansch)
|
12
|
+
* Fix duplicate filters attribute definition in TTY::Logger::Config
|
13
|
+
|
14
|
+
## [v0.4.0] - 2020-07-29
|
15
|
+
|
16
|
+
### Added
|
17
|
+
* Allow editing logger configuration at runtime ([#10](https://github.com/piotrmurach/tty-logger/pull/10))
|
18
|
+
* Support for the `<<` streaming operator ([#9](https://github.com/piotrmurach/tty-logger/pull/9)))
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
* Change gemspec to update pastel version and restrict only to minor version
|
22
|
+
|
23
|
+
### Fixed
|
24
|
+
* Fix to filter sensitive information from exceptions
|
25
|
+
|
26
|
+
## [v0.3.0] - 2020-01-01
|
27
|
+
|
28
|
+
### Added
|
29
|
+
* Add ability to filter sensitive information out of structured data
|
30
|
+
|
31
|
+
### Changed
|
32
|
+
* Remove the test and task files from the gemspec
|
33
|
+
|
34
|
+
### Fixed
|
35
|
+
* Fix console handler highlighting of nested hash keys
|
36
|
+
|
37
|
+
## [v0.2.0] - 2019-09-30
|
38
|
+
|
39
|
+
### Added
|
40
|
+
* Add ability to add structured data inside logging block
|
41
|
+
* Add ability to filter sensitive data
|
42
|
+
* Add ability to define custom log types
|
43
|
+
* Add ability to temporarily log at different level
|
44
|
+
* Add performance tests
|
45
|
+
|
46
|
+
### Changed
|
47
|
+
* Change to dynamically define log types
|
48
|
+
|
49
|
+
## [v0.1.0] - 2019-07-21
|
4
50
|
|
5
51
|
* Initial implementation and release
|
6
52
|
|
53
|
+
[v0.5.0]: https://github.com/piotrmurach/tty-logger/compare/v0.4.0..v0.5.0
|
54
|
+
[v0.4.0]: https://github.com/piotrmurach/tty-logger/compare/v0.3.0..v0.4.0
|
55
|
+
[v0.3.0]: https://github.com/piotrmurach/tty-logger/compare/v0.2.0..v0.3.0
|
56
|
+
[v0.2.0]: https://github.com/piotrmurach/tty-logger/compare/v0.1.0..v0.2.0
|
7
57
|
[v0.1.0]: https://github.com/piotrmurach/tty-logger/compare/v0.1.0
|
data/README.md
CHANGED
@@ -1,17 +1,48 @@
|
|
1
1
|
<div align="center">
|
2
|
-
<a href="https://
|
2
|
+
<a href="https://ttytoolkit.org" target="_blank"><img width="130" src="https://github.com/piotrmurach/tty/raw/master/images/tty.png" alt="tty logo" /></a>
|
3
3
|
</div>
|
4
4
|
|
5
|
-
# TTY::Logger
|
5
|
+
# TTY::Logger [][gitter]
|
6
|
+
|
7
|
+
[][gem]
|
8
|
+
[][travis]
|
9
|
+
[][appveyor]
|
10
|
+
[][codeclimate]
|
11
|
+
[][coverage]
|
12
|
+
[][inchpages]
|
13
|
+
|
14
|
+
[gitter]: https://gitter.im/piotrmurach/tty
|
15
|
+
[gem]: http://badge.fury.io/rb/tty-logger
|
16
|
+
[travis]: http://travis-ci.org/piotrmurach/tty-logger
|
17
|
+
[appveyor]: https://ci.appveyor.com/project/piotrmurach/tty-logger
|
18
|
+
[codeclimate]: https://codeclimate.com/github/piotrmurach/tty-logger
|
19
|
+
[coverage]: https://coveralls.io/github/piotrmurach/tty-logger
|
20
|
+
[inchpages]: http://inch-ci.org/github/piotrmurach/tty-logger
|
6
21
|
|
7
22
|
> A readable, structured and beautiful logging for the terminal
|
8
23
|
|
24
|
+
**TTY::Logger** provides independent logging component for [TTY toolkit](https://github.com/piotrmurach/tty).
|
25
|
+
|
26
|
+

|
27
|
+
|
28
|
+
## Features
|
29
|
+
|
30
|
+
* Intuitive console output for an increased readability
|
31
|
+
* Ability to stream data to any IO object
|
32
|
+
* Supports structured data logging
|
33
|
+
* Filters sensitive data
|
34
|
+
* Allows to define custom log types
|
35
|
+
* Formats and truncates messages to avoid clogging logging output
|
36
|
+
* Customizable styling of labels and symbols for console output
|
37
|
+
* Includes metadata information: time, location, scope
|
38
|
+
* Handles multiple logging outputs
|
39
|
+
|
9
40
|
## Installation
|
10
41
|
|
11
42
|
Add this line to your application's Gemfile:
|
12
43
|
|
13
44
|
```ruby
|
14
|
-
gem
|
45
|
+
gem "tty-logger"
|
15
46
|
```
|
16
47
|
|
17
48
|
And then execute:
|
@@ -22,12 +53,746 @@ Or install it yourself as:
|
|
22
53
|
|
23
54
|
$ gem install tty-logger
|
24
55
|
|
25
|
-
|
56
|
+
|
57
|
+
## Contents
|
58
|
+
|
59
|
+
* [1. Usage](#1-usage)
|
60
|
+
* [2. Synopsis](#2-synopsis)
|
61
|
+
* [2.1 Logging](#21-logging)
|
62
|
+
* [2.1.1 Exceptions](#211-exceptions)
|
63
|
+
* [2.1.2 Types](#212-types)
|
64
|
+
* [2.2 Levels](#22-levels)
|
65
|
+
* [2.2.1 Scoped Level](#22-scoped-level)
|
66
|
+
* [2.3 Structured Data](#23-structured-data)
|
67
|
+
* [2.4 Configuration](#24-configuration)
|
68
|
+
* [2.4.1 Metadata](#241-metadata)
|
69
|
+
* [2.4.2 Filters](#242-filters)
|
70
|
+
* [2.5 Cloning](#25-cloning)
|
71
|
+
* [2.6 Handlers](#26-handlers)
|
72
|
+
* [2.6.1 Console Handler](#261-console-handler)
|
73
|
+
* [2.6.2 Stream Handler](#262-stream-handler)
|
74
|
+
* [2.6.3 Custom Handler](#263-custom-handler)
|
75
|
+
* [2.6.4 Multiple Handlers](#264-multiple-handlers)
|
76
|
+
* [2.7 Formatters](#27-formatters)
|
77
|
+
* [2.8 Output streams](#28-output-streams)
|
78
|
+
* [3. Community Extensions](#3-community-extensions)
|
79
|
+
* [3.1 Sentry Handler](#31-sentry-handler)
|
80
|
+
|
81
|
+
## 1. Usage
|
82
|
+
|
83
|
+
Create logger:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
logger = TTY::Logger.new
|
87
|
+
```
|
88
|
+
|
89
|
+
And log information using any of the logger [built-in types](#212-types):
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
logger.info "Deployed successfully"
|
93
|
+
logger.info "Deployed", "successfully"
|
94
|
+
logger.info { "Dynamically generated info" }
|
95
|
+
```
|
96
|
+
|
97
|
+
Include structured data:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
logger.success "Deployed successfully", myapp: "myapp", env: "prod"
|
101
|
+
# =>
|
102
|
+
# ✔ success Deployed successfully app=myapp env=prod
|
103
|
+
```
|
104
|
+
|
105
|
+
Add [metadata](#241-metadata) information:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
logger = TTY::Logger.new do |config|
|
109
|
+
config.metadata = [:date, :time]
|
110
|
+
end
|
111
|
+
logger.info "Deployed successfully", myapp: "myapp", env: "prod"
|
112
|
+
# =>
|
113
|
+
# [2019-07-17] [23:21:55.287] › ℹ info Info about the deploy app=myapp env=prod
|
114
|
+
```
|
115
|
+
|
116
|
+
Or change structured data [formatting](#27-formatters) display to `JSON`:
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
logger = TTY::Logger.new do |config|
|
120
|
+
config.formatter = :json
|
121
|
+
end
|
122
|
+
logger.info "Deployed successfully"
|
123
|
+
# =>
|
124
|
+
# [2019-07-17] [23:21:55.287] › ℹ info Info about the deploy {"app":"myapp","env":"prod"}
|
125
|
+
```
|
126
|
+
|
127
|
+
## 2. Synopsis
|
128
|
+
|
129
|
+
## 2.1 Logging
|
130
|
+
|
131
|
+
There are many logger types to choose from:
|
132
|
+
|
133
|
+
* `debug` - logs message at `:debug` level
|
134
|
+
* `info` - logs message at `:info` level
|
135
|
+
* `success` - logs message at `:info` level
|
136
|
+
* `wait` - logs message at `:info` level
|
137
|
+
* `warn` - logs message at `:warn` level
|
138
|
+
* `error` - logs message at `:error` level
|
139
|
+
* `fatal` - logs message at `:fatal` level
|
140
|
+
|
141
|
+
To log a message, simply choose one of the above types and pass in the actual message. For example, to log successfully deployment at info level do:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
logger.success "Deployed successfully"
|
145
|
+
# =>
|
146
|
+
# ✔ success Deployed successfully
|
147
|
+
```
|
148
|
+
|
149
|
+
Or pass in multiple messages:
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
logger.success "Deployed", "successfully"
|
153
|
+
# =>
|
154
|
+
# ✔ success Deployed successfully
|
155
|
+
```
|
156
|
+
|
157
|
+
You can delay message evaluation by passing it inside a block:
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
logger.success { "Dynamically generated info" }
|
161
|
+
# =>
|
162
|
+
# ✔ success Dynamically generated info
|
163
|
+
```
|
164
|
+
|
165
|
+
Similar to regular logging, you cal split your message into chunks inside a block:
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
logger.success { ["Dynamically", "generated", "info"] }
|
169
|
+
# =>
|
170
|
+
# ✔ success Dynamically generated info
|
171
|
+
```
|
172
|
+
|
173
|
+
The above comes handy when paired with [structured data](#23-structured-data).
|
174
|
+
|
175
|
+
#### 2.1.1 Exceptions
|
176
|
+
|
177
|
+
You can also report on exceptions.
|
178
|
+
|
179
|
+
For example, let's say you caught an exception about incorrect data format and use `fatal` level to log it:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
begin
|
183
|
+
raise ArgumentError, "Wrong data"
|
184
|
+
rescue => ex
|
185
|
+
logger.fatal("Error:", ex)
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
This will result in a message followed by a full backtrace:
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
# =>
|
193
|
+
# ! fatal Error: Wrong data
|
194
|
+
# tty-logger/spec/unit/exception_spec.rb:12:in `block (2 levels) in <top (required)>'
|
195
|
+
# rspec-core-3.8.2/lib/rspec/core/example.rb:257:in `instance_exec'
|
196
|
+
# rspec-core-3.8.2/lib/rspec/core/example.rb:257:in `block in run'
|
197
|
+
```
|
198
|
+
|
199
|
+
#### 2.1.2 Types
|
200
|
+
|
201
|
+
You can define custom log types via the `types` configuration option:
|
202
|
+
|
203
|
+
For example, if you want to add `thanks` and `done` log types, you need to provide their names along with logging levels. You can further customise the `:console` output with your desired styling:
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
logger = TTY::Logger.new do |config|
|
207
|
+
config.types = {
|
208
|
+
thanks: {level: :info},
|
209
|
+
done: {level: :info}
|
210
|
+
}
|
211
|
+
config.handlers = [
|
212
|
+
[:console, {
|
213
|
+
styles: {
|
214
|
+
thanks: {
|
215
|
+
symbol: "❤️ ",
|
216
|
+
label: "thanks",
|
217
|
+
color: :magenta,
|
218
|
+
levelpad: 0
|
219
|
+
},
|
220
|
+
done: {
|
221
|
+
symbol: "!!",
|
222
|
+
label: "done",
|
223
|
+
color: :green,
|
224
|
+
levelpad: 2
|
225
|
+
}
|
226
|
+
}
|
227
|
+
}]
|
228
|
+
]
|
229
|
+
end
|
230
|
+
```
|
231
|
+
|
232
|
+
Once defined, you can call new log types:
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
logger.thanks("Great work!")
|
236
|
+
logger.done("Work done!")
|
237
|
+
# =>
|
238
|
+
# ❤️ thanks Great work!
|
239
|
+
# !! done Work done!
|
240
|
+
```
|
241
|
+
|
242
|
+

|
243
|
+
|
244
|
+
### 2.2 Levels
|
245
|
+
|
246
|
+
The supported levels, ordered by precedence, are:
|
247
|
+
|
248
|
+
* `:debug` - for debug-related messages
|
249
|
+
* `:info` - for information of any kind
|
250
|
+
* `:warn` - for warnings
|
251
|
+
* `:error` - for errors
|
252
|
+
* `:fatal` - for fatal conditions
|
253
|
+
|
254
|
+
So the order is: `:debug` < `:info` < `:warn` < `:error` < `:fatal`
|
255
|
+
|
256
|
+
For example, `:info` takes precedence over `:debug`. If your log level is set to `:info`, `:info`, `:warn`, `:error` and `:fatal` will be printed to the console. If your log level is set to `:warn`, only `:warn`, `:error` and `:fatal` will be printed.
|
257
|
+
|
258
|
+
You can set level using the `level` configuration option. The value can be a symbol, a string or level constant. For example, `:info`, `INFO` or `TTY::Logger::INFO_LEVEL` will qualify as valid level value.
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
TTY::Logger.new do |config|
|
262
|
+
config.level = :info # or "INFO" or TTY::Logger::INFO_LEVEL
|
263
|
+
end
|
264
|
+
```
|
265
|
+
|
266
|
+
Or you can specific level for each log events handler.
|
267
|
+
|
268
|
+
For example, to log messages above `:info` level to a stream and only `:error` level events to the console do:
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
logger = TTY::Logger.new do |config|
|
272
|
+
config.handlers = [
|
273
|
+
[:console, level: :error],
|
274
|
+
[:stream, level: :info]
|
275
|
+
]
|
276
|
+
end
|
277
|
+
```
|
278
|
+
|
279
|
+
You can also change the [output streams](#28-output-streams) for each handler.
|
280
|
+
|
281
|
+
#### 2.2.1 Scoped Level
|
282
|
+
|
283
|
+
You can temporarily change level, raise it or lower it by using the `log_at` call. By default messages are logged at `:info` level, but you can change this for the duration of a block:
|
26
284
|
|
27
285
|
```ruby
|
28
286
|
logger = TTY::Logger.new
|
287
|
+
|
288
|
+
logger.info("not logged")
|
289
|
+
|
290
|
+
logger.log_at :debug do
|
291
|
+
logger.debug("logged")
|
292
|
+
end
|
293
|
+
# =>
|
294
|
+
# • debug logged
|
295
|
+
```
|
296
|
+
|
297
|
+
Or elevate a level to an error with a constant `ERROR_LEVEL`:
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
logger.log_at TTY::Logger::ERROR_LEVEL do
|
301
|
+
logger.debug("not logged")
|
302
|
+
logger.error("logged")
|
303
|
+
end
|
304
|
+
# =>
|
305
|
+
# ⨯ error logged
|
306
|
+
```
|
307
|
+
|
308
|
+
### 2.3 Structured data
|
309
|
+
|
310
|
+
To add global data available for all logger calls:
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
logger = TTY::Logger.new(fields: {app: "myapp", env: "prod"})
|
314
|
+
|
315
|
+
logger.info("Deploying...")
|
316
|
+
# =>
|
317
|
+
# ℹ info Deploying... app=myapp env=prod
|
318
|
+
```
|
319
|
+
|
320
|
+
To only add data for a single log event:
|
321
|
+
|
322
|
+
```ruby
|
323
|
+
logger = TTY::Logger.new
|
324
|
+
logger.wait "Ready to deploy", app: "myapp", env: "prod"
|
325
|
+
# =>
|
326
|
+
# … waiting Ready to deploy app=myapp env=prod
|
327
|
+
```
|
328
|
+
|
329
|
+
You can delay data evaluation until it's evaluated by passing it inside a block:
|
330
|
+
|
331
|
+
```ruby
|
332
|
+
logger.wait { ["Ready to deploy", {app: "myapp", env: "prod"}] }
|
333
|
+
# =>
|
334
|
+
# … waiting Ready to deploy app=myapp env=prod
|
335
|
+
```
|
336
|
+
|
337
|
+
### 2.4 Configuration
|
338
|
+
|
339
|
+
All the configuration options can be changed globally via `configure` or per logger instance.
|
340
|
+
|
341
|
+
* `:filters` - the storage of placeholders to filter sensitive data out from the logs. Defaults to `{}`.
|
342
|
+
* `:formatter` - the formatter used to display structured data. Defaults to `:text`. See [Formatters](#27-formatters) for more details.
|
343
|
+
* `:handlers` - the handlers used to log messages. Defaults to `[:console]`. See [Handlers](#26-handlers) for more details.
|
344
|
+
* `:level` - the logging level. Any message logged below this level will be simply ignored. Each handler may have it's own default level. Defaults to `:info`
|
345
|
+
* `:max_bytes` - the maximum message size to be logged in bytes. Defaults to `8192` bytes. The truncated message will have `...` at the end.
|
346
|
+
* `:max_depth` - the maximum depth for nested structured data. Defaults to `3`.
|
347
|
+
* `:metadata` - the meta info to display before the message, can be `:pid`, `:date`, `:time` or `:file`. Defaults to empty array `[]`, no metadata. Setting this to `:all` will print all the metadata.
|
348
|
+
* `:types` - the new custom log types. Defaults to `{}`.
|
349
|
+
* `:date_format` - uses `strftime` format to display dates. Defaults to `"%F"`.
|
350
|
+
* `:time_format` - uses `strftime` format to display times. Defaults to `"%T.%3N"`.
|
351
|
+
|
352
|
+
For example, to configure `:max_bytes`, `:level` and `:metadata` for all logger instances do:
|
353
|
+
|
354
|
+
```ruby
|
355
|
+
TTY::Logger.configure do |config|
|
356
|
+
config.max_bytes = 2**10
|
357
|
+
config.level = :error
|
358
|
+
config.metadata = [:time, :date]
|
359
|
+
end
|
360
|
+
```
|
361
|
+
|
362
|
+
Or if you wish to setup configuration per logger instance use block:
|
363
|
+
|
364
|
+
```ruby
|
365
|
+
logger = TTY::Logger.new do |config|
|
366
|
+
config.max_bytes = 2**20
|
367
|
+
config.metadata = [:all]
|
368
|
+
end
|
369
|
+
```
|
370
|
+
|
371
|
+
You can also change the logger's configuration at runtime:
|
372
|
+
|
373
|
+
```ruby
|
374
|
+
logger.configure do |config|
|
375
|
+
config.level = :debug
|
376
|
+
end
|
377
|
+
```
|
378
|
+
|
379
|
+
### 2.4.1 Metadata
|
380
|
+
|
381
|
+
The `:metdata` configuration option can include the following symbols:
|
382
|
+
|
383
|
+
* `:pid` - the log event process identifier
|
384
|
+
* `:date` - the log event date
|
385
|
+
* `:time` - the log event time
|
386
|
+
* `:file` - the file with a line number the log event is triggered from
|
387
|
+
|
388
|
+
### 2.4.2 Filters
|
389
|
+
|
390
|
+
You can filter sensitive data out of log output with `filters` configuration option. The `filters` can be further configured to remove info from log message with `message` or structured data with `data`. Both methods, as a value accept a list of sensitive items to search for.
|
391
|
+
|
392
|
+
If you want to filter sensitive information from log messages use `message`:
|
393
|
+
|
394
|
+
```ruby
|
395
|
+
logger = TTY::Logger.new(output: output) do |config|
|
396
|
+
config.filters.message = %w[secret password]
|
397
|
+
end
|
398
|
+
```
|
399
|
+
|
400
|
+
Which by default will replace each matching string with `[FILTERED]` placeholder:
|
401
|
+
|
402
|
+
```ruby
|
403
|
+
logger.info("Super secret info with password")
|
404
|
+
# =>
|
405
|
+
# ℹ info Super [FILTERED] info with [FILTERED]
|
406
|
+
```
|
407
|
+
|
408
|
+
You can also replace each data item with a custom placeholder. To do so use a `:mask` keyword with a replacement placeholder.
|
409
|
+
|
410
|
+
For example, to replace "secret" content with placeholder `"<SECRET>"` do:
|
411
|
+
|
412
|
+
```ruby
|
413
|
+
logger = TTY::Logger.new do |config|
|
414
|
+
config.filters.message = %w[secret]
|
415
|
+
config.filters.mask = "<SECRET>"
|
416
|
+
end
|
417
|
+
```
|
418
|
+
|
419
|
+
When logged, it will produce:
|
420
|
+
|
421
|
+
```ruby
|
422
|
+
logger.info("Super secret info")
|
423
|
+
# =>
|
424
|
+
# ℹ info Super <SECRET> info
|
425
|
+
```
|
426
|
+
|
427
|
+
To filter out sensitive information out of structured data use `data` method. By default any value matching a parameter name will be filtered regardless of the level of nesting. If you wish to filter only a specific deeply nested key use a dot notation like `params.card.password` to only filter `{params: {card: {password: "Secret123"}}}`.
|
428
|
+
|
429
|
+
For example to filter out a `:password` from data do:
|
430
|
+
|
431
|
+
```ruby
|
432
|
+
logger = TTY::Logger.new do |config|
|
433
|
+
config.filters.data = %i[password]
|
434
|
+
end
|
435
|
+
```
|
436
|
+
|
437
|
+
This will filter out any key matching password:
|
438
|
+
|
439
|
+
```ruby
|
440
|
+
logger.info("Secret info", password: "Secret123", email: "")
|
441
|
+
# =>
|
442
|
+
# ℹ info Secret info password="[FILTERED]" email="secret@example.com"
|
29
443
|
```
|
30
444
|
|
445
|
+
But also any nested data item:
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
logger.info("Secret info", params: {password: "Secret123", email: ""})
|
449
|
+
# =>
|
450
|
+
# ℹ info Secret info params={password="[FILTERED]" email="secret@example.com"}
|
451
|
+
```
|
452
|
+
|
453
|
+
You're not limited to using only direct string comparison. You can also match based on regular expressions. For example, to match keys starting with `ba` we can add a following filter:
|
454
|
+
|
455
|
+
```ruby
|
456
|
+
logger = TTY::Logger.new do |config|
|
457
|
+
config.filters.data = [/ba/]
|
458
|
+
end
|
459
|
+
```
|
460
|
+
|
461
|
+
Then appropriate values will be masked:
|
462
|
+
|
463
|
+
```ruby
|
464
|
+
logger.info("Filtering data", {"foo" => {"bar" => "val", "baz" => "val"}})
|
465
|
+
# =>
|
466
|
+
# ℹ info Filtering data foo={bar="[FILTERED]" baz="[FILTERED]"}
|
467
|
+
```
|
468
|
+
|
469
|
+
You can mix and match. To filter keys based on pattern inside a deeply nested hash use dot notation with regular expression. For example, to find keys for the `:foo` parent key that starts with `:b` character, we could do:
|
470
|
+
|
471
|
+
```ruby
|
472
|
+
logger = TTY::Logger.new do |config|
|
473
|
+
config.filters.data = [/^foo\.b/]
|
474
|
+
end
|
475
|
+
```
|
476
|
+
|
477
|
+
Then only keys under the `:foo` key will be filtered:
|
478
|
+
|
479
|
+
```ruby
|
480
|
+
logger.info("Filtering data", {"foo" => {"bar" => "val"}, "baz" => {"bar" => val"}})
|
481
|
+
# =>
|
482
|
+
# ℹ info Filtering data foo={bar="[FILTERED]"} baz={bar=val}
|
483
|
+
```
|
484
|
+
|
485
|
+
### 2.5 Cloning
|
486
|
+
|
487
|
+
You can create a copy of a logger with the current configuration using the `copy` method.
|
488
|
+
|
489
|
+
For example, given the following logger with `:app` and `:env` data:
|
490
|
+
|
491
|
+
```ruby
|
492
|
+
logger = TTY::Logger.new(fields: {app: "parent", env: "prod"})
|
493
|
+
```
|
494
|
+
|
495
|
+
We can create a copy with a custom configuration that changes filtered message content and `:app` data:
|
496
|
+
|
497
|
+
```ruby
|
498
|
+
child_logger = logger.copy(app: "child") do |config|
|
499
|
+
config.filters = ["logging"]
|
500
|
+
end
|
501
|
+
```
|
502
|
+
|
503
|
+
```ruby
|
504
|
+
logger.info("Parent logging")
|
505
|
+
child_logger.warn("Child logging")
|
506
|
+
# =>
|
507
|
+
# ℹ info Parent logging app=parent env=prod
|
508
|
+
# ⚠ warning Child [FILTERED] app=child env=prod
|
509
|
+
```
|
510
|
+
|
511
|
+
### 2.6 Handlers
|
512
|
+
|
513
|
+
`TTY::Logger` supports many ways to handle log messages.
|
514
|
+
|
515
|
+
The available handlers by default are:
|
516
|
+
|
517
|
+
* `:console` - log messages to the console, enabled by default
|
518
|
+
* `:null` - discards any log messages
|
519
|
+
* `:stream` - log messages to an `IO` stream, a file, a socket or a console.
|
520
|
+
|
521
|
+
You can also implement your own [custom handler](#263-custom-handler).
|
522
|
+
|
523
|
+
The handlers can be configured via global or instance configuration with `handlers`. The handler can be a name or a class name:
|
524
|
+
|
525
|
+
```ruby
|
526
|
+
TTY::Logger.new do |config|
|
527
|
+
config.handlers = [:console]
|
528
|
+
end
|
529
|
+
```
|
530
|
+
|
531
|
+
Or using class name:
|
532
|
+
|
533
|
+
```ruby
|
534
|
+
TTY::Logger.new do |config|
|
535
|
+
config.handlers = [TTY::Logger::Handlers::Console]
|
536
|
+
end
|
537
|
+
```
|
538
|
+
|
539
|
+
Handlers can also be added/removed dynamically through `add_handler` or `remove_handler`.
|
540
|
+
|
541
|
+
```ruby
|
542
|
+
logger = TTY::Logger.new
|
543
|
+
logger.add_handler(:console)
|
544
|
+
logger.remove_handler(:console)
|
545
|
+
```
|
546
|
+
|
547
|
+
#### 2.6.1 Console Handler
|
548
|
+
|
549
|
+
The console handler prints log messages to the console. It supports the following options:
|
550
|
+
|
551
|
+
* `:styles` - a hash of styling options.
|
552
|
+
* `:formatter` - the formatter for log messages. Defaults to `:text`
|
553
|
+
* `:output` - the device to log error messages to. Defaults to `$stderr`
|
554
|
+
* `:message_format` - uses `sprintf` format to display messages. Defaults to `"%-25s"`.
|
555
|
+
|
556
|
+
The supported options in the `:styles` are:
|
557
|
+
|
558
|
+
* `:label` - the name for the log message.
|
559
|
+
* `:symbol` - the graphics to display before the log message label.
|
560
|
+
* `:color` - the color for the log message.
|
561
|
+
* `:levelpad` - the extra amount of padding used to display log label.
|
562
|
+
|
563
|
+
See the [TTY::Logger::Handlers::Console](https://github.com/piotrmurach/tty-logger/blob/master/lib/tty/logger/handlers/console.rb) for full list of styles.
|
564
|
+
|
565
|
+
Console handler has many default styles such as `success` and `error`:
|
566
|
+
|
567
|
+
```ruby
|
568
|
+
logger = TTY::Logger.new
|
569
|
+
logger.success("Default success")
|
570
|
+
logger.error("Default error")
|
571
|
+
# =>
|
572
|
+
# ✔ success Default success
|
573
|
+
# ⨯ error Default error
|
574
|
+
```
|
575
|
+
|
576
|
+
You can change the default styling with a tuple of handler name and options hash.
|
577
|
+
|
578
|
+
In our example, we want to change the styling of `success` and `error`:
|
579
|
+
|
580
|
+
```ruby
|
581
|
+
new_styles = {
|
582
|
+
styles: {
|
583
|
+
success: {
|
584
|
+
symbol: "+",
|
585
|
+
label: "Ohh yes"
|
586
|
+
},
|
587
|
+
error: {
|
588
|
+
symbol: "!",
|
589
|
+
label: "Dooh",
|
590
|
+
levelpad: 3 # the amount of extra padding to align level names in a column
|
591
|
+
}
|
592
|
+
}
|
593
|
+
}
|
594
|
+
```
|
595
|
+
|
596
|
+
And then use the `new_styles` when providing `handlers` configuration:
|
597
|
+
|
598
|
+
```ruby
|
599
|
+
styled_logger = TTY::Logger.new do |config|
|
600
|
+
config.handlers = [[:console, new_styles]]
|
601
|
+
end
|
602
|
+
|
603
|
+
styled_logger.success("Custom success")
|
604
|
+
styled_logger.error("Custom error")
|
605
|
+
# =>
|
606
|
+
# + Ohh yes Custom success
|
607
|
+
# ! Dooh Custom error
|
608
|
+
```
|
609
|
+
|
610
|
+
To increase message padding to a percentage of terminal width (depends on [tty-screen](https://github.com/piotrmurach/tty-screen/)):
|
611
|
+
|
612
|
+
```ruby
|
613
|
+
TTY::Logger.new do |config|
|
614
|
+
padding = (TTY::Screen.columns * 0.4).to_i
|
615
|
+
config.handlers = [[:console, { message_format: "%-#{padding}s" }]]
|
616
|
+
end
|
617
|
+
```
|
618
|
+
|
619
|
+
#### 2.6.2 Stream handler
|
620
|
+
|
621
|
+
To send log event data outside of console to another service or `IO` stream, you can use `:stream` handler.
|
622
|
+
|
623
|
+
```ruby
|
624
|
+
logger = TTY::Logger.new(output: output) do |config|
|
625
|
+
config.handlers = [:stream]
|
626
|
+
config.metadata = [:all]
|
627
|
+
end
|
628
|
+
```
|
629
|
+
|
630
|
+
By default, the output will be a plain text streamed to console. The text contains key and value pairs of all the metadata and the message of the log event.
|
631
|
+
|
632
|
+
```ruby
|
633
|
+
logger.info("Info about the deploy", app:"myap", env:"prod")
|
634
|
+
# =>
|
635
|
+
# pid=18315 date="2019-07-21" time="15:42:12.463" path="examples/stream.rb:17:in`<main>`"
|
636
|
+
# level=info message="Info about the deploy" app=myapp env=prod
|
637
|
+
```
|
638
|
+
|
639
|
+
You can change stream formatter for ease of working with external services such as `Logstash`. For example, to use `:stream` handler with `:json` format do:
|
640
|
+
|
641
|
+
```ruby
|
642
|
+
logger = TTY::Logger.new(output: output) do |config|
|
643
|
+
config.handlers = [[:stream, formatter: :json]]
|
644
|
+
config.metadata = [:all]
|
645
|
+
end
|
646
|
+
```
|
647
|
+
|
648
|
+
This will output JSON formatted text streamed to console.
|
649
|
+
|
650
|
+
```ruby
|
651
|
+
logger.info("Info about the deploy", app="myap", env="prod")
|
652
|
+
# =>
|
653
|
+
# {"pid":18513,"date":"2019-07-21","time":"15:54:09.924","path":"examples/stream.rb:17:in`<main>`",
|
654
|
+
# "level":"info","message":"Info about the deploy","app":"myapp","env":"prod"}
|
655
|
+
```
|
656
|
+
|
657
|
+
#### 2.6.3 Custom Handler
|
658
|
+
|
659
|
+
You can create your own log event handler if the default ones don't match your needs.
|
660
|
+
|
661
|
+
The design of your handler should include two calls:
|
662
|
+
|
663
|
+
* `initialize` - where all dependencies get injected
|
664
|
+
* `call` - where the log event is handled
|
665
|
+
|
666
|
+
We start with the implementation of the `initialize` method. This method by default is injected with `:config` key that includes all global configuration options. The `:output` key for displaying log message in the console and `:formatter`.
|
667
|
+
|
668
|
+
In our case we also add custom `:label`:
|
669
|
+
|
670
|
+
```ruby
|
671
|
+
class MyHandler
|
672
|
+
def initialize(output: nil, config: nil, formatter: nil, label: nil)
|
673
|
+
@label = label
|
674
|
+
@output = output
|
675
|
+
end
|
676
|
+
end
|
677
|
+
```
|
678
|
+
|
679
|
+
Next is the `call` method that accepts the log `event`.
|
680
|
+
|
681
|
+
The `event` has the following attributes:
|
682
|
+
|
683
|
+
* `message` - the array of message parts to be printed
|
684
|
+
* `fields` - the structured data supplied with the event
|
685
|
+
* `metadata` - the additional info about the event. See [metadata](#241-metadata) section for details.
|
686
|
+
|
687
|
+
We add implementation of `call`:
|
688
|
+
|
689
|
+
```ruby
|
690
|
+
class MyHandler
|
691
|
+
def initialize(output: nil, config: nil, label: nil)
|
692
|
+
@label = label
|
693
|
+
@output = output
|
694
|
+
end
|
695
|
+
|
696
|
+
def call(event)
|
697
|
+
@output.puts "(#{@label}) #{event.message.join}"
|
698
|
+
end
|
699
|
+
end
|
700
|
+
```
|
701
|
+
|
702
|
+
Once you have your custom handler, you need to register it with the logger. You can do so using the `handlers` configuration option:
|
703
|
+
|
704
|
+
```ruby
|
705
|
+
logger = TTY::Logger.new do |config|
|
706
|
+
config.handlers = [[MyHandler, label: "myhandler"]]
|
707
|
+
end
|
708
|
+
```
|
709
|
+
|
710
|
+
Or add your handler dynamically after logger initialization:
|
711
|
+
|
712
|
+
```ruby
|
713
|
+
logger = TTY::Logger.new
|
714
|
+
logger.add_handler [MyHandler, label: "myhandler"]
|
715
|
+
```
|
716
|
+
|
717
|
+
#### 2.6.4 Multiple Handlers
|
718
|
+
|
719
|
+
You can define as many handlers as you need. For example, you may log messages both to console and stream:
|
720
|
+
|
721
|
+
```ruby
|
722
|
+
logger = TTY::Logger.new do |config|
|
723
|
+
config.handlers = [:console, :stream]
|
724
|
+
end
|
725
|
+
```
|
726
|
+
|
727
|
+
Each handler can have its own configuration. For example, you can register `:console` handler to log messages above error level and `:stream` that logs any message with info or higher level:
|
728
|
+
|
729
|
+
```ruby
|
730
|
+
logger = TTY::Logger.new do |config|
|
731
|
+
config.handlers = [
|
732
|
+
[:console, level: :error],
|
733
|
+
[:stream, level: :info]
|
734
|
+
]
|
735
|
+
end
|
736
|
+
```
|
737
|
+
|
738
|
+
### 2.7 Formatters
|
739
|
+
|
740
|
+
The available formatters are:
|
741
|
+
|
742
|
+
* `:json`
|
743
|
+
* `:text`
|
744
|
+
|
745
|
+
You can configure format for all the handlers:
|
746
|
+
|
747
|
+
```ruby
|
748
|
+
TTY::Logger.new do |config|
|
749
|
+
config.formatter = :json
|
750
|
+
end
|
751
|
+
```
|
752
|
+
|
753
|
+
Or specify a different formatter for each handler. For example, let's say you want to log to console twice, once with default formatter and once with `:json` formatter:
|
754
|
+
|
755
|
+
```ruby
|
756
|
+
TTY::Logger.new do |config|
|
757
|
+
config.handlers = [:console, [:console, formatter: :json]]
|
758
|
+
end
|
759
|
+
```
|
760
|
+
|
761
|
+
### 2.8 Output Streams
|
762
|
+
|
763
|
+
By default all log events are output to `stderr`. You can change this using configuration `output` option. Any `IO`-like stream such as file, socket or console can be used. For example, to log all messages to a file do:
|
764
|
+
|
765
|
+
```ruby
|
766
|
+
logger = TTY::Logger.new do |config|
|
767
|
+
config.output = File.open("errors.log", "a")
|
768
|
+
end
|
769
|
+
```
|
770
|
+
|
771
|
+
You can also specify multiple streams that all log messages will be sent to:
|
772
|
+
|
773
|
+
```ruby
|
774
|
+
logger = TTY::Logger.new do |config|
|
775
|
+
config.output = [$stderr, File.open("errors.log", "a")]
|
776
|
+
end
|
777
|
+
```
|
778
|
+
|
779
|
+
Conversely, you can specify different output for each of the handlers used. For example, you can output all messages above info level to a file with a stream handler and only show error messages in the console with a nicely formatted output.
|
780
|
+
|
781
|
+
```ruby
|
782
|
+
logger = TTY::Logger.new do |config|
|
783
|
+
config.handlers = [
|
784
|
+
[:console, output: $stderr, level: :error],
|
785
|
+
[:stream, output: File.open("errors.log", "a"), level: :info)]
|
786
|
+
]
|
787
|
+
end
|
788
|
+
```
|
789
|
+
|
790
|
+
## 3. Community Extensions
|
791
|
+
|
792
|
+
### 3.1 Sentry Handler
|
793
|
+
|
794
|
+
[tty-logger-raven](https://github.com/ianks/tty-logger-raven) provides an extension for Sentry.io.
|
795
|
+
|
31
796
|
## Development
|
32
797
|
|
33
798
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|