betterlog 2.1.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42be8d52810b7073915e4b1efea2bbf42a9dab3fce71392d2d76018a6e15f1b8
4
- data.tar.gz: 614f43b1a12d2e45bd0149c32045bdba913269ffe3799958584ec2bcb2ad0007
3
+ metadata.gz: b6cba025c355a1dfa04219216b3bfd51d99e37e5d22bfbf46fe2d29c93f43f89
4
+ data.tar.gz: ff8256d38cb36de010ce1f0122e51e5e95aea082121533fb9b1ccbd148521125
5
5
  SHA512:
6
- metadata.gz: 88672071ddeea36aaca49a2f49ec2408f2e378b2f17de5c2aed437aeed1e73ba8e44ee0af0f9bac72c10f8561b226191e982f4d1076922cae54f1d91327ea846
7
- data.tar.gz: 46686b79bf11b7013e784cd6b4031b686b3dedeab53f401fde392d852802e87ff01ee28014a125f601f4120263a6f3ce0c0d288995a3cf240dfa58d9c8310513
6
+ metadata.gz: 33d3ed44b0b7ffca65ae280eab36317c37c3f83e1bff19084bd054b6e22edc648e396d66ca270d972a85868740a5a1c1326d427f62f4942249b89022cafec34e
7
+ data.tar.gz: a9e446d2e8ed415cc5591175752a6b2d901e4ad4890fa8c1ef142db8df6c6959edb80e5cc660f160c11537884bf604148a9311287e29e85743b6473c66c724ca
data/CHANGES.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changes
2
2
 
3
+ ## 2025-09-03 v2.1.3
4
+
5
+ - Improved documentation for the `colorize` method with detailed styling examples
6
+ - Enhanced documentation for the `format_pattern` method with a detailed syntax guide
7
+ - Added `doc` directory to `.gitignore` and updated `Rakefile` to include it in the ignore list
8
+
3
9
  ## 2025-09-02 v2.1.2
4
10
 
5
11
  - Moved only `filter_severities` method to private scope
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2018 Florian Frank
1
+ Copyright 2018 betterplace
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -2,74 +2,327 @@
2
2
 
3
3
  ## Description
4
4
 
5
- Logging tools for betterplace structured logging in rails applications.
5
+ Structured logging support for Rails applications with flexible formatting and
6
+ filtering capabilities.
6
7
 
7
- ## Configuration
8
+ ## Installation
8
9
 
9
- Copy the example configuration in config/log.yml into your application to get
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
- gem 'betterlog'
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
- ### `betterlog`
23
+ ### Basic Logging
19
24
 
20
- Use it to tail local logfiles:
25
+ The main logging interface provides structured JSON logging with automatic
26
+ Rails integration:
21
27
 
22
- ```
23
- $ betterlog -f
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
- or filter from stdin with
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
- $ betterlog -F rails -n 1000 -s GET
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
- Display the help for more options with `betterlog -h`.
87
+ Search for specific terms in log files:
88
+ ```bash
89
+ $ betterlog -f -s SELECT
90
+ ```
39
91
 
40
- ### `betterlog_pusher`
92
+ This filters out all logging messages where `meta: { module: 'api_v4' }` was
93
+ given:
41
94
 
42
- - `BETTERLOG_SERVER_URL` is the URL log information is ultimately posted to
43
- in the form of `https://user:password@appname-prd-log.betterops.de/log`.
95
+ ```
96
+ $ betterlog -f -s meta:module=api_v4
97
+ ```
44
98
 
45
- - `BETTERLOG_LINES`, e. g. 1000, is the number of lines which are posted per
46
- every request to the above URL.
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
- - `REDIS_URL` the redis server URL for the server where Log information is
49
- stored before posted to the betterlog server.
105
+ Filter stdin from file with default format in color:
106
+ ```bash
107
+ $ betterlog -pd -c < unicorn.log
108
+ ```
50
109
 
