activesupport-json_logging 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b542fc320d19a1789f47805250847291ca671676834f66f1b99257d0311706ef
4
- data.tar.gz: 8dac946f3ee55c6b22ff4d7996e12c6b6ea220434c7ba4514a7495ce251c7504
3
+ metadata.gz: 4854135797f8609d12de7e48f10b2ece4151e828ae9d6699fcd8f367f645cf5f
4
+ data.tar.gz: 7fe2c2710e8adcab432233e3c55f97d337ba89ca1d5bd286c4e8b290662a3ac7
5
5
  SHA512:
6
- metadata.gz: 82f446cdb9ddc23c91ce99df51f90fd4d6cc2f8eecdaa45276bb8ff8aa074cb1ef07bde42b1ce3e2fc907e34e2e235a544cd54d36a1da5016a0fcf621b8b397b
7
- data.tar.gz: 21cc1fe28c94ae215a2293fe5f934bc9f139bba4affd9431b0aa41f0c0620e30ab456c0c43bd4b834e61d4e89a6d2a5876c3fdc47d2ca21b2d4163f4a3327578
6
+ metadata.gz: bd806fd601a0c4f761bd235f46e848f16701fe09e2995039c22e07c4aaa26545ad15f756ec635da3768a20a678fe7d3f6f35d2535a98f482fe885137758c1a58
7
+ data.tar.gz: 72c2460e491be67a3ead7de92e549cf11d13c51b3da774251080263311b51c3c8a79a7bc0ad4354b9bb2b0d11d16ae47f74511b800f1230b2fb5aaf3adc68b8c
data/CHANGELOG.md CHANGED
@@ -1,44 +1,12 @@
1
- # Changelog
1
+ # CHANGELOG
2
2
 
3
- ## 1.0.0 (2024-10-31)
3
+ ## 1.1.0 (2025-11-04)
4
4
 
5
- First stable release.
5
+ - 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"]`)
6
+ - Filter system-controlled keys (severity, timestamp, message, tags, context) from user context to prevent conflicts
7
+ - Prevent nested context objects when user context includes a `context` key
8
+ - Fix pending spec for TimeWithZone objects by requiring ActiveSupport time extensions
6
9
 
7
- - feat: single-line JSON format compatible with cloud logging services (GCP, AWS, Azure)
8
- - feat: native tagged logging with `logger.tagged("TAG")` API compatible with Rails
9
- - feat: thread-safe context via `JsonLogging.with_context` for per-thread fields
10
- - feat: smart message parsing for hashes, JSON strings, and plain strings
11
- - feat: inherit all ActiveSupport::Logger features (silence, local_level, etc.)
12
- - feat: BroadcastLogger compatibility for Rails 7.1+ automatic wrapping
13
- - feat: timestamp precision in microseconds (iso8601 with 6 decimals)
14
- - feat: Rails ParameterFilter integration for automatic sensitive data filtering
15
- - feat: input sanitization removing control characters and truncating long strings
16
- - feat: sensitive key pattern matching fallback when ParameterFilter unavailable
17
- - feat: depth and size limits for nested structures to prevent log bloat
18
- - feat: single-line JSON output to prevent log injection via newlines
19
- - feat: graceful error handling with fallback entries on serialization errors
20
- - feat: Rails 6.0, 6.1, 7.0, 7.1, 7.2, 8.0 support
21
- - feat: IsolatedExecutionState for thread/Fiber isolation (Rails 7.1+)
22
- - feat: backward compatible fallback to Thread.current for Rails 6-7.0
23
- - feat: kwargs support in logger initialization for Rails 7+
24
- - perf: ~0.006ms per log entry overhead (250-400% vs plain text, typical for JSON)
25
- - perf: memory efficient with ~3KB per entry and zero retained memory
26
- - feat: performance benchmarks with memory profiling included
27
- - test: 93.78% code coverage with comprehensive RSpec suite
28
- - test: BroadcastLogger integration tests
29
- - test: IsolatedExecutionState thread safety tests
30
- - test: Appraisals configured for multi-version testing (Rails 6-8)
31
- - test: GitHub Actions CI workflow
32
- - docs: complete README with installation, usage, and API docs
33
- - docs: Rails environment configuration examples (development, production, test)
34
- - docs: Lograge integration with third-party logger configurations
35
- - docs: Puma integration example
36
- - docs: security best practices and ParameterFilter guide
37
- - docs: inherited Rails logger features documentation
10
+ ## 1.0.0 (2025-10-31)
38
11
 
