activesupport-json_logging 1.1.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 +13 -0
- data/README.md +121 -31
- data/lib/json_logging/formatter_with_tags.rb +53 -8
- data/lib/json_logging/helpers.rb +11 -1
- data/lib/json_logging/json_logger_extension.rb +33 -11
- data/lib/json_logging/version.rb +1 -1
- metadata +154 -17
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,18 @@
|
|
|
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
|
+
|
|
9
|
+
## 1.2.0 (2025-11-07)
|
|
10
|
+
|
|
11
|
+
- Add support for service-specific tagged loggers: create loggers with permanent tags using `logger.tagged("service")` without a block
|
|
12
|
+
- Improve BroadcastLogger compatibility: service-specific loggers work seamlessly with `ActiveSupport::BroadcastLogger`
|
|
13
|
+
- Fix LocalTagStorage implementation to match Rails' TaggedLogging behavior: use `tag_stack` attribute accessor pattern for proper tag isolation
|
|
14
|
+
- Add comprehensive examples in README for service-specific loggers and BroadcastLogger integration
|
|
15
|
+
|
|
3
16
|
## 1.1.0 (2025-11-04)
|
|
4
17
|
|
|
5
18
|
- Move tags to root level of JSON payload instead of nested in context (breaking change: tags now at `payload["tags"]` instead of `payload["context"]["tags"]`)
|
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://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.
|
|
@@ -8,6 +8,10 @@ Supports Rails versions from 6 to 8.
|
|
|
8
8
|
|
|
9
9
|
Sponsored by [Kisko Labs](https://www.kiskolabs.com).
|
|
10
10
|
|
|
11
|
+
<a href="https://www.kiskolabs.com">
|
|
12
|
+
<img src="kisko.svg" width="200" alt="Sponsored by Kisko Labs" />
|
|
13
|
+
</a>
|
|
14
|
+
|
|
11
15
|
|
|
12
16
|
## Installation
|
|
13
17
|
|
|
@@ -40,6 +44,8 @@ end
|
|
|
40
44
|
- `JsonLogging.with_context` to attach contextual fields per-thread
|
|
41
45
|
- Smart message parsing (handles hashes, JSON strings, plain strings, and Exception objects)
|
|
42
46
|
- Native `tagged` method support - use it just like Rails' tagged logger
|
|
47
|
+
- Service-specific tagged loggers - create loggers with permanent tags using `logger.tagged("service")` without a block
|
|
48
|
+
- Full compatibility with `ActiveSupport::BroadcastLogger` (Rails 7.1+)
|
|
43
49
|
- Automatic Rails integration via Railtie (auto-requires the gem in Rails apps)
|
|
44
50
|
|
|
45
51
|
## Basic usage
|
|
@@ -63,6 +69,17 @@ logger.tagged("BCX").info("Stuff")
|
|
|
63
69
|
logger.tagged("BCX", "Jason").info("Stuff")
|
|
64
70
|
logger.tagged("BCX").tagged("Jason").info("Stuff")
|
|
65
71
|
|
|
72
|
+
# Create a service-specific logger with permanent tags
|
|
73
|
+
# All logs from this logger will include the "dotenv" tag
|
|
74
|
+
dotenv_logger = logger.tagged("dotenv")
|
|
75
|
+
dotenv_logger.info("Loading environment variables") # Includes "dotenv" tag
|
|
76
|
+
dotenv_logger.warn("Missing .env file") # Includes "dotenv" tag
|
|
77
|
+
|
|
78
|
+
# You can also create service loggers directly
|
|
79
|
+
base_logger = JsonLogging.logger($stdout)
|
|
80
|
+
service_logger = base_logger.tagged("my-service")
|
|
81
|
+
service_logger.info("Service started") # All logs tagged with "my-service"
|
|
82
|
+
|
|
66
83
|
# Add context
|
|
67
84
|
JsonLogging.with_context(user_id: 123) do
|
|
68
85
|
logger.warn({event: "slow_query", duration_ms: 250})
|
|
@@ -85,6 +102,84 @@ This gem does **not** automatically configure your Rails app. You set it up manu
|
|
|
85
102
|
- In Rails 7.1+, Rails automatically wraps your logger in `ActiveSupport::BroadcastLogger` to enable writing to multiple destinations (e.g., STDOUT and file simultaneously). This works seamlessly with our logger - your JSON logger will be wrapped and all method calls will delegate correctly. No special handling needed.
|
|
86
103
|
- In Rails 7.1+, tag storage uses `ActiveSupport::IsolatedExecutionState` for improved thread/Fiber safety.
|
|
87
104
|
|
|
105
|
+
### Service-specific loggers with tags
|
|
106
|
+
|
|
107
|
+
You can create loggers with permanent tags for specific services or components. This is useful when you want all logs from a particular service to be tagged consistently:
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
# Create a logger for DotEnv service with "dotenv" tag
|
|
111
|
+
base_logger = JsonLogging.logger($stdout)
|
|
112
|
+
dotenv_logger = base_logger.tagged("dotenv")
|
|
113
|
+
|
|
114
|
+
# All logs from this logger will include the "dotenv" tag
|
|
115
|
+
dotenv_logger.info("Loading .env file")
|
|
116
|
+
dotenv_logger.warn("Missing .env.local file")
|
|
117
|
+
dotenv_logger.error("Invalid environment variable format")
|
|
118
|
+
|
|
119
|
+
# Example: Configure Dotenv::Rails to use tagged logger
|
|
120
|
+
if defined?(Dotenv::Rails)
|
|
121
|
+
Dotenv::Rails.logger = base_logger.tagged("dotenv")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Example: Create multiple service loggers
|
|
125
|
+
redis_logger = base_logger.tagged("redis")
|
|
126
|
+
sidekiq_logger = base_logger.tagged("sidekiq")
|
|
127
|
+
api_logger = base_logger.tagged("api")
|
|
128
|
+
|
|
129
|
+
# Each service logger maintains its tag across all log calls
|
|
130
|
+
redis_logger.info("Connected to Redis") # Tagged with "redis"
|
|
131
|
+
sidekiq_logger.info("Job enqueued") # Tagged with "sidekiq"
|
|
132
|
+
api_logger.info("Request received") # Tagged with "api"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### BroadcastLogger integration
|
|
136
|
+
|
|
137
|
+
`ActiveSupport::BroadcastLogger` (Rails 7.1+) allows writing logs to multiple destinations simultaneously. `JsonLogging` works seamlessly with `BroadcastLogger`:
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
# Create JSON loggers for different destinations
|
|
141
|
+
stdout_logger = JsonLogging.logger($stdout)
|
|
142
|
+
file_logger = JsonLogging.logger(Rails.root.join("log", "production.log"))
|
|
143
|
+
|
|
144
|
+
# Wrap in BroadcastLogger to write to both destinations
|
|
145
|
+
broadcast_logger = ActiveSupport::BroadcastLogger.new(stdout_logger)
|
|
146
|
+
broadcast_logger.broadcast_to(file_logger)
|
|
147
|
+
|
|
148
|
+
# All logging methods work through BroadcastLogger
|
|
149
|
+
broadcast_logger.info("This goes to both STDOUT and file")
|
|
150
|
+
broadcast_logger.warn({event: "warning", message: "Something happened"})
|
|
151
|
+
|
|
152
|
+
# Tagged logging works through BroadcastLogger
|
|
153
|
+
broadcast_logger.tagged("REQUEST", request_id) do
|
|
154
|
+
broadcast_logger.info("Processing request") # Tagged logs go to both destinations
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Service-specific loggers work with BroadcastLogger
|
|
158
|
+
# Note: Create service logger from underlying logger, then wrap in BroadcastLogger
|
|
159
|
+
# (BroadcastLogger.tagged without block returns array due to delegation)
|
|
160
|
+
base_logger = JsonLogging.logger($stdout)
|
|
161
|
+
dotenv_logger = base_logger.tagged("dotenv")
|
|
162
|
+
dotenv_broadcast = ActiveSupport::BroadcastLogger.new(dotenv_logger)
|
|
163
|
+
dotenv_broadcast.broadcast_to(file_logger.tagged("dotenv")) # Tag second destination too
|
|
164
|
+
dotenv_broadcast.info("Environment loaded") # Tagged and broadcast to all destinations
|
|
165
|
+
|
|
166
|
+
# Rails 7.1+ automatically uses BroadcastLogger
|
|
167
|
+
# Your configuration can be simplified:
|
|
168
|
+
Rails.application.configure do
|
|
169
|
+
# Rails will automatically wrap this in BroadcastLogger
|
|
170
|
+
base_logger = ActiveSupport::Logger.new($stdout)
|
|
171
|
+
json_logger = JsonLogging.new(base_logger)
|
|
172
|
+
config.logger = json_logger # Rails wraps this in BroadcastLogger automatically
|
|
173
|
+
end
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Key points:**
|
|
177
|
+
- All logger methods (`info`, `warn`, `error`, etc.) work through `BroadcastLogger`
|
|
178
|
+
- Tagged logging (`tagged`) works correctly through `BroadcastLogger`
|
|
179
|
+
- Service-specific tagged loggers work with `BroadcastLogger`
|
|
180
|
+
- Each destination receives properly formatted JSON logs
|
|
181
|
+
- No special configuration needed - just wrap your `JsonLogging` logger in `BroadcastLogger`
|
|
182
|
+
|
|
88
183
|
### Basic setup
|
|
89
184
|
|
|
90
185
|
Create `config/initializers/json_logging.rb`:
|
|
@@ -188,6 +283,8 @@ end
|
|
|
188
283
|
|
|
189
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:
|
|
190
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
|
+
|
|
191
288
|
```ruby
|
|
192
289
|
# config/initializers/lograge.rb
|
|
193
290
|
# Note: require is optional in Rails apps (auto-loaded via Railtie)
|
|
@@ -200,8 +297,26 @@ Rails.application.configure do
|
|
|
200
297
|
config.lograge.formatter = Lograge::Formatters::Raw.new
|
|
201
298
|
config.lograge.keep_original_rails_log = ENV["DEBUG"] ? true : false
|
|
202
299
|
|
|
203
|
-
#
|
|
204
|
-
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
|
+
# }
|
|
205
320
|
|
|
206
321
|
# Build unified JSON logger
|
|
207
322
|
logdev = Rails.env.production? ? Rails.root.join("log", "#{Rails.env}.log") : $stdout
|
|
@@ -211,7 +326,6 @@ Rails.application.configure do
|
|
|
211
326
|
|
|
212
327
|
# Set the main Rails logger
|
|
213
328
|
config.logger = json_logger
|
|
214
|
-
config.log_tags = [:request_id, :remote_ip]
|
|
215
329
|
|
|
216
330
|
# Override Rails.logger to ensure it uses our formatter
|
|
217
331
|
Rails.logger = json_logger
|
|
@@ -232,13 +346,6 @@ Rails.application.configure do
|
|
|
232
346
|
|
|
233
347
|
# Disable verbose enqueue logs to reduce noise
|
|
234
348
|
config.active_job.verbose_enqueue_logs = false
|
|
235
|
-
|
|
236
|
-
# Optional: Customize log tags based on request
|
|
237
|
-
# config.log_tags = [
|
|
238
|
-
# :request_id,
|
|
239
|
-
# ->(request) { request.remote_ip },
|
|
240
|
-
# ->(request) { request.subdomain }
|
|
241
|
-
# ]
|
|
242
349
|
end
|
|
243
350
|
```
|
|
244
351
|
|
|
@@ -499,27 +606,10 @@ The gem will automatically filter these from all log entries, including context
|
|
|
499
606
|
|
|
500
607
|
## Development
|
|
501
608
|
|
|
502
|
-
|
|
503
|
-
# Install dependencies
|
|
504
|
-
bundle install
|
|
505
|
-
bundle exec appraisal install
|
|
506
|
-
|
|
507
|
-
# Run tests for current Rails version
|
|
508
|
-
bundle exec rspec
|
|
509
|
-
|
|
510
|
-
# Run tests for all Rails versions (6.0, 6.1, 7.0, 7.1, 7.2, 8.0)
|
|
511
|
-
bin/appraisals
|
|
609
|
+
Run release.rb script to prepare code for publishing, it has all the required checks and tests.
|
|
512
610
|
|
|
513
|
-
|
|
514
|
-
bin/
|
|
515
|
-
|
|
516
|
-
# Run tests for multiple versions
|
|
517
|
-
bin/appraisals rails-7.0 rails-8.0
|
|
518
|
-
|
|
519
|
-
# Or use appraisal directly
|
|
520
|
-
bundle exec appraisal rails-7.0 rspec
|
|
521
|
-
|
|
522
|
-
bundle exec standardrb --fix
|
|
611
|
+
```bash
|
|
612
|
+
usr/bin/release.rb
|
|
523
613
|
```
|
|
524
614
|
|
|
525
615
|
### Development: Using from Local Repository
|
|
@@ -8,7 +8,13 @@ module JsonLogging
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def current_tags
|
|
11
|
-
|
|
11
|
+
# If LocalTagStorage is extended on this formatter, use its tag_stack
|
|
12
|
+
# This matches Rails' TaggedLogging behavior where tag_stack attribute shadows the method
|
|
13
|
+
if (stack = current_tag_stack)
|
|
14
|
+
stack.tags
|
|
15
|
+
else
|
|
16
|
+
@logger.send(:current_tags)
|
|
17
|
+
end
|
|
12
18
|
end
|
|
13
19
|
|
|
14
20
|
def call(severity, timestamp, progname, msg)
|
|
@@ -22,24 +28,63 @@ module JsonLogging
|
|
|
22
28
|
build_fallback_output(severity, timestamp, msg, e)
|
|
23
29
|
end
|
|
24
30
|
|
|
31
|
+
def push_tags(*tags)
|
|
32
|
+
# If LocalTagStorage is present, use it; otherwise use logger's thread-local storage
|
|
33
|
+
if (stack = current_tag_stack)
|
|
34
|
+
stack.push_tags(tags)
|
|
35
|
+
else
|
|
36
|
+
@logger.send(:push_tags, tags)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
25
40
|
# Support tagged blocks for formatter
|
|
26
41
|
def tagged(*tags)
|
|
27
42
|
if block_given?
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
if (stack = current_tag_stack)
|
|
44
|
+
pushed_count = stack.push_tags(tags).size
|
|
45
|
+
begin
|
|
46
|
+
yield @logger
|
|
47
|
+
ensure
|
|
48
|
+
stack.pop_tags(pushed_count)
|
|
49
|
+
end
|
|
50
|
+
else
|
|
51
|
+
previous = @logger.send(:current_tags).dup
|
|
52
|
+
@logger.send(:push_tags, tags)
|
|
53
|
+
begin
|
|
54
|
+
yield @logger
|
|
55
|
+
ensure
|
|
56
|
+
@logger.send(:set_tags, previous)
|
|
57
|
+
end
|
|
34
58
|
end
|
|
35
59
|
else
|
|
36
|
-
|
|
60
|
+
if (stack = current_tag_stack)
|
|
61
|
+
stack.push_tags(tags)
|
|
62
|
+
else
|
|
63
|
+
@logger.send(:push_tags, tags)
|
|
64
|
+
end
|
|
37
65
|
self
|
|
38
66
|
end
|
|
39
67
|
end
|
|
40
68
|
|
|
41
69
|
private
|
|
42
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
|
+
|
|
43
88
|
def build_fallback_output(severity, timestamp, msg, error)
|
|
44
89
|
timestamp_str = Helpers.normalize_timestamp(timestamp)
|
|
45
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: {
|
|
@@ -75,7 +75,9 @@ module JsonLogging
|
|
|
75
75
|
# Return a new wrapped logger with tags applied (similar to TaggedLogging)
|
|
76
76
|
logger = JsonLogging.new(self)
|
|
77
77
|
# Extend formatter with LocalTagStorage to preserve current tags when creating nested loggers
|
|
78
|
+
# This matches Rails' TaggedLogging behavior
|
|
78
79
|
logger.formatter.extend(LocalTagStorage)
|
|
80
|
+
# Push tags through formatter (matches Rails delegation pattern)
|
|
79
81
|
logger.formatter.push_tags(*formatter.current_tags, *tags)
|
|
80
82
|
logger
|
|
81
83
|
end
|
|
@@ -127,12 +129,12 @@ module JsonLogging
|
|
|
127
129
|
payload = PayloadBuilder.build_base_payload(
|
|
128
130
|
msg,
|
|
129
131
|
severity: severity_name(severity),
|
|
130
|
-
timestamp: Helpers.normalize_timestamp(
|
|
132
|
+
timestamp: Helpers.normalize_timestamp(Helpers.current_time)
|
|
131
133
|
)
|
|
132
134
|
payload = PayloadBuilder.merge_context(
|
|
133
135
|
payload,
|
|
134
136
|
additional_context: JsonLogging.additional_context.compact,
|
|
135
|
-
tags: current_tags
|
|
137
|
+
tags: formatter.current_tags
|
|
136
138
|
)
|
|
137
139
|
|
|
138
140
|
payload.compact
|
|
@@ -159,19 +161,39 @@ module JsonLogging
|
|
|
159
161
|
# Module for preserving current tags when creating nested tagged loggers
|
|
160
162
|
# Similar to ActiveSupport::TaggedLogging::LocalTagStorage
|
|
161
163
|
# When extended on a formatter, stores tags locally instead of using thread-local storage
|
|
164
|
+
# Uses tag_stack attribute accessor pattern to match Rails' TaggedLogging behavior
|
|
162
165
|
module LocalTagStorage
|
|
166
|
+
attr_accessor :tag_stack
|
|
167
|
+
|
|
163
168
|
def self.extended(base)
|
|
164
|
-
base.
|
|
169
|
+
base.tag_stack = LocalTagStack.new
|
|
165
170
|
end
|
|
166
171
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
end
|
|
172
|
+
# Simple tag stack implementation for local tag storage
|
|
173
|
+
# Similar to ActiveSupport::TaggedLogging::TagStack but simplified for JSON logging
|
|
174
|
+
class LocalTagStack
|
|
175
|
+
attr_reader :tags
|
|
172
176
|
|
|
173
|
-
|
|
174
|
-
|
|
177
|
+
def initialize
|
|
178
|
+
@tags = []
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def push_tags(tags)
|
|
182
|
+
flat = Array(tags).flatten.compact.map(&:to_s).reject(&:empty?)
|
|
183
|
+
return [] if flat.empty?
|
|
184
|
+
@tags.concat(flat)
|
|
185
|
+
flat
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def pop_tags(count = 1)
|
|
189
|
+
return [] if count <= 0
|
|
190
|
+
|
|
191
|
+
@tags.pop(count)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def clear
|
|
195
|
+
@tags.clear
|
|
196
|
+
end
|
|
175
197
|
end
|
|
176
198
|
end
|
|
177
199
|
end
|
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.1
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
8
|
-
autorequire:
|
|
7
|
+
- Andrei Makarov
|
|
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
|
|
@@ -56,42 +55,56 @@ dependencies:
|
|
|
56
55
|
requirements:
|
|
57
56
|
- - "~>"
|
|
58
57
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: '3
|
|
58
|
+
version: '3'
|
|
60
59
|
type: :development
|
|
61
60
|
prerelease: false
|
|
62
61
|
version_requirements: !ruby/object:Gem::Requirement
|
|
63
62
|
requirements:
|
|
64
63
|
- - "~>"
|
|
65
64
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: '3
|
|
65
|
+
version: '3'
|
|
66
|
+
- !ruby/object:Gem::Dependency
|
|
67
|
+
name: webmock
|
|
68
|
+
requirement: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - "~>"
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '3'
|
|
73
|
+
type: :development
|
|
74
|
+
prerelease: false
|
|
75
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
76
|
+
requirements:
|
|
77
|
+
- - "~>"
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '3'
|
|
67
80
|
- !ruby/object:Gem::Dependency
|
|
68
81
|
name: rake
|
|
69
82
|
requirement: !ruby/object:Gem::Requirement
|
|
70
83
|
requirements:
|
|
71
84
|
- - "~>"
|
|
72
85
|
- !ruby/object:Gem::Version
|
|
73
|
-
version: '13
|
|
86
|
+
version: '13'
|
|
74
87
|
type: :development
|
|
75
88
|
prerelease: false
|
|
76
89
|
version_requirements: !ruby/object:Gem::Requirement
|
|
77
90
|
requirements:
|
|
78
91
|
- - "~>"
|
|
79
92
|
- !ruby/object:Gem::Version
|
|
80
|
-
version: '13
|
|
93
|
+
version: '13'
|
|
81
94
|
- !ruby/object:Gem::Dependency
|
|
82
95
|
name: simplecov
|
|
83
96
|
requirement: !ruby/object:Gem::Requirement
|
|
84
97
|
requirements:
|
|
85
98
|
- - "~>"
|
|
86
99
|
- !ruby/object:Gem::Version
|
|
87
|
-
version: '0.
|
|
100
|
+
version: '0.22'
|
|
88
101
|
type: :development
|
|
89
102
|
prerelease: false
|
|
90
103
|
version_requirements: !ruby/object:Gem::Requirement
|
|
91
104
|
requirements:
|
|
92
105
|
- - "~>"
|
|
93
106
|
- !ruby/object:Gem::Version
|
|
94
|
-
version: '0.
|
|
107
|
+
version: '0.22'
|
|
95
108
|
- !ruby/object:Gem::Dependency
|
|
96
109
|
name: rspec_junit_formatter
|
|
97
110
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -122,6 +135,20 @@ dependencies:
|
|
|
122
135
|
version: '3'
|
|
123
136
|
- !ruby/object:Gem::Dependency
|
|
124
137
|
name: standard
|
|
138
|
+
requirement: !ruby/object:Gem::Requirement
|
|
139
|
+
requirements:
|
|
140
|
+
- - "~>"
|
|
141
|
+
- !ruby/object:Gem::Version
|
|
142
|
+
version: '1.52'
|
|
143
|
+
type: :development
|
|
144
|
+
prerelease: false
|
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
146
|
+
requirements:
|
|
147
|
+
- - "~>"
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: '1.52'
|
|
150
|
+
- !ruby/object:Gem::Dependency
|
|
151
|
+
name: standard-custom
|
|
125
152
|
requirement: !ruby/object:Gem::Requirement
|
|
126
153
|
requirements:
|
|
127
154
|
- - "~>"
|
|
@@ -134,34 +161,146 @@ dependencies:
|
|
|
134
161
|
- - "~>"
|
|
135
162
|
- !ruby/object:Gem::Version
|
|
136
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'
|
|
137
248
|
- !ruby/object:Gem::Dependency
|
|
138
249
|
name: appraisal
|
|
139
250
|
requirement: !ruby/object:Gem::Requirement
|
|
140
251
|
requirements:
|
|
141
252
|
- - "~>"
|
|
142
253
|
- !ruby/object:Gem::Version
|
|
143
|
-
version: '2
|
|
254
|
+
version: '2'
|
|
144
255
|
type: :development
|
|
145
256
|
prerelease: false
|
|
146
257
|
version_requirements: !ruby/object:Gem::Requirement
|
|
147
258
|
requirements:
|
|
148
259
|
- - "~>"
|
|
149
260
|
- !ruby/object:Gem::Version
|
|
150
|
-
version: '2
|
|
261
|
+
version: '2'
|
|
151
262
|
- !ruby/object:Gem::Dependency
|
|
152
263
|
name: memory_profiler
|
|
153
264
|
requirement: !ruby/object:Gem::Requirement
|
|
154
265
|
requirements:
|
|
155
266
|
- - "~>"
|
|
156
267
|
- !ruby/object:Gem::Version
|
|
157
|
-
version: '1
|
|
268
|
+
version: '1'
|
|
158
269
|
type: :development
|
|
159
270
|
prerelease: false
|
|
160
271
|
version_requirements: !ruby/object:Gem::Requirement
|
|
161
272
|
requirements:
|
|
162
273
|
- - "~>"
|
|
163
274
|
- !ruby/object:Gem::Version
|
|
164
|
-
version: '1
|
|
275
|
+
version: '1'
|
|
276
|
+
- !ruby/object:Gem::Dependency
|
|
277
|
+
name: rbs
|
|
278
|
+
requirement: !ruby/object:Gem::Requirement
|
|
279
|
+
requirements:
|
|
280
|
+
- - "~>"
|
|
281
|
+
- !ruby/object:Gem::Version
|
|
282
|
+
version: '3'
|
|
283
|
+
type: :development
|
|
284
|
+
prerelease: false
|
|
285
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
286
|
+
requirements:
|
|
287
|
+
- - "~>"
|
|
288
|
+
- !ruby/object:Gem::Version
|
|
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'
|
|
165
304
|
description: Lightweight JSON logger and formatter integrating with Rails/ActiveSupport.
|
|
166
305
|
No extra deps beyond Rails/Activesupport. Compatible with Rails 6–8.
|
|
167
306
|
email:
|
|
@@ -192,7 +331,6 @@ metadata:
|
|
|
192
331
|
source_code_uri: https://github.com/amkisko/activesupport-json_logging.rb
|
|
193
332
|
changelog_uri: https://github.com/amkisko/activesupport-json_logging.rb/blob/main/CHANGELOG.md
|
|
194
333
|
bug_tracker_uri: https://github.com/amkisko/activesupport-json_logging.rb/issues
|
|
195
|
-
post_install_message:
|
|
196
334
|
rdoc_options: []
|
|
197
335
|
require_paths:
|
|
198
336
|
- lib
|
|
@@ -207,8 +345,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
207
345
|
- !ruby/object:Gem::Version
|
|
208
346
|
version: '0'
|
|
209
347
|
requirements: []
|
|
210
|
-
rubygems_version:
|
|
211
|
-
signing_key:
|
|
348
|
+
rubygems_version: 4.0.3
|
|
212
349
|
specification_version: 4
|
|
213
350
|
summary: Structured JSON logging for Rails/ActiveSupport with safe, single-line entries.
|
|
214
351
|
test_files: []
|