51
- The rails application should be configured like this to store log information
52
- on this redis server:
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
- ### `betterlog_sink`
117
+ Betterlog follows a modular architecture where different components work
118
+ together to provide structured logging:
59
119
 
60
- This is a small wrapper around the `kubectl logs…` command,
61
- see `kubectl help logs` for the options.
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
- To tail a log and prettify the output just call and pipe to the `betterlog`
64
- executable:
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
- $ betterlog_sink --since=1m -f | betterlog
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
- The sink always defaults to the production logfile, to switch the context to
71
- staging, prepend the command with the `LOG_ENV` env variable like so:
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
- $ LOG_ENV=staging betterlog_sink -f | betterlog
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/Rakefile CHANGED
@@ -12,8 +12,8 @@ GemHadar do
12
12
  test_dir 'spec'
13
13
  ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', 'coverage', '.rvmrc',
14
14
  '.ruby-version', '.AppleDouble', 'tags', '.DS_Store', '.utilsrc',
15
- '.bundle', '.byebug_history', 'errors.lst', '.yardoc', 'betterlog-server',
16
- 'gospace'
15
+ '.bundle', '.byebug_history', 'errors.lst', '.yardoc', 'doc',
16
+ 'betterlog-server', 'gospace'
17
17
  package_ignore '.all_images.yml', '.utilsrc', '.rspec', '.tool-versions',
18
18
  '.gitignore', *Dir['.semaphore/**/*'], *Dir['.github/**/*']
19
19
  readme 'README.md'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.2
1
+ 2.1.4
data/betterlog.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: betterlog 2.1.2 ruby lib
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.2".freeze
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]
@@ -65,15 +65,48 @@ module Betterlog
65
65
  #
66
66
  # This method applies visual styling to a string by looking up the
67
67
  # appropriate style configuration based on the provided key and value,
68
- # then applying that style using the internal apply_style method.
69
- #
70
- # @param key [ Object ] the lookup key for determining the style
71
- # configuration
72
- # @param value [ Object ] the value used to determine which specific
73
- # style to apply
74
- # @param string [ Object ] the string to be colorized, defaults to the
75
- # key if not provided
76
- # @return [ String ] the colorized string based on the configured styles
68
+ # then applying that style using the internal apply_style method. The
69
+ # colorization logic supports both static and dynamic styling based on
70
+ # the value being formatted.
71
+ #
72
+ # <b>Style Configuration Patterns</b>
73
+ #
74
+ # Styles can be configured in several ways:
75
+ #
76
+ # <b>Static Styles</b>
77
+ # - String: Single ANSI color code (e.g., "red", "bold")
78
+ # - Array: Multiple ANSI codes (e.g., ["red", "bold"])
79
+ #
80
+ # <b>Dynamic Styles</b>
81
+ # - ComplexConfig::Settings: Different styles based on value content
82
+ # Example: { debug: "green", error: "red" } where the style is selected based on the value
83
+ #
84
+ # <b>Usage Examples</b>
85
+ #
86
+ # Given a configuration like:
87
+ # styles:
88
+ # 'timestamp': [ yellow, bold ]
89
+ # severity:
90
+ # debug: green
91
+ # info: green
92
+ # warn: yellow
93
+ # error: red
94
+ #
95
+ # The method will:
96
+ # - Colorize "{timestamp}" with yellow/bold styling
97
+ # - Colorize "{severity}" with green for "debug"/"info", yellow for "warn", red for "error"
98
+ #
99
+ # @param key [Object] the lookup key for determining the style configuration
100
+ # @param value [Object] the value used to determine which specific style to apply
101
+ # @param string [Object] the string to be colorized, defaults to the key if not provided
102
+ # @return [String] the colorized string based on the configured styles
103
+ # @see Betterlog::Log::EventFormatter#apply_style
104
+ #
105
+ # @example Static styling
106
+ # colorize(:timestamp, nil, "2023-12-01") # Returns colored timestamp string
107
+ #
108
+ # @example Dynamic styling based on value
109
+ # colorize(:severity, :error, "ERROR") # Returns red-colored string
77
110
  def colorize(key, value, string = key)
