betterlog 2.1.3 → 2.1.4
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/LICENSE +1 -1
- data/README.md +288 -35
- data/VERSION +1 -1
- data/betterlog.gemspec +2 -2
- data/lib/betterlog/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6cba025c355a1dfa04219216b3bfd51d99e37e5d22bfbf46fe2d29c93f43f89
|
4
|
+
data.tar.gz: ff8256d38cb36de010ce1f0122e51e5e95aea082121533fb9b1ccbd148521125
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33d3ed44b0b7ffca65ae280eab36317c37c3f83e1bff19084bd054b6e22edc648e396d66ca270d972a85868740a5a1c1326d427f62f4942249b89022cafec34e
|
7
|
+
data.tar.gz: a9e446d2e8ed415cc5591175752a6b2d901e4ad4890fa8c1ef142db8df6c6959edb80e5cc660f160c11537884bf604148a9311287e29e85743b6473c66c724ca
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -2,74 +2,327 @@
|
|
2
2
|
|
3
3
|
## Description
|
4
4
|
|
5
|
-
|
5
|
+
Structured logging support for Rails applications with flexible formatting and
|
6
|
+
filtering capabilities.
|
6
7
|
|
7
|
-
##
|
8
|
+
## Installation
|
8
9
|
|
9
|
-
|
10
|
-
you started. Then add this line to your Gemfile:
|
10
|
+
You can use rubygems to fetch the gem and install it for you:
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
# gem install betterlog
|
13
|
+
|
14
|
+
You can also put this line into your Gemfile:
|
15
|
+
|
16
|
+
gem 'betterlog'
|
17
|
+
|
18
|
+
and bundle. This will make the `Betterlog` module and its logging facilities
|
19
|
+
available.
|
15
20
|
|
16
21
|
## Usage
|
17
22
|
|
18
|
-
###
|
23
|
+
### Basic Logging
|
19
24
|
|
20
|
-
|
25
|
+
The main logging interface provides structured JSON logging with automatic
|
26
|
+
Rails integration:
|
21
27
|
|
22
|
-
```
|
23
|
-
|
28
|
+
```ruby
|
29
|
+
# Log simple messages
|
30
|
+
Log.info("User logged in", meta: { module: 'session', user_id: 123 })
|
31
|
+
Log.error("Database connection failed", meta: { module: 'database', error: "Connection timeout" })
|
32
|
+
|
33
|
+
# Log exceptions with full backtrace information
|
34
|
+
begin
|
35
|
+
# some code that might fail
|
36
|
+
rescue => e
|
37
|
+
Log.error(e, meta: { module: 'api_v4', context: "API request processing" })
|
38
|
+
end
|
24
39
|
```
|
25
40
|
|
26
|
-
|
41
|
+
### Command-Line Interface
|
27
42
|
|
43
|
+
The `betterlog` CLI tool provides powerful log file processing and filtering
|
44
|
+
capabilities:
|
45
|
+
|
46
|
+
#### Basic Usage
|
47
|
+
|
48
|
+
Tail local logfiles:
|
49
|
+
```bash
|
50
|
+
$ betterlog -f
|
28
51
|
```
|
52
|
+
|
53
|
+
Filter from stdin:
|
54
|
+
```bash
|
29
55
|
$ cat log/development.log | betterlog
|
30
56
|
```
|
31
57
|
|
32
58
|
Search for GET in the last 1000 rails log lines:
|
59
|
+
```bash
|
60
|
+
$ betterlog -F rails -n 1000 -s GET
|
61
|
+
```
|
33
62
|
|
63
|
+
Display help for all options:
|
64
|
+
```bash
|
65
|
+
$ betterlog -h
|
34
66
|
```
|
35
|
-
|
67
|
+
|
68
|
+
#### Command-Line Options
|
69
|
+
|
70
|
+
- `-c` Enable colors during pretty printing
|
71
|
+
- `-f` Follow the log files in real-time
|
72
|
+
- `-h` Display help information
|
73
|
+
- `-p FORMAT` Pretty print log files (e.g., `long`, `short`)
|
74
|
+
- `-e EMITTER` Only output events from specific emitters
|
75
|
+
- `-s MATCH` Only display events matching search string
|
76
|
+
- `-S SEVERITY` Only output events with specified severity level
|
77
|
+
- `-n NUMBER` Rewind this many lines backwards before tailing
|
78
|
+
- `-F SHORTCUT` Use configuration file shortcuts
|
79
|
+
|
80
|
+
#### Examples
|
81
|
+
|
82
|
+
Follow Rails logs with colorized output for errors or greater:
|
83
|
+
```bash
|
84
|
+
$ betterlog -f -F rails -p long -c -S ">=error"
|
36
85
|
```
|
37
86
|
|
38
|
-
|
87
|
+
Search for specific terms in log files:
|
88
|
+
```bash
|
89
|
+
$ betterlog -f -s SELECT
|
90
|
+
```
|
39
91
|
|
40
|
-
|
92
|
+
This filters out all logging messages where `meta: { module: 'api_v4' }` was
|
93
|
+
given:
|
41
94
|
|
42
|
-
|
43
|
-
|
95
|
+
```
|
96
|
+
$ betterlog -f -s meta:module=api_v4
|
97
|
+
```
|
44
98
|
|
45
|
-
|
46
|
-
|
99
|
+
Follow multiple log files with default format in colors including the last 10
|
100
|
+
lines:
|
101
|
+
```bash
|
102
|
+
$ betterlog -f -F rails -F redis -pd -c -n 10
|
103
|
+
```
|
47
104
|
|
48
|
-
|
49
|
-
|
105
|
+
Filter stdin from file with default format in color:
|
106
|
+
```bash
|
107
|
+
$ betterlog -pd -c < unicorn.log
|
108
|
+
```
|
50
109
|
|
51
|
-
|
52
|
-
|
110
|
+
Filter last 10 lines of a file with default format in color:
|
111
|
+
```bash
|
112
|
+
$ betterlog -c -pd -n 10 unicorn.log
|
113
|
+
```
|
53
114
|
|
54
|
-
|
55
|
-
config.logger = Betterlog::Logger.new(Redis.new(url: ENV.fetch('REDIS_URL')))
|
56
|
-
```
|
115
|
+
### Architecture Overview
|
57
116
|
|
58
|
-
|
117
|
+
Betterlog follows a modular architecture where different components work
|
118
|
+
together to provide structured logging:
|
59
119
|
|
60
|
-
|
61
|
-
|
120
|
+
```mermaid
|
121
|
+
graph TD
|
122
|
+
A[Application Code] --> B(Log Interface)
|
123
|
+
B --> C[Betterlog::Log]
|
124
|
+
C --> D[Event Creation]
|
125
|
+
D --> E[JSON Serialization]
|
126
|
+
E --> F[Formatting Engine]
|
127
|
+
F --> G[Output to Logger]
|
62
128
|
|
63
|
-
|
64
|
-
|
129
|
+
subgraph "Rails Integration"
|
130
|
+
H[Rails.logger]
|
131
|
+
I[LegacyFormatter]
|
132
|
+
J[Structured Logging]
|
133
|
+
H <---> I
|
134
|
+
I <---> J
|
135
|
+
end
|
65
136
|
|
137
|
+
C --> H
|
66
138
|
```
|
67
|
-
|
139
|
+
|
140
|
+
**Diagram Explanation**: This shows how the system is structured. Application
|
141
|
+
code calls the logging interface (`Log.info`), which creates structured events
|
142
|
+
and processes them through JSON serialization and formatting before outputting
|
143
|
+
to either Rails' logger or a default logger. The Rails integration section
|
144
|
+
shows how it seamlessly connects with Rails' existing logging infrastructure.
|
145
|
+
|
146
|
+
### Logging Flow
|
147
|
+
|
148
|
+
When you call a logging method, the following process occurs:
|
149
|
+
|
150
|
+
```mermaid
|
151
|
+
sequenceDiagram
|
152
|
+
participant App as Application
|
153
|
+
participant Log as Betterlog::Log
|
154
|
+
participant Formatter as EventFormatter
|
155
|
+
participant Logger as Rails.logger/DefaultLogger
|
156
|
+
|
157
|
+
App->>Log: Log.info(message, data)
|
158
|
+
Log->>Formatter: format(pretty: false)
|
159
|
+
Formatter->>Formatter: JSON.generate(event)
|
160
|
+
Formatter->>Logger: logger.info(json_string)
|
161
|
+
Logger-->>App: Success/Failure
|
68
162
|
```
|
69
163
|
|
70
|
-
|
71
|
-
|
164
|
+
**Diagram Explanation**: This illustrates the complete logging workflow. When
|
165
|
+
you call `Log.info()`, it goes through the Betterlog::Log (or Log) class, gets
|
166
|
+
formatted into a structured event with JSON serialization, and finally outputs
|
167
|
+
to either Rails' logger or the default logger. The process is designed to
|
168
|
+
maintain structured logging while being compatible with existing Rails logging
|
169
|
+
systems.
|
72
170
|
|
171
|
+
### Thread-Local Metadata
|
172
|
+
|
173
|
+
Betterlog supports thread-local metadata that gets automatically included with
|
174
|
+
all log events:
|
175
|
+
|
176
|
+
```mermaid
|
177
|
+
sequenceDiagram
|
178
|
+
participant User as User Code
|
179
|
+
participant Meta as GlobalMetadata
|
180
|
+
participant Log as Betterlog::Log
|
181
|
+
|
182
|
+
User->>Meta: Betterlog.with_meta(data) { block }
|
183
|
+
Meta->>Meta: Add data to thread-local storage
|
184
|
+
Log->>Log: emit(event)
|
185
|
+
Log->>Log: Merge with GlobalMetadata.current
|
186
|
+
Meta->>Meta: Remove data after block
|
73
187
|
```
|
74
|
-
|
188
|
+
|
189
|
+
**Diagram Explanation**: This shows how thread-local metadata works. When you
|
190
|
+
use `Betterlog.with_meta()`, it temporarily adds metadata to a thread-local
|
191
|
+
store, which gets merged with your log events during processing. The metadata
|
192
|
+
is automatically cleaned up after the block executes, ensuring thread safety
|
193
|
+
and preventing memory leaks.
|
194
|
+
|
195
|
+
**Practical Usage Examples**:
|
196
|
+
|
197
|
+
**In Rails Controllers** (from `application_controller.rb`):
|
198
|
+
```ruby
|
199
|
+
class ApplicationController < ActionController::Base
|
200
|
+
# …
|
201
|
+
around_action :set_global_metadata
|
202
|
+
|
203
|
+
|
204
|
+
def set_global_metadata(&block)
|
205
|
+
Betterlog.with_meta(
|
206
|
+
request_id: request.request_id,
|
207
|
+
user_id: current_user&.id,
|
208
|
+
&block
|
209
|
+
)
|
210
|
+
end
|
211
|
+
end
|
75
212
|
```
|
213
|
+
This ensures all logs within a request include user and request context
|
214
|
+
automatically.
|
215
|
+
|
216
|
+
|
217
|
+
**In Background Jobs** (from `booking_mandate/job.rb`):
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
Betterlog.with_meta(
|
221
|
+
module: 'booking',
|
222
|
+
booking_mandate_id: id,
|
223
|
+
) do
|
224
|
+
# All logs in this block automatically include:
|
225
|
+
# - module: 'booking'
|
226
|
+
# - booking_mandate_id: id
|
227
|
+
Log.info("Successfully booked booking mandate #{id}")
|
228
|
+
end
|
229
|
+
```
|
230
|
+
|
231
|
+
This pattern provides consistent contextual information across all log entries
|
232
|
+
for a given request or job execution while maintaining thread safety.
|
233
|
+
|
234
|
+
These examples show how global metadata is actually used in production code:
|
235
|
+
1. **Controller level**: Automatically includes request and user context for
|
236
|
+
all logs during a web request
|
237
|
+
2. **Job level**: Automatically includes job-specific context (like booking
|
238
|
+
mandate ID) for all logs within that job execution
|
239
|
+
|
240
|
+
This makes debugging much easier since you can always trace logs back to their
|
241
|
+
specific context without having to manually pass around context information.
|
242
|
+
|
243
|
+
### Configuration
|
244
|
+
|
245
|
+
Configuration is handled through the `config/log.yml` file. The configuration
|
246
|
+
supports:
|
247
|
+
|
248
|
+
- Log formats and styling definitions
|
249
|
+
- Severity filtering rules
|
250
|
+
- Configuration shortcuts for different environments
|
251
|
+
- Color schemes for terminal output
|
252
|
+
|
253
|
+
Example configuration structure:
|
254
|
+
```yaml
|
255
|
+
development: &development
|
256
|
+
level: <%= ENV.fetch('LOG_LEVEL', :debug).to_sym %>
|
257
|
+
styles:
|
258
|
+
'timestamp': [ yellow, bold ]
|
259
|
+
'file': [ blue, bold ]
|
260
|
+
severity:
|
261
|
+
debug: green
|
262
|
+
info: green
|
263
|
+
warn: yellow
|
264
|
+
error: red
|
265
|
+
fatal: [ red, blink ]
|
266
|
+
unknown: red
|
267
|
+
formats:
|
268
|
+
default: &default_format >
|
269
|
+
{%lt%timestamp} {%5s%severity}
|
270
|
+
"{%0.<%= ENV.fetch('COLUMNS', 80).to_i / 2 %>%message}"
|
271
|
+
{host}
|
272
|
+
{location}
|
273
|
+
{file}{-%O%backtrace}{-%O%meta}
|
274
|
+
d: *default_format
|
275
|
+
long: &long_format |
|
276
|
+
type: {type}
|
277
|
+
timestamp: {%lt%timestamp}
|
278
|
+
severity: {severity}
|
279
|
+
message: "{message}"
|
280
|
+
error_class: {error_class}
|
281
|
+
backtrace: {%O%backtrace}
|
282
|
+
host: {host}
|
283
|
+
location: {location}
|
284
|
+
file: {file}
|
285
|
+
meta: {%O%meta}\n
|
286
|
+
l: *long_format
|
287
|
+
legacy: >
|
288
|
+
{%0.1s%severity} [{%lt%timestamp} #{%d%pid}] {%5s%severity} --
|
289
|
+
{program}: {message}
|
290
|
+
config_files:
|
291
|
+
rails:
|
292
|
+
- log/development.log
|
293
|
+
test:
|
294
|
+
- log/test.log
|
295
|
+
mysql:
|
296
|
+
- log/mysql/mysqld.log
|
297
|
+
- log/mysql/mysql-slow.log
|
298
|
+
legacy_supported: yes
|
299
|
+
test:
|
300
|
+
<<: *development
|
301
|
+
level: <%= ENV.fetch('LOG_LEVEL', :debug).to_sym %>
|
302
|
+
staging: *development
|
303
|
+
production:
|
304
|
+
<<: *development
|
305
|
+
level: <%= ENV.fetch('LOG_LEVEL', :info).to_sym %>
|
306
|
+
```
|
307
|
+
|
308
|
+
### Rails Integration
|
309
|
+
|
310
|
+
When used in a Rails application, betterlog automatically integrates with
|
311
|
+
Rails' logging system by detecting Rails presence and using `Rails.logger`
|
312
|
+
instead of its default logger. The system also includes a
|
313
|
+
`Betterlog::Log::LegacyEventFormatter` that ensures compatibility with existing
|
314
|
+
Rails logging formats.
|
315
|
+
|
316
|
+
## Download
|
317
|
+
|
318
|
+
The homepage of this library is located at
|
319
|
+
|
320
|
+
* https://github.com/betterplace/betterlog
|
321
|
+
|
322
|
+
## Author
|
323
|
+
|
324
|
+
The [betterplace Developers](mailto:developers@betterplace.org)
|
325
|
+
|
326
|
+
## License
|
327
|
+
|
328
|
+
This software is licensed under the [Apache 2.0 license](LICENSE)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.4
|
data/betterlog.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: betterlog 2.1.
|
2
|
+
# stub: betterlog 2.1.4 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "betterlog".freeze
|
6
|
-
s.version = "2.1.
|
6
|
+
s.version = "2.1.4".freeze
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib".freeze]
|
data/lib/betterlog/version.rb
CHANGED