39
- ---
40
-
41
- ## 0.1.0
42
-
43
- - feat: initial JSON formatter and logger implementation
44
- - test: basic RSpec test coverage
12
+ - Initial stable release
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # activesupport-json_logging
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/activesupport-json_logging.svg)](https://badge.fury.io/rb/activesupport-json_logging) [![Test Status](https://github.com/amkisko/activesupport-json_logging.rb/actions/workflows/ci.yml/badge.svg)](https://github.com/amkisko/activesupport-json_logging.rb/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/amkisko/activesupport-json_logging.rb/graph/badge.svg?token=881AFPL643)](https://codecov.io/gh/amkisko/activesupport-json_logging.rb)
3
+ [![Gem Version](https://badge.fury.io/rb/activesupport-json_logging.svg)](https://badge.fury.io/rb/activesupport-json_logging) [![Test Status](https://github.com/amkisko/activesupport-json_logging.rb/actions/workflows/ci.yml/badge.svg)](https://github.com/amkisko/activesupport-json_logging.rb/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/amkisko/activesupport-json_logging.rb/graph/badge.svg?token=UX80FTO0Y0)](https://codecov.io/gh/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,7 @@ Supports Rails versions from 6 to 8.
8
8
 
9
9
  Sponsored by [Kisko Labs](https://www.kiskolabs.com).
10
10
 
11
+
11
12
  ## Installation
12
13
 
13
14
  Add to your Gemfile:
@@ -30,22 +31,6 @@ Rails.application.configure do
30
31
  end
31
32
  ```
32
33
 
33
- ### Development: Using from Local Repository
34
-
35
- When developing the gem or testing changes in your application, you can point your Gemfile to a local path:
36
-
37
- ```ruby
38
- # In your application's Gemfile
39
- gem "activesupport-json_logging", path: "../activesupport-json_logging.rb"
40
- ```
41
-
42
- Then run:
43
-
44
- ```bash
45
- bundle install
46
- ```
47
-
48
- **Note:** When using `path:` in your Gemfile, Bundler will use the local gem directly. Changes you make to the gem code will be immediately available in your application without needing to rebuild or reinstall the gem. This is ideal for development and testing.
49
34
 
50
35
  ## What you get
51
36
 
@@ -329,10 +314,10 @@ logger.tagged("BCX").tagged("Jason").info("Stuff")
329
314
  # Wrap a TaggedLogging logger - works perfectly
330
315
  tagged_logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
331
316
  json_logger = JsonLogging.new(tagged_logger)
332
- json_logger.tagged("TEST") { json_logger.info("message") } # Tags appear in JSON context
317
+ json_logger.tagged("TEST") { json_logger.info("message") } # Tags appear at root level in JSON
333
318
  ```
334
319
 
335
- **Note:** If you wrap a `JsonLogging` logger with `ActiveSupport::TaggedLogging`, the TaggedLogging's text-based tags will appear as part of the message string in the JSON output, not as structured tags in the context. For best results, wrap loggers with `JsonLogging` last.
320
+ **Note:** If you wrap a `JsonLogging` logger with `ActiveSupport::TaggedLogging`, the TaggedLogging's text-based tags will appear as part of the message string in the JSON output, not as structured tags at the root level. For best results, wrap loggers with `JsonLogging` last.
336
321
 
337
322
  ### JsonLogging::JsonLogger
338
323
 
@@ -359,7 +344,7 @@ formatter.call("INFO", Time.now, nil, "message")
359
344
 
360
345
  # With tags (useful for Puma or other standalone use cases)
361
346
  formatter = JsonLogging::Formatter.new(tags: ["Puma"])
362
- formatter.call("INFO", Time.now, nil, "message") # Output includes "Puma" tag in context
347
+ formatter.call("INFO", Time.now, nil, "message") # Output includes "Puma" tag at root level
363
348
 
364
349
  # Multiple tags
365
350
  formatter = JsonLogging::Formatter.new(tags: ["Puma", "Worker"])
@@ -511,6 +496,7 @@ Rails.application.config.filter_parameters += [
511
496
 
512
497
  The gem will automatically filter these from all log entries, including context data. Encrypted attributes (using Rails 7+ `encrypts`) are automatically filtered as well.
513
498
 
499
+
514
500
  ## Development
515
501
 
516
502
  ```bash
@@ -536,6 +522,47 @@ bundle exec appraisal rails-7.0 rspec
536
522
  bundle exec standardrb --fix
537
523
  ```
538
524
 
525
+ ### Development: Using from Local Repository
526
+
527
+ When developing the gem or testing changes in your application, you can point your Gemfile to a local path:
528
+
529
+ ```ruby
530
+ # In your application's Gemfile
531
+ gem "activesupport-json_logging", path: "../activesupport-json_logging.rb"
532
+ ```
533
+
534
+ Then run:
535
+
536
+ ```bash
537
+ bundle install
538
+ ```
539
+
540
+ **Note:** When using `path:` in your Gemfile, Bundler will use the local gem directly. Changes you make to the gem code will be immediately available in your application without needing to rebuild or reinstall the gem. This is ideal for development and testing.
541
+
542
+ ## Contributing
543
+
544
+ Bug reports and pull requests are welcome on GitHub at https://github.com/amkisko/activesupport-json_logging.rb
545
+
546
+ Contribution policy:
547
+ - New features are not necessarily added to the gem
548
+ - Pull request should have test coverage for affected parts
549
+ - Pull request should have changelog entry
550
+
551
+ Review policy:
552
+ - It might take up to 2 calendar weeks to review and merge critical fixes
553
+ - It might take up to 6 calendar months to review and merge pull request
554
+ - It might take up to 1 calendar year to review an issue
555
+
556
+
557
+ ## Publishing
558
+
559
+ ```sh
560
+ rm activesupport-json_logging-*.gem
561
+ gem build activesupport-json_logging.gemspec
562
+ gem push activesupport-json_logging-*.gem
563
+ ```
564
+
539
565
  ## License
540
566
 
541
- MIT
567
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
568
+
@@ -4,4 +4,3 @@ require "json_logging"
4
4
 
5
5
  # Ensure Railtie is loaded so Rails auto-discovers it
6
6
  require "activesupport/json_logging/railtie" if defined?(Rails)
7
-
@@ -29,14 +29,22 @@ module JsonLogging
29
29
  additional_context || {}
30
30
  end
31
31
 
32
- deduped_additional = sanitized_context.reject { |k, _| payload.key?(k) }
32
+ # Filter out system-controlled keys from user context
33
+ # These keys should never be set by user context as they're controlled by the logger
34
+ system_controlled_keys = [:tags, "tags", :severity, "severity", :timestamp, "timestamp", :message, "message", :context, "context"]
35
+ user_context_filtered = sanitized_context.except(*system_controlled_keys)
36
+
37
+ # Also prevent overriding any existing payload keys (additional safety)
38
+ deduped_additional = user_context_filtered.reject { |k, _| payload.key?(k) }
33
39
  merged_context = existing_context.merge(deduped_additional)
34
40
 
41
+ # Put tags at root level, separate from context
42
+ # Merge with existing tags from payload (e.g., when logging a hash with tags: [...] at root)
35
43
  unless tags.empty?
36
- existing_tags = Array(merged_context[:tags])
44
+ existing_tags = Array(payload[:tags] || payload["tags"])
37
45
  # Sanitize tag strings (remove control chars, truncate)
38
46
  sanitized_tags = tags.map { |tag| Sanitizer.sanitize_string(tag.to_s) }
39
- merged_context[:tags] = (existing_tags + sanitized_tags).uniq
47
+ payload[:tags] = (existing_tags + sanitized_tags).uniq
40
48
  end
41
49
 
42
50
  payload[:context] = merged_context unless merged_context.empty?
@@ -1,3 +1,3 @@
1
1
  module JsonLogging
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activesupport-json_logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - amkisko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-31 00:00:00.000000000 Z
11
+ date: 2025-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -92,6 +92,34 @@ dependencies:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
94
  version: '0.21'
95
+ - !ruby/object:Gem::Dependency
96
+ name: rspec_junit_formatter
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '0.6'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '0.6'
109
+ - !ruby/object:Gem::Dependency
110
+ name: simplecov-cobertura
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '3'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '3'
95
123
  - !ruby/object:Gem::Dependency
96
124
  name: standard
97
125
  requirement: !ruby/object:Gem::Requirement