activesupport-json_logging 1.2.0 → 1.2.1
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 +26 -31
- data/lib/json_logging/formatter_with_tags.rb +26 -11
- data/lib/json_logging/helpers.rb +11 -1
- data/lib/json_logging/json_logger_extension.rb +4 -2
- data/lib/json_logging/version.rb +1 -1
- metadata +117 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 879dfb3d0d8142a294407c70771d234e55d410032dbc50f035bf85f3bd33b79a
|
|
4
|
+
data.tar.gz: bfa9d0637d5e84f58acdf407ce782feda91b584c5c63700b93ec2aa4e6e59dd4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e4ed4ef5739e411af61e6186581ec30aa3f0653c557d7f2bc088abf264a3e8608c483b0790b892a7e1c10674d55811f95a5a3e4c33d073cd59949469e732e875
|
|
7
|
+
data.tar.gz: ec86db106814dee2731695159275fb7c56700d36564571edd72e54013d076dd1a3328a050eae06429d16eaaf1c0538404ae8345605d5a2ec63684ca1f71f40b7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 1.2.1 (2026-01-18)
|
|
4
|
+
|
|
5
|
+
- Refactor tag stack handling in JsonLogging formatter for improved maintainability
|
|
6
|
+
- Refactor timestamp handling in JsonLogging helpers to support Time.zone
|
|
7
|
+
- Add Ruby 4.0 support in gemspec and Appraisal configurations
|
|
8
|
+
|
|
3
9
|
## 1.2.0 (2025-11-07)
|
|
4
10
|
|
|
5
11
|
- Add support for service-specific tagged loggers: create loggers with permanent tags using `logger.tagged("service")` without a block
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# activesupport-json_logging
|
|
2
2
|
|
|
3
|
-
[](https://badge.fury.io/rb/activesupport-json_logging) [](https://github.com/amkisko/activesupport-json_logging.rb/actions/workflows/test.yml) [](https://codecov.io/gh/amkisko/activesupport-json_logging.rb)
|
|
3
|
+
[](https://badge.fury.io/rb/activesupport-json_logging) [](https://github.com/amkisko/activesupport-json_logging.rb/actions/workflows/test.yml) [](https://codecov.io/gh/amkisko/activesupport-json_logging.rb) [](https://sonarcloud.io/summary/new_code?id=amkisko_activesupport-json_logging.rb)
|
|
4
4
|
|
|
5
5
|
Structured JSON logging for Rails and ActiveSupport with a safe, single-line formatter.
|
|
6
6
|
No dependencies beyond Rails and Activesupport.
|
|
@@ -283,6 +283,8 @@ end
|
|
|
283
283
|
|
|
284
284
|
If you use Lograge, configure it to feed raw hashes and let this gem handle JSON formatting. This example shows a complete setup including all Rails component loggers and common third-party libraries:
|
|
285
285
|
|
|
286
|
+
**Important:** When using Lograge, `config.log_tags` does not work for adding fields to Lograge output. Instead, use `config.lograge.custom_options` to add custom fields to your request logs.
|
|
287
|
+
|
|
286
288
|
```ruby
|
|
287
289
|
# config/initializers/lograge.rb
|
|
288
290
|
# Note: require is optional in Rails apps (auto-loaded via Railtie)
|
|
@@ -295,8 +297,26 @@ Rails.application.configure do
|
|
|
295
297
|
config.lograge.formatter = Lograge::Formatters::Raw.new
|
|
296
298
|
config.lograge.keep_original_rails_log = ENV["DEBUG"] ? true : false
|
|
297
299
|
|
|
298
|
-
#
|
|
299
|
-
config.
|
|
300
|
+
# Add custom fields to Lograge output
|
|
301
|
+
# Note: config.log_tags does NOT work with Lograge - use custom_options instead
|
|
302
|
+
config.lograge.custom_options = ->(event) {
|
|
303
|
+
{
|
|
304
|
+
remote_ip: Current.remote_addr,
|
|
305
|
+
request_id: Current.request_id,
|
|
306
|
+
user_agent: Current.user_agent,
|
|
307
|
+
user_id: Current.user&.id
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
# Optionally merge additional context from JsonLogging.with_context
|
|
312
|
+
# config.lograge.custom_options = ->(event) {
|
|
313
|
+
# {
|
|
314
|
+
# remote_ip: Current.remote_addr,
|
|
315
|
+
# request_id: Current.request_id,
|
|
316
|
+
# user_agent: Current.user_agent,
|
|
317
|
+
# user_id: Current.user&.id
|
|
318
|
+
# }.merge(JsonLogging.additional_context)
|
|
319
|
+
# }
|
|
300
320
|
|
|
301
321
|
# Build unified JSON logger
|
|
302
322
|
logdev = Rails.env.production? ? Rails.root.join("log", "#{Rails.env}.log") : $stdout
|
|
@@ -306,7 +326,6 @@ Rails.application.configure do
|
|
|
306
326
|
|
|
307
327
|
# Set the main Rails logger
|
|
308
328
|
config.logger = json_logger
|
|
309
|
-
config.log_tags = [:request_id, :remote_ip]
|
|
310
329
|
|
|
311
330
|
# Override Rails.logger to ensure it uses our formatter
|
|
312
331
|
Rails.logger = json_logger
|
|
@@ -327,13 +346,6 @@ Rails.application.configure do
|
|
|
327
346
|
|
|
328
347
|
# Disable verbose enqueue logs to reduce noise
|
|
329
348
|
config.active_job.verbose_enqueue_logs = false
|
|
330
|
-
|
|
331
|
-
# Optional: Customize log tags based on request
|
|
332
|
-
# config.log_tags = [
|
|
333
|
-
# :request_id,
|
|
334
|
-
# ->(request) { request.remote_ip },
|
|
335
|
-
# ->(request) { request.subdomain }
|
|
336
|
-
# ]
|
|
337
349
|
end
|
|
338
350
|
```
|
|
339
351
|
|
|
@@ -594,27 +606,10 @@ The gem will automatically filter these from all log entries, including context
|
|
|
594
606
|
|
|
595
607
|
## Development
|
|
596
608
|
|
|
597
|
-
|
|
598
|
-
# Install dependencies
|
|
599
|
-
bundle install
|
|
600
|
-
bundle exec appraisal generate
|
|
601
|
-
|
|
602
|
-
# Run tests for current Rails version
|
|
603
|
-
bundle exec rspec
|
|
609
|
+
Run release.rb script to prepare code for publishing, it has all the required checks and tests.
|
|
604
610
|
|
|
605
|
-
|
|
606
|
-
bin/
|
|
607
|
-
|
|
608
|
-
# Run tests for specific Rails version
|
|
609
|
-
bin/appraisals rails-7.0
|
|
610
|
-
|
|
611
|
-
# Run tests for multiple versions
|
|
612
|
-
bin/appraisals rails-7.0 rails-8.0
|
|
613
|
-
|
|
614
|
-
# Or use appraisal directly
|
|
615
|
-
bundle exec appraisal rails-7.0 rspec
|
|
616
|
-
|
|
617
|
-
bundle exec standardrb --fix
|
|
611
|
+
```bash
|
|
612
|
+
usr/bin/release.rb
|
|
618
613
|
```
|
|
619
614
|
|
|
620
615
|
### Development: Using from Local Repository
|
|
@@ -10,8 +10,8 @@ module JsonLogging
|
|
|
10
10
|
def current_tags
|
|
11
11
|
# If LocalTagStorage is extended on this formatter, use its tag_stack
|
|
12
12
|
# This matches Rails' TaggedLogging behavior where tag_stack attribute shadows the method
|
|
13
|
-
if
|
|
14
|
-
|
|
13
|
+
if (stack = current_tag_stack)
|
|
14
|
+
stack.tags
|
|
15
15
|
else
|
|
16
16
|
@logger.send(:current_tags)
|
|
17
17
|
end
|
|
@@ -30,8 +30,8 @@ module JsonLogging
|
|
|
30
30
|
|
|
31
31
|
def push_tags(*tags)
|
|
32
32
|
# If LocalTagStorage is present, use it; otherwise use logger's thread-local storage
|
|
33
|
-
if
|
|
34
|
-
|
|
33
|
+
if (stack = current_tag_stack)
|
|
34
|
+
stack.push_tags(tags)
|
|
35
35
|
else
|
|
36
36
|
@logger.send(:push_tags, tags)
|
|
37
37
|
end
|
|
@@ -40,14 +40,12 @@ module JsonLogging
|
|
|
40
40
|
# Support tagged blocks for formatter
|
|
41
41
|
def tagged(*tags)
|
|
42
42
|
if block_given?
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
previous_count = tag_stack.tags.size
|
|
46
|
-
tag_stack.push_tags(tags)
|
|
43
|
+
if (stack = current_tag_stack)
|
|
44
|
+
pushed_count = stack.push_tags(tags).size
|
|
47
45
|
begin
|
|
48
46
|
yield @logger
|
|
49
47
|
ensure
|
|
50
|
-
|
|
48
|
+
stack.pop_tags(pushed_count)
|
|
51
49
|
end
|
|
52
50
|
else
|
|
53
51
|
previous = @logger.send(:current_tags).dup
|
|
@@ -59,8 +57,8 @@ module JsonLogging
|
|
|
59
57
|
end
|
|
60
58
|
end
|
|
61
59
|
else
|
|
62
|
-
if
|
|
63
|
-
|
|
60
|
+
if (stack = current_tag_stack)
|
|
61
|
+
stack.push_tags(tags)
|
|
64
62
|
else
|
|
65
63
|
@logger.send(:push_tags, tags)
|
|
66
64
|
end
|
|
@@ -70,6 +68,23 @@ module JsonLogging
|
|
|
70
68
|
|
|
71
69
|
private
|
|
72
70
|
|
|
71
|
+
# Returns the current tag_stack to use, checking in order:
|
|
72
|
+
# 1. This formatter's tag_stack (if LocalTagStorage is extended)
|
|
73
|
+
# 2. Logger's formatter's tag_stack (if it has LocalTagStorage)
|
|
74
|
+
# 3. nil (fall back to thread-local storage)
|
|
75
|
+
def current_tag_stack
|
|
76
|
+
if respond_to?(:tag_stack, true) && instance_variable_defined?(:@tag_stack)
|
|
77
|
+
tag_stack
|
|
78
|
+
elsif logger_formatter_has_tag_stack?
|
|
79
|
+
@logger.formatter.tag_stack
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def logger_formatter_has_tag_stack?
|
|
84
|
+
@logger.formatter.respond_to?(:tag_stack, true) &&
|
|
85
|
+
@logger.formatter.instance_variable_defined?(:@tag_stack)
|
|
86
|
+
end
|
|
87
|
+
|
|
73
88
|
def build_fallback_output(severity, timestamp, msg, error)
|
|
74
89
|
timestamp_str = Helpers.normalize_timestamp(timestamp)
|
|
75
90
|
fallback_payload = {
|
data/lib/json_logging/helpers.rb
CHANGED
|
@@ -4,7 +4,17 @@ module JsonLogging
|
|
|
4
4
|
|
|
5
5
|
# Normalize timestamp to ISO8601 with microseconds
|
|
6
6
|
def normalize_timestamp(timestamp)
|
|
7
|
-
|
|
7
|
+
time = timestamp || current_time
|
|
8
|
+
time.utc.iso8601(6)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Get current time, using Time.zone if available, otherwise Time.now
|
|
12
|
+
def current_time
|
|
13
|
+
if defined?(Time.zone) && Time.zone
|
|
14
|
+
Time.zone.now
|
|
15
|
+
else
|
|
16
|
+
Time.now
|
|
17
|
+
end
|
|
8
18
|
end
|
|
9
19
|
|
|
10
20
|
# Safely convert object to string, never raises
|
|
@@ -50,7 +50,7 @@ module JsonLogging
|
|
|
50
50
|
msg ||= "<uninitialized>"
|
|
51
51
|
|
|
52
52
|
fallback = {
|
|
53
|
-
timestamp: Helpers.normalize_timestamp(
|
|
53
|
+
timestamp: Helpers.normalize_timestamp(Helpers.current_time),
|
|
54
54
|
severity: severity_name(severity),
|
|
55
55
|
message: Sanitizer.sanitize_string(Helpers.safe_string(msg)),
|
|
56
56
|
logger_error: {
|
|
@@ -129,7 +129,7 @@ module JsonLogging
|
|
|
129
129
|
payload = PayloadBuilder.build_base_payload(
|
|
130
130
|
msg,
|
|
131
131
|
severity: severity_name(severity),
|
|
132
|
-
timestamp: Helpers.normalize_timestamp(
|
|
132
|
+
timestamp: Helpers.normalize_timestamp(Helpers.current_time)
|
|
133
133
|
)
|
|
134
134
|
payload = PayloadBuilder.merge_context(
|
|
135
135
|
payload,
|
|
@@ -186,6 +186,8 @@ module JsonLogging
|
|
|
186
186
|
end
|
|
187
187
|
|
|
188
188
|
def pop_tags(count = 1)
|
|
189
|
+
return [] if count <= 0
|
|
190
|
+
|
|
189
191
|
@tags.pop(count)
|
|
190
192
|
end
|
|
191
193
|
|
data/lib/json_logging/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activesupport-json_logging
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activesupport
|
|
@@ -140,14 +139,112 @@ dependencies:
|
|
|
140
139
|
requirements:
|
|
141
140
|
- - "~>"
|
|
142
141
|
- !ruby/object:Gem::Version
|
|
143
|
-
version: '1'
|
|
142
|
+
version: '1.52'
|
|
144
143
|
type: :development
|
|
145
144
|
prerelease: false
|
|
146
145
|
version_requirements: !ruby/object:Gem::Requirement
|
|
147
146
|
requirements:
|
|
148
147
|
- - "~>"
|
|
149
148
|
- !ruby/object:Gem::Version
|
|
150
|
-
version: '1'
|
|
149
|
+
version: '1.52'
|
|
150
|
+
- !ruby/object:Gem::Dependency
|
|
151
|
+
name: standard-custom
|
|
152
|
+
requirement: !ruby/object:Gem::Requirement
|
|
153
|
+
requirements:
|
|
154
|
+
- - "~>"
|
|
155
|
+
- !ruby/object:Gem::Version
|
|
156
|
+
version: '1.0'
|
|
157
|
+
type: :development
|
|
158
|
+
prerelease: false
|
|
159
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
160
|
+
requirements:
|
|
161
|
+
- - "~>"
|
|
162
|
+
- !ruby/object:Gem::Version
|
|
163
|
+
version: '1.0'
|
|
164
|
+
- !ruby/object:Gem::Dependency
|
|
165
|
+
name: standard-performance
|
|
166
|
+
requirement: !ruby/object:Gem::Requirement
|
|
167
|
+
requirements:
|
|
168
|
+
- - "~>"
|
|
169
|
+
- !ruby/object:Gem::Version
|
|
170
|
+
version: '1.8'
|
|
171
|
+
type: :development
|
|
172
|
+
prerelease: false
|
|
173
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
174
|
+
requirements:
|
|
175
|
+
- - "~>"
|
|
176
|
+
- !ruby/object:Gem::Version
|
|
177
|
+
version: '1.8'
|
|
178
|
+
- !ruby/object:Gem::Dependency
|
|
179
|
+
name: standard-rails
|
|
180
|
+
requirement: !ruby/object:Gem::Requirement
|
|
181
|
+
requirements:
|
|
182
|
+
- - "~>"
|
|
183
|
+
- !ruby/object:Gem::Version
|
|
184
|
+
version: '1.5'
|
|
185
|
+
type: :development
|
|
186
|
+
prerelease: false
|
|
187
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
188
|
+
requirements:
|
|
189
|
+
- - "~>"
|
|
190
|
+
- !ruby/object:Gem::Version
|
|
191
|
+
version: '1.5'
|
|
192
|
+
- !ruby/object:Gem::Dependency
|
|
193
|
+
name: standard-rspec
|
|
194
|
+
requirement: !ruby/object:Gem::Requirement
|
|
195
|
+
requirements:
|
|
196
|
+
- - "~>"
|
|
197
|
+
- !ruby/object:Gem::Version
|
|
198
|
+
version: '0.3'
|
|
199
|
+
type: :development
|
|
200
|
+
prerelease: false
|
|
201
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
202
|
+
requirements:
|
|
203
|
+
- - "~>"
|
|
204
|
+
- !ruby/object:Gem::Version
|
|
205
|
+
version: '0.3'
|
|
206
|
+
- !ruby/object:Gem::Dependency
|
|
207
|
+
name: rubocop-rails
|
|
208
|
+
requirement: !ruby/object:Gem::Requirement
|
|
209
|
+
requirements:
|
|
210
|
+
- - "~>"
|
|
211
|
+
- !ruby/object:Gem::Version
|
|
212
|
+
version: '2.33'
|
|
213
|
+
type: :development
|
|
214
|
+
prerelease: false
|
|
215
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
216
|
+
requirements:
|
|
217
|
+
- - "~>"
|
|
218
|
+
- !ruby/object:Gem::Version
|
|
219
|
+
version: '2.33'
|
|
220
|
+
- !ruby/object:Gem::Dependency
|
|
221
|
+
name: rubocop-rspec
|
|
222
|
+
requirement: !ruby/object:Gem::Requirement
|
|
223
|
+
requirements:
|
|
224
|
+
- - "~>"
|
|
225
|
+
- !ruby/object:Gem::Version
|
|
226
|
+
version: '3.8'
|
|
227
|
+
type: :development
|
|
228
|
+
prerelease: false
|
|
229
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
230
|
+
requirements:
|
|
231
|
+
- - "~>"
|
|
232
|
+
- !ruby/object:Gem::Version
|
|
233
|
+
version: '3.8'
|
|
234
|
+
- !ruby/object:Gem::Dependency
|
|
235
|
+
name: rubocop-thread_safety
|
|
236
|
+
requirement: !ruby/object:Gem::Requirement
|
|
237
|
+
requirements:
|
|
238
|
+
- - "~>"
|
|
239
|
+
- !ruby/object:Gem::Version
|
|
240
|
+
version: '0.7'
|
|
241
|
+
type: :development
|
|
242
|
+
prerelease: false
|
|
243
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
244
|
+
requirements:
|
|
245
|
+
- - "~>"
|
|
246
|
+
- !ruby/object:Gem::Version
|
|
247
|
+
version: '0.7'
|
|
151
248
|
- !ruby/object:Gem::Dependency
|
|
152
249
|
name: appraisal
|
|
153
250
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -190,6 +287,20 @@ dependencies:
|
|
|
190
287
|
- - "~>"
|
|
191
288
|
- !ruby/object:Gem::Version
|
|
192
289
|
version: '3'
|
|
290
|
+
- !ruby/object:Gem::Dependency
|
|
291
|
+
name: benchmark
|
|
292
|
+
requirement: !ruby/object:Gem::Requirement
|
|
293
|
+
requirements:
|
|
294
|
+
- - "~>"
|
|
295
|
+
- !ruby/object:Gem::Version
|
|
296
|
+
version: '0.5'
|
|
297
|
+
type: :development
|
|
298
|
+
prerelease: false
|
|
299
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
300
|
+
requirements:
|
|
301
|
+
- - "~>"
|
|
302
|
+
- !ruby/object:Gem::Version
|
|
303
|
+
version: '0.5'
|
|
193
304
|
description: Lightweight JSON logger and formatter integrating with Rails/ActiveSupport.
|
|
194
305
|
No extra deps beyond Rails/Activesupport. Compatible with Rails 6–8.
|
|
195
306
|
email:
|
|
@@ -220,7 +331,6 @@ metadata:
|
|
|
220
331
|
source_code_uri: https://github.com/amkisko/activesupport-json_logging.rb
|
|
221
332
|
changelog_uri: https://github.com/amkisko/activesupport-json_logging.rb/blob/main/CHANGELOG.md
|
|
222
333
|
bug_tracker_uri: https://github.com/amkisko/activesupport-json_logging.rb/issues
|
|
223
|
-
post_install_message:
|
|
224
334
|
rdoc_options: []
|
|
225
335
|
require_paths:
|
|
226
336
|
- lib
|
|
@@ -235,8 +345,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
235
345
|
- !ruby/object:Gem::Version
|
|
236
346
|
version: '0'
|
|
237
347
|
requirements: []
|
|
238
|
-
rubygems_version:
|
|
239
|
-
signing_key:
|
|
348
|
+
rubygems_version: 4.0.3
|
|
240
349
|
specification_version: 4
|
|
241
350
|
summary: Structured JSON logging for Rails/ActiveSupport with safe, single-line entries.
|
|
242
351
|
test_files: []
|