78
111
  case style = cc.log.styles[key]
79
112
  when nil, String, Array
@@ -109,18 +142,54 @@ module Betterlog
109
142
  end
110
143
  end
111
144
 
112
- # Formats a log event using a specified pattern with support for
113
- # directives and colorization.
145
+ # Formats a log event using a specified pattern with support for directives and colorization.
114
146
  #
115
- # This method processes a format string by replacing placeholders with
116
- # actual event data, applying formatting directives for special handling
117
- # of values like objects or timestamps, and optionally applying color
118
- # styling based on configured styles.
147
+ # This method processes a format string by replacing placeholders with actual event data,
148
+ # applying formatting directives for special handling of values like objects or timestamps,
149
+ # and optionally applying color styling based on configured styles.
119
150
  #
120
- # @param format [ String ] the format pattern to apply to the log event
121
- # @return [ String ] the formatted string representation of the log event
151
+ # <b>Format Pattern Syntax</b>
152
+ #
153
+ # Format patterns use curly braces `{}` to define placeholders with optional directives:
154
+ #
155
+ # <b>Basic Key Substitution</b>
156
+ # - `{key}` - Substitutes the value of `@event[key]`
157
+ # - `{-key}` - Invisible variant; omits output when value is nil (instead of showing `{key}`)
158
+ #
159
+ # <b>Object Formatting Directives</b>
160
+ # - `{%O%key}` - Formats complex objects (arrays/hashes) with nested structure visualization
161
+ # Example: Shows arrays with bullet points and hashes with key-value pairs
162
+ #
163
+ # <b>Timestamp Formatting Directives</b>
164
+ # - `{%t%key}` - Formats timestamp values with various time formats based on flag:
165
+ # - `%ut%key` - UTC ISO8601 format (e.g., "2023-12-01T10:30:45.123Z")
166
+ # - `%lt%key` - Local time ISO8601 format
167
+ # - `%it%key` - Unix timestamp integer (e.g., "1701423425")
168
+ # - `%ft%key` - Unix timestamp float (e.g., "1701423425.123")
169
+ # - `%t%key` (default) - UTC ISO8601 format
170
+ #
171
+ # <b>String Formatting Directives</b>
172
+ # - `{%.format%key}` - Applies Ruby string formatting using the `%` operator
173
+ # Example: `{%.2f%price}` formats a float to 2 decimal places
174
+ #
175
+ # <b>Colorization</b>
176
+ # Values are automatically colorized based on configured styles in the `styles` configuration.
177
+ # For example, timestamp values use yellow/bold styling, and severity levels use different colors
178
+ # based on their value (debug=green, warn=yellow, error=red, etc.).
179
+ #
180
+ # @param format [String] the format pattern to apply to the log event
181
+ # @return [String] the formatted string representation of the log event
122
182
  # @see Betterlog::Log::EventFormatter#format_object
123
183
  # @see Betterlog::Log::EventFormatter#colorize
184
+ #
185
+ # @example Basic usage with default configuration
186
+ # formatter.format_pattern(format: "{%lt%timestamp} {message}")
187
+ #
188
+ # @example Complex formatting with object display
189
+ # formatter.format_pattern(format: "{%O%backtrace} {message}")
190
+ #
191
+ # @example Conditional display of optional fields
192
+ # formatter.format_pattern(format: "{file}{-%O%backtrace}")
124
193
  def format_pattern(format:)
125
194
  format.
126
195
  gsub('\n', "\n").
@@ -1,6 +1,6 @@
1
1
  module Betterlog
2
2
  # Betterlog version
3
- VERSION = '2.1.2'
3
+ VERSION = '2.1.4'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: betterlog
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - betterplace Developers