philiprehberger-structured_logger 0.4.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 +6 -0
- data/README.md +36 -0
- data/lib/philiprehberger/structured_logger/logger.rb +52 -0
- data/lib/philiprehberger/structured_logger/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c8cf0e19aa5820ae2ee81a3cf73ece78e151e6a53f7fc48f8c74e94f9b7841ed
|
|
4
|
+
data.tar.gz: c7ab4e1bc11362adc93bfe54dcf06360b846a232d1d433c597a60f7d2e4a1fd0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d239e014b25dd71f821e97213b1ad979c2444d6cae3f4db330debec29e6f6a045b6dde4abc84e350f6cca3f384886fccc2430d413709131f58a6b81f8b09657e
|
|
7
|
+
data.tar.gz: 9a390ecf766ec22be918f9fb3a2daf5fcc8643cafe7848e82b72ce6fae7fc90c3cc176ba15da5dc2fb7f2544cf51730088851ec4fa801fe80ab70dfdd98eca7f
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.0] - 2026-04-25
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `Logger#with_tags(*tags)` for tagged context blocks with automatic restoration
|
|
14
|
+
- `Logger#measure_value(message)` variant of `#measure` that returns the block result while still emitting the timing entry
|
|
15
|
+
|
|
10
16
|
## [0.4.0] - 2026-04-17
|
|
11
17
|
|
|
12
18
|
### Added
|
data/README.md
CHANGED
|
@@ -256,6 +256,40 @@ logger.close
|
|
|
256
256
|
|
|
257
257
|
When the buffer is full, writes fall back to synchronous mode (backpressure) to avoid dropping log entries.
|
|
258
258
|
|
|
259
|
+
### Tagged Context
|
|
260
|
+
|
|
261
|
+
Use `with_tags` to add tags to the logging context for the duration of a block. Tags merge with any existing tags (de-duplicated, preserving order) and the original context is restored on exit:
|
|
262
|
+
|
|
263
|
+
```ruby
|
|
264
|
+
require "philiprehberger/structured_logger"
|
|
265
|
+
|
|
266
|
+
logger = Philiprehberger::StructuredLogger::Logger.new
|
|
267
|
+
|
|
268
|
+
logger.with_tags("auth", "request") do
|
|
269
|
+
logger.info("Login attempt")
|
|
270
|
+
# => {"timestamp":"...","level":"info","message":"Login attempt","tags":["auth","request"]}
|
|
271
|
+
end
|
|
272
|
+
# Tags are restored after the block
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Measuring with Return Value
|
|
276
|
+
|
|
277
|
+
Use `measure_value` when you need the block's result while still emitting a timing entry:
|
|
278
|
+
|
|
279
|
+
```ruby
|
|
280
|
+
require "philiprehberger/structured_logger"
|
|
281
|
+
|
|
282
|
+
logger = Philiprehberger::StructuredLogger::Logger.new
|
|
283
|
+
|
|
284
|
+
result = logger.measure_value("db.query") do
|
|
285
|
+
# ...query the database...
|
|
286
|
+
[{ id: 1, name: "Alice" }]
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# result == [{ id: 1, name: "Alice" }]
|
|
290
|
+
# => {"timestamp":"...","level":"info","message":"db.query","event":"db.query","duration_ms":12.345}
|
|
291
|
+
```
|
|
292
|
+
|
|
259
293
|
## API
|
|
260
294
|
|
|
261
295
|
### `Philiprehberger::StructuredLogger::Logger`
|
|
@@ -275,6 +309,8 @@ When the buffer is full, writes fall back to synchronous mode (backpressure) to
|
|
|
275
309
|
| `silence(level = :fatal, &block)` | Temporarily raise log level for a block |
|
|
276
310
|
| `log_exception(exception, level: :error, **extra)` | Log exception details |
|
|
277
311
|
| `measure(event_name, **context) { block }` | Time a block, emit an info event with `duration_ms`, and re-raise on failure |
|
|
312
|
+
| `#with_tags(*tags) { block }` | Add tags to context for the block |
|
|
313
|
+
| `#measure_value(message) { block }` | Like #measure but returns the block's value |
|
|
278
314
|
| `add_output(io, level: nil, formatter: nil)` | Add an output destination at runtime |
|
|
279
315
|
| `with_correlation_id(id = nil, &block)` | Set a correlation ID for the block |
|
|
280
316
|
| `flush` | Force write of all buffered log entries |
|
|
@@ -50,6 +50,41 @@ module Philiprehberger
|
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# Adds the given tags to the logger's context under the `:tags`
|
|
54
|
+
# key, merging with any existing tags (de-duplicated, preserving
|
|
55
|
+
# insertion order). When a block is given, the previous context is
|
|
56
|
+
# restored when the block exits (even on exception). Without a
|
|
57
|
+
# block, the change persists like {#with_context}.
|
|
58
|
+
#
|
|
59
|
+
# @param tags [Array<String, Symbol>] one or more tags to add.
|
|
60
|
+
# @yield (optional) executes within the tagged context; the
|
|
61
|
+
# original context is restored on exit.
|
|
62
|
+
# @return [Object, Hash] the block's return value when a block is
|
|
63
|
+
# given, otherwise the new merged context hash.
|
|
64
|
+
#
|
|
65
|
+
# @example Block form
|
|
66
|
+
# logger.with_tags('auth', 'request') do
|
|
67
|
+
# logger.info('Login attempt')
|
|
68
|
+
# # entry includes tags: ['auth', 'request']
|
|
69
|
+
# end
|
|
70
|
+
def with_tags(*tags)
|
|
71
|
+
existing = @context[:tags] || []
|
|
72
|
+
merged_tags = (existing + tags).uniq
|
|
73
|
+
if block_given?
|
|
74
|
+
@monitor.synchronize do
|
|
75
|
+
original = @context
|
|
76
|
+
@context = @context.merge(tags: merged_tags).freeze
|
|
77
|
+
yield
|
|
78
|
+
ensure
|
|
79
|
+
@context = original
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
@monitor.synchronize do
|
|
83
|
+
@context = @context.merge(tags: merged_tags).freeze
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
53
88
|
def silence(temp_level = :fatal, &block)
|
|
54
89
|
@monitor.synchronize do
|
|
55
90
|
original = @level
|
|
@@ -111,6 +146,23 @@ module Philiprehberger
|
|
|
111
146
|
end
|
|
112
147
|
end
|
|
113
148
|
|
|
149
|
+
# Variant of {#measure} that emits the same timing log entry but
|
|
150
|
+
# also returns the block's return value. Captures and re-raises
|
|
151
|
+
# exceptions like {#measure}.
|
|
152
|
+
#
|
|
153
|
+
# @param event_name [String, Symbol] the event name to record as
|
|
154
|
+
# the `event` field in the log entry.
|
|
155
|
+
# @param context [Hash] extra context merged into the log entry.
|
|
156
|
+
# @yield executes the measured block.
|
|
157
|
+
# @return [Object] the block's return value on success.
|
|
158
|
+
# @raise re-raises any exception raised by the block.
|
|
159
|
+
#
|
|
160
|
+
# @example Capturing a query result
|
|
161
|
+
# result = logger.measure_value('db.query') { query_database }
|
|
162
|
+
def measure_value(event_name, **context, &)
|
|
163
|
+
measure(event_name, **context, &)
|
|
164
|
+
end
|
|
165
|
+
|
|
114
166
|
def flush
|
|
115
167
|
@monitor.synchronize { @outputs.each { |out| out[:io].flush if out[:io].respond_to?(:flush) } }
|
|
116
168
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: philiprehberger-structured_logger
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Philip Rehberger
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A zero-dependency Ruby gem for structured JSON logging with context merging,
|
|
14
14
|
child loggers, level filtering, and pluggable outputs.
|