logstruct 0.0.1 → 0.0.2.pre.rc1
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 +26 -2
- data/LICENSE +21 -0
- data/README.md +67 -0
- data/lib/log_struct/concerns/configuration.rb +93 -0
- data/lib/log_struct/concerns/error_handling.rb +94 -0
- data/lib/log_struct/concerns/logging.rb +45 -0
- data/lib/log_struct/config_struct/error_handling_modes.rb +25 -0
- data/lib/log_struct/config_struct/filters.rb +80 -0
- data/lib/log_struct/config_struct/integrations.rb +89 -0
- data/lib/log_struct/configuration.rb +59 -0
- data/lib/log_struct/enums/error_handling_mode.rb +22 -0
- data/lib/log_struct/enums/error_reporter.rb +14 -0
- data/lib/log_struct/enums/event.rb +48 -0
- data/lib/log_struct/enums/level.rb +66 -0
- data/lib/log_struct/enums/source.rb +26 -0
- data/lib/log_struct/enums.rb +9 -0
- data/lib/log_struct/formatter.rb +224 -0
- data/lib/log_struct/handlers.rb +27 -0
- data/lib/log_struct/hash_utils.rb +21 -0
- data/lib/log_struct/integrations/action_mailer/callbacks.rb +100 -0
- data/lib/log_struct/integrations/action_mailer/error_handling.rb +173 -0
- data/lib/log_struct/integrations/action_mailer/event_logging.rb +90 -0
- data/lib/log_struct/integrations/action_mailer/metadata_collection.rb +78 -0
- data/lib/log_struct/integrations/action_mailer.rb +50 -0
- data/lib/log_struct/integrations/active_job/log_subscriber.rb +104 -0
- data/lib/log_struct/integrations/active_job.rb +38 -0
- data/lib/log_struct/integrations/active_record.rb +258 -0
- data/lib/log_struct/integrations/active_storage.rb +94 -0
- data/lib/log_struct/integrations/carrierwave.rb +111 -0
- data/lib/log_struct/integrations/good_job/log_subscriber.rb +228 -0
- data/lib/log_struct/integrations/good_job/logger.rb +73 -0
- data/lib/log_struct/integrations/good_job.rb +111 -0
- data/lib/log_struct/integrations/host_authorization.rb +81 -0
- data/lib/log_struct/integrations/integration_interface.rb +21 -0
- data/lib/log_struct/integrations/lograge.rb +114 -0
- data/lib/log_struct/integrations/rack.rb +31 -0
- data/lib/log_struct/integrations/rack_error_handler/middleware.rb +146 -0
- data/lib/log_struct/integrations/rack_error_handler.rb +32 -0
- data/lib/log_struct/integrations/shrine.rb +75 -0
- data/lib/log_struct/integrations/sidekiq/logger.rb +43 -0
- data/lib/log_struct/integrations/sidekiq.rb +39 -0
- data/lib/log_struct/integrations/sorbet.rb +49 -0
- data/lib/log_struct/integrations.rb +41 -0
- data/lib/log_struct/log/action_mailer.rb +55 -0
- data/lib/log_struct/log/active_job.rb +64 -0
- data/lib/log_struct/log/active_storage.rb +78 -0
- data/lib/log_struct/log/carrierwave.rb +82 -0
- data/lib/log_struct/log/error.rb +76 -0
- data/lib/log_struct/log/good_job.rb +151 -0
- data/lib/log_struct/log/interfaces/additional_data_field.rb +20 -0
- data/lib/log_struct/log/interfaces/common_fields.rb +42 -0
- data/lib/log_struct/log/interfaces/message_field.rb +20 -0
- data/lib/log_struct/log/interfaces/request_fields.rb +36 -0
- data/lib/log_struct/log/plain.rb +53 -0
- data/lib/log_struct/log/request.rb +76 -0
- data/lib/log_struct/log/security.rb +80 -0
- data/lib/log_struct/log/shared/add_request_fields.rb +29 -0
- data/lib/log_struct/log/shared/merge_additional_data_fields.rb +28 -0
- data/lib/log_struct/log/shared/serialize_common.rb +36 -0
- data/lib/log_struct/log/shrine.rb +70 -0
- data/lib/log_struct/log/sidekiq.rb +50 -0
- data/lib/log_struct/log/sql.rb +126 -0
- data/lib/log_struct/log.rb +43 -0
- data/lib/log_struct/log_keys.rb +102 -0
- data/lib/log_struct/monkey_patches/active_support/tagged_logging/formatter.rb +36 -0
- data/lib/log_struct/multi_error_reporter.rb +149 -0
- data/lib/log_struct/param_filters.rb +89 -0
- data/lib/log_struct/railtie.rb +31 -0
- data/lib/log_struct/semantic_logger/color_formatter.rb +209 -0
- data/lib/log_struct/semantic_logger/formatter.rb +94 -0
- data/lib/log_struct/semantic_logger/logger.rb +129 -0
- data/lib/log_struct/semantic_logger/setup.rb +219 -0
- data/lib/log_struct/sorbet/serialize_symbol_keys.rb +23 -0
- data/lib/log_struct/sorbet.rb +13 -0
- data/lib/log_struct/string_scrubber.rb +84 -0
- data/lib/log_struct/version.rb +6 -0
- data/lib/log_struct.rb +37 -0
- data/lib/logstruct.rb +2 -6
- data/logstruct.gemspec +52 -0
- metadata +221 -5
- data/Rakefile +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ce0ec5e8973926358ab0282f61945eb85bbaead27060a16b00e85685b2b83f2
|
4
|
+
data.tar.gz: d5146c601563992a8b426f8bcfea1db40d631995c7e16d7a771e98b78010c2ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e30c656d03a93056e85e750189277007c05737f123d0b576b9f600f75a9b48dd3ff45fdf82e3990a8b9541793dd6402013f8bf982f0addc8f1191dcc4a32fe0
|
7
|
+
data.tar.gz: fe24218d1771ff69ecf9a4d2fd8901aed19472ee02c38e2e14f87d0c0c3293887492b1e038f79e0985d4be6350a402c544db4bf28cf718a4a8229e61dd98f6e8
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,32 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
3
8
|
## [0.0.1] - 2025-03-04
|
4
9
|
|
5
10
|
### Added
|
6
11
|
|
7
|
-
-
|
8
|
-
|
12
|
+
- Pushed empty gem to RubyGems to secure the name
|
13
|
+
|
14
|
+
## [0.0.2-rc1] - 2025-09-05
|
15
|
+
|
16
|
+
### Added
|
17
|
+
|
18
|
+
- Unified GitHub Actions workflow to release RubyGem and sync/tag the Terraform provider; dry-run support for safe validation
|
19
|
+
- Provider catalog export script and automated provider CI (build/vet/test)
|
20
|
+
- Terraform docs page with quickstart, recipes, and provider README link
|
21
|
+
- API design doc (typed vs. untyped) planned; initial philosophy captured
|
22
|
+
- Coverage threshold gate (>= 80%) in CI; additional tests to lift coverage
|
23
|
+
- Release helper: scripts/create_release_tag.sh (creates annotated tag from version.rb)
|
24
|
+
|
25
|
+
### Changed
|
26
|
+
|
27
|
+
- ActionMailer callbacks patched for Rails 7.0; event logging + metadata collection tested
|
28
|
+
- Provider CloudWatch filter builder refactored for testability; key lookups aligned with exported catalog (event/source)
|
29
|
+
|
30
|
+
### Fixed
|
31
|
+
|
32
|
+
- Pre-commit hooks reporting; cspell dictionary updated; TypeScript import fixes in site
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 DocSpring Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# LogStruct
|
2
|
+
|
3
|
+
Adds JSON structured logging to any Rails app. Simply add the gem to your Gemfile and add an initializer to configure it. By default, your Rails app prints JSON logs to STDOUT (or to the configured destination when `RAILS_LOG_TO_STDOUT` is set). They're easy to search and filter, you can turn them into metrics and alerts, and they're great for building dashboards in CloudWatch, Grafana, or Datadog.
|
4
|
+
|
5
|
+
We support all your other favorite gems too, like Sidekiq, Sentry, and Shrine. (And if not, please open a PR!)
|
6
|
+
|
7
|
+
## Features
|
8
|
+
|
9
|
+
- JSON logging enabled by default in production and test environments
|
10
|
+
- ActionMailer integration for email delivery logging
|
11
|
+
- ActiveJob integration for job execution logging
|
12
|
+
- Sidekiq integration for background job logging
|
13
|
+
- Shrine integration for file upload logging
|
14
|
+
- Error handling and reporting
|
15
|
+
- Metadata collection for rich context
|
16
|
+
- Lograge integration for structured request logging
|
17
|
+
- Sensitive data scrubbing for strings (inspired by the Logstop gem)
|
18
|
+
- Host authorization logging for security violations
|
19
|
+
- Rack middleware for enhanced error logging
|
20
|
+
- ActionMailer delivery callbacks for Rails 7.0.x (backported from Rails 7.1)
|
21
|
+
- Type checking with Sorbet and RBS annotations
|
22
|
+
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
Add this line to your application's Gemfile:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
gem 'logstruct'
|
29
|
+
```
|
30
|
+
|
31
|
+
And then execute:
|
32
|
+
|
33
|
+
```bash
|
34
|
+
$ bundle install
|
35
|
+
```
|
36
|
+
|
37
|
+
Or install it yourself as:
|
38
|
+
|
39
|
+
```bash
|
40
|
+
$ gem install logstruct
|
41
|
+
```
|
42
|
+
|
43
|
+
## Configuration and Initialization
|
44
|
+
|
45
|
+
LogStruct is designed to be highly opinionated and work out of the box with minimal configuration.
|
46
|
+
|
47
|
+
Please see the [documentation](https://logstruct.com/docs/configuration/) for configuration options.
|
48
|
+
|
49
|
+
### Important Notes on Integration
|
50
|
+
|
51
|
+
Once initialized, the gem automatically includes its modules into the appropriate base classes:
|
52
|
+
|
53
|
+
- `ActiveSupport::TaggedLogging` is patched to support both Hashes and Strings
|
54
|
+
- `ActionMailer::Base` includes error handling and event logging modules
|
55
|
+
- We configure `Lograge` for request logging
|
56
|
+
- A Rack middleware is inserted to catch and log errors, including security violations (IP spoofing, CSRF, blocked hosts, etc.)
|
57
|
+
- Structured logging is set up for ActiveJob, Sidekiq, Shrine, etc.
|
58
|
+
- Rails `config.filter_parameters` are merged into LogStruct's filters and then cleared (to avoid double filtering). Configure sensitive keys via `LogStruct.config.filters`.
|
59
|
+
- When `RAILS_LOG_TO_STDOUT` is set, we log to STDOUT only. Otherwise, we log to STDOUT by default without adding a file appender to avoid duplicate logs.
|
60
|
+
|
61
|
+
## Documentation
|
62
|
+
|
63
|
+
Please see the [documentation](https://logstruct.com/docs) for more details. (All code examples are type-checked and tested, and it's harder to keep a README up to date.)
|
64
|
+
|
65
|
+
## License
|
66
|
+
|
67
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "../configuration"
|
5
|
+
|
6
|
+
module LogStruct
|
7
|
+
module Concerns
|
8
|
+
# Concern for handling errors according to configured modes
|
9
|
+
module Configuration
|
10
|
+
module ClassMethods
|
11
|
+
extend T::Sig
|
12
|
+
|
13
|
+
sig { params(block: T.proc.params(config: LogStruct::Configuration).void).void }
|
14
|
+
def configure(&block)
|
15
|
+
yield(config)
|
16
|
+
end
|
17
|
+
|
18
|
+
sig { returns(LogStruct::Configuration) }
|
19
|
+
def config
|
20
|
+
LogStruct::Configuration.instance
|
21
|
+
end
|
22
|
+
|
23
|
+
# (Can't use alias_method since this module is extended into LogStruct)
|
24
|
+
sig { returns(LogStruct::Configuration) }
|
25
|
+
def configuration
|
26
|
+
config
|
27
|
+
end
|
28
|
+
|
29
|
+
# Setter method to replace the configuration (for testing purposes)
|
30
|
+
sig { params(config: LogStruct::Configuration).void }
|
31
|
+
def configuration=(config)
|
32
|
+
LogStruct::Configuration.set_instance(config)
|
33
|
+
end
|
34
|
+
|
35
|
+
sig { returns(T::Boolean) }
|
36
|
+
def enabled?
|
37
|
+
config.enabled
|
38
|
+
end
|
39
|
+
|
40
|
+
sig { void }
|
41
|
+
def set_enabled_from_rails_env!
|
42
|
+
# Set enabled based on current Rails environment and the LOGSTRUCT_ENABLED env var.
|
43
|
+
# Precedence:
|
44
|
+
# 1. Check if LOGSTRUCT_ENABLED env var is defined
|
45
|
+
# - Sets enabled=true only when value is "true"
|
46
|
+
# - Sets enabled=false when value is "false" (or any non-"true")
|
47
|
+
# 2. Otherwise, check if current Rails environment is in enabled_environments
|
48
|
+
# 3. Otherwise, leave as config.enabled (defaults to true)
|
49
|
+
|
50
|
+
# Then check if LOGSTRUCT_ENABLED env var is set
|
51
|
+
config.enabled = if ENV["LOGSTRUCT_ENABLED"]
|
52
|
+
# Override to true only if env var is "true"
|
53
|
+
ENV["LOGSTRUCT_ENABLED"] == "true"
|
54
|
+
else
|
55
|
+
config.enabled_environments.include?(::Rails.env.to_sym)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
sig { returns(T::Boolean) }
|
60
|
+
def is_local?
|
61
|
+
config.local_environments.include?(::Rails.env.to_sym)
|
62
|
+
end
|
63
|
+
|
64
|
+
sig { returns(T::Boolean) }
|
65
|
+
def is_production?
|
66
|
+
!is_local?
|
67
|
+
end
|
68
|
+
|
69
|
+
sig { void }
|
70
|
+
def merge_rails_filter_parameters!
|
71
|
+
return unless ::Rails.application.config.respond_to?(:filter_parameters)
|
72
|
+
|
73
|
+
rails_filter_params = ::Rails.application.config.filter_parameters
|
74
|
+
return unless rails_filter_params.is_a?(Array)
|
75
|
+
|
76
|
+
# Convert all Rails filter parameters to symbols and merge with our filter keys
|
77
|
+
converted_params = rails_filter_params.map do |param|
|
78
|
+
param.respond_to?(:to_sym) ? param.to_sym : param
|
79
|
+
end
|
80
|
+
|
81
|
+
# Add Rails filter parameters to our filter keys
|
82
|
+
config.filters.filter_keys += converted_params
|
83
|
+
|
84
|
+
# Ensure no duplicates
|
85
|
+
config.filters.filter_keys.uniq!
|
86
|
+
|
87
|
+
# Clear Rails filter parameters since we've incorporated them
|
88
|
+
::Rails.application.config.filter_parameters.clear
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module LogStruct
|
5
|
+
module Concerns
|
6
|
+
# Concern for handling errors according to configured modes
|
7
|
+
module ErrorHandling
|
8
|
+
module ClassMethods
|
9
|
+
extend T::Sig
|
10
|
+
extend T::Helpers
|
11
|
+
|
12
|
+
# Needed for raise
|
13
|
+
requires_ancestor { Module }
|
14
|
+
|
15
|
+
# Get the error handling mode for a given source
|
16
|
+
sig { params(source: Source).returns(ErrorHandlingMode) }
|
17
|
+
def error_handling_mode_for(source)
|
18
|
+
config = LogStruct.config
|
19
|
+
|
20
|
+
# Use a case statement for type-safety
|
21
|
+
case source
|
22
|
+
when Source::TypeChecking
|
23
|
+
config.error_handling_modes.type_checking_errors
|
24
|
+
when Source::LogStruct
|
25
|
+
config.error_handling_modes.logstruct_errors
|
26
|
+
when Source::Security
|
27
|
+
config.error_handling_modes.security_errors
|
28
|
+
when Source::Rails, Source::App, Source::Job, Source::Storage, Source::Mailer,
|
29
|
+
Source::Shrine, Source::CarrierWave, Source::Sidekiq
|
30
|
+
config.error_handling_modes.standard_errors
|
31
|
+
else
|
32
|
+
# Ensures the case statement is exhaustive
|
33
|
+
T.absurd(source)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Log an errors with structured data
|
38
|
+
sig { params(error: StandardError, source: Source, context: T.nilable(T::Hash[Symbol, T.untyped])).void }
|
39
|
+
def log_error(error, source:, context: nil)
|
40
|
+
# Create structured log entry
|
41
|
+
error_log = Log::Error.from_exception(
|
42
|
+
source,
|
43
|
+
error,
|
44
|
+
context || {}
|
45
|
+
)
|
46
|
+
LogStruct.error(error_log)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Report an error using the configured handler or MultiErrorReporter
|
50
|
+
sig { params(error: StandardError, source: Source, context: T.nilable(T::Hash[Symbol, T.untyped])).void }
|
51
|
+
def log_and_report_error(error, source:, context: nil)
|
52
|
+
log_error(error, source: source, context: context)
|
53
|
+
error_handler = LogStruct.config.error_reporting_handler
|
54
|
+
if error_handler
|
55
|
+
# Use the configured handler
|
56
|
+
error_handler.call(error, context, source)
|
57
|
+
else
|
58
|
+
# Fall back to MultiErrorReporter (detects Sentry, Bugsnag, etc.)
|
59
|
+
LogStruct::MultiErrorReporter.report_error(error, context || {})
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Handle an error according to the configured error handling mode (log, report, raise, etc)
|
64
|
+
sig { params(error: StandardError, source: Source, context: T.nilable(T::Hash[Symbol, T.untyped])).void }
|
65
|
+
def handle_exception(error, source:, context: nil)
|
66
|
+
mode = error_handling_mode_for(source)
|
67
|
+
|
68
|
+
# Log / report in production, raise locally (dev/test)
|
69
|
+
if mode == ErrorHandlingMode::LogProduction || mode == ErrorHandlingMode::ReportProduction
|
70
|
+
raise(error) if !LogStruct.is_production?
|
71
|
+
end
|
72
|
+
|
73
|
+
case mode
|
74
|
+
when ErrorHandlingMode::Ignore
|
75
|
+
# Do nothing
|
76
|
+
|
77
|
+
when ErrorHandlingMode::Raise
|
78
|
+
raise(error)
|
79
|
+
|
80
|
+
when ErrorHandlingMode::Log, ErrorHandlingMode::LogProduction
|
81
|
+
log_error(error, source: source, context: context)
|
82
|
+
|
83
|
+
when ErrorHandlingMode::Report, ErrorHandlingMode::ReportProduction
|
84
|
+
log_and_report_error(error, source: source, context: context)
|
85
|
+
|
86
|
+
else
|
87
|
+
# Ensures the case statement is exhaustive
|
88
|
+
T.absurd(mode)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "../log"
|
5
|
+
|
6
|
+
module LogStruct
|
7
|
+
module Concerns
|
8
|
+
# Concern for handling errors according to configured modes
|
9
|
+
module Logging
|
10
|
+
module ClassMethods
|
11
|
+
extend T::Sig
|
12
|
+
|
13
|
+
# Log a log struct at debug level
|
14
|
+
sig { params(log: Log::Interfaces::CommonFields).void }
|
15
|
+
def debug(log)
|
16
|
+
Rails.logger.debug(log)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Log a log struct at info level
|
20
|
+
sig { params(log: Log::Interfaces::CommonFields).void }
|
21
|
+
def info(log)
|
22
|
+
Rails.logger.info(log)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Log a log struct at warn level
|
26
|
+
sig { params(log: Log::Interfaces::CommonFields).void }
|
27
|
+
def warn(log)
|
28
|
+
Rails.logger.warn(log)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Log a log struct at error level
|
32
|
+
sig { params(log: Log::Interfaces::CommonFields).void }
|
33
|
+
def error(log)
|
34
|
+
Rails.logger.error(log)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Log a log struct at fatal level
|
38
|
+
sig { params(log: Log::Interfaces::CommonFields).void }
|
39
|
+
def fatal(log)
|
40
|
+
Rails.logger.fatal(log)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module LogStruct
|
5
|
+
module ConfigStruct
|
6
|
+
class ErrorHandlingModes < T::Struct
|
7
|
+
include Sorbet::SerializeSymbolKeys
|
8
|
+
|
9
|
+
# How to handle different types of errors
|
10
|
+
# Modes:
|
11
|
+
# - Ignore - Ignore the error
|
12
|
+
# - Log - Log the error
|
13
|
+
# - Report - Log and report to error tracking service (but don't crash)
|
14
|
+
# - LogProduction - Log error in production, raise locally (dev/test)
|
15
|
+
# - ReportProduction - Report error in production, raise locally (dev/test)
|
16
|
+
# - Raise - Always raise the error
|
17
|
+
|
18
|
+
# Configurable error handling categories
|
19
|
+
prop :type_checking_errors, ErrorHandlingMode, default: ErrorHandlingMode::LogProduction
|
20
|
+
prop :logstruct_errors, ErrorHandlingMode, default: ErrorHandlingMode::LogProduction
|
21
|
+
prop :security_errors, ErrorHandlingMode, default: ErrorHandlingMode::Report
|
22
|
+
prop :standard_errors, ErrorHandlingMode, default: ErrorHandlingMode::Raise
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module LogStruct
|
5
|
+
module ConfigStruct
|
6
|
+
class Filters < T::Struct
|
7
|
+
include Sorbet::SerializeSymbolKeys
|
8
|
+
|
9
|
+
# Keys that should be filtered in nested structures such as request params and job arguments.
|
10
|
+
# Filtered data includes information about Hashes and Arrays.
|
11
|
+
#
|
12
|
+
# { _filtered: {
|
13
|
+
# _class: "Hash", # Class of the filtered value
|
14
|
+
# _bytes: 1234, # Length of JSON string in bytes
|
15
|
+
# _keys_count: 3, # Number of keys in the hash
|
16
|
+
# _keys: [:key1, :key2, :key3], # First 10 keys in the hash
|
17
|
+
# }
|
18
|
+
# }
|
19
|
+
#
|
20
|
+
# Default: [:password, :password_confirmation, :pass, :pw, :token, :secret,
|
21
|
+
# :credentials, :creds, :auth, :authentication, :authorization]
|
22
|
+
#
|
23
|
+
prop :filter_keys,
|
24
|
+
T::Array[Symbol],
|
25
|
+
factory: -> {
|
26
|
+
%i[
|
27
|
+
password password_confirmation pass pw token secret
|
28
|
+
credentials auth authentication authorization
|
29
|
+
credit_card ssn social_security
|
30
|
+
]
|
31
|
+
}
|
32
|
+
|
33
|
+
# Keys where string values should include an SHA256 hash.
|
34
|
+
# Useful for tracing emails across requests (e.g. sign in, sign up) while protecting privacy.
|
35
|
+
# Default: [:email, :email_address]
|
36
|
+
prop :filter_keys_with_hashes,
|
37
|
+
T::Array[Symbol],
|
38
|
+
factory: -> { %i[email email_address] }
|
39
|
+
|
40
|
+
# Hash salt for SHA256 hashing (typically used for email addresses)
|
41
|
+
# Used for both param filters and string scrubbing
|
42
|
+
# Default: "l0g5t0p"
|
43
|
+
prop :hash_salt, String, default: "l0g5t0p"
|
44
|
+
|
45
|
+
# Hash length for SHA256 hashing (typically used for email addresses)
|
46
|
+
# Used for both param filters and string scrubbing
|
47
|
+
# Default: 12
|
48
|
+
prop :hash_length, Integer, default: 12
|
49
|
+
|
50
|
+
# Filter email addresses. Also controls email filtering for the ActionMailer integration
|
51
|
+
# (to, from, recipient fields, etc.)
|
52
|
+
# Default: true
|
53
|
+
prop :email_addresses, T::Boolean, default: true
|
54
|
+
|
55
|
+
# Filter URL passwords
|
56
|
+
# Default: true
|
57
|
+
prop :url_passwords, T::Boolean, default: true
|
58
|
+
|
59
|
+
# Filter credit card numbers
|
60
|
+
# Default: true
|
61
|
+
prop :credit_card_numbers, T::Boolean, default: true
|
62
|
+
|
63
|
+
# Filter phone numbers
|
64
|
+
# Default: true
|
65
|
+
prop :phone_numbers, T::Boolean, default: true
|
66
|
+
|
67
|
+
# Filter social security numbers
|
68
|
+
# Default: true
|
69
|
+
prop :ssns, T::Boolean, default: true
|
70
|
+
|
71
|
+
# Filter IP addresses
|
72
|
+
# Default: false
|
73
|
+
prop :ip_addresses, T::Boolean, default: false
|
74
|
+
|
75
|
+
# Filter MAC addresses
|
76
|
+
# Default: false
|
77
|
+
prop :mac_addresses, T::Boolean, default: false
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "active_support/notifications"
|
5
|
+
|
6
|
+
module LogStruct
|
7
|
+
module ConfigStruct
|
8
|
+
class Integrations < T::Struct
|
9
|
+
include Sorbet::SerializeSymbolKeys
|
10
|
+
|
11
|
+
# Enable or disable Sorbet error handler integration
|
12
|
+
# Default: true
|
13
|
+
prop :enable_sorbet_error_handlers, T::Boolean, default: true
|
14
|
+
|
15
|
+
# Enable or disable Lograge integration
|
16
|
+
# Default: true
|
17
|
+
prop :enable_lograge, T::Boolean, default: true
|
18
|
+
|
19
|
+
# Custom options for Lograge
|
20
|
+
# Default: nil
|
21
|
+
prop :lograge_custom_options, T.nilable(Handlers::LogrageCustomOptions), default: nil
|
22
|
+
|
23
|
+
# Enable or disable ActionMailer integration
|
24
|
+
# Default: true
|
25
|
+
prop :enable_actionmailer, T::Boolean, default: true
|
26
|
+
|
27
|
+
# Enable or disable host authorization logging
|
28
|
+
# Default: true
|
29
|
+
prop :enable_host_authorization, T::Boolean, default: true
|
30
|
+
|
31
|
+
# Enable or disable ActiveJob integration
|
32
|
+
# Default: true
|
33
|
+
prop :enable_activejob, T::Boolean, default: true
|
34
|
+
|
35
|
+
# Enable or disable Rack middleware
|
36
|
+
# Default: true
|
37
|
+
prop :enable_rack_error_handler, T::Boolean, default: true
|
38
|
+
|
39
|
+
# Enable or disable Sidekiq integration
|
40
|
+
# Default: true
|
41
|
+
prop :enable_sidekiq, T::Boolean, default: true
|
42
|
+
|
43
|
+
# Enable or disable Shrine integration
|
44
|
+
# Default: true
|
45
|
+
prop :enable_shrine, T::Boolean, default: true
|
46
|
+
|
47
|
+
# Enable or disable ActiveStorage integration
|
48
|
+
# Default: true
|
49
|
+
prop :enable_activestorage, T::Boolean, default: true
|
50
|
+
|
51
|
+
# Enable or disable CarrierWave integration
|
52
|
+
# Default: true
|
53
|
+
prop :enable_carrierwave, T::Boolean, default: true
|
54
|
+
|
55
|
+
# Enable or disable GoodJob integration
|
56
|
+
# Default: true
|
57
|
+
prop :enable_goodjob, T::Boolean, default: true
|
58
|
+
|
59
|
+
# Enable SemanticLogger integration for high-performance logging
|
60
|
+
# Default: true
|
61
|
+
prop :enable_semantic_logger, T::Boolean, default: true
|
62
|
+
|
63
|
+
# Enable colored JSON output in development
|
64
|
+
# Default: true
|
65
|
+
prop :enable_color_output, T::Boolean, default: true
|
66
|
+
|
67
|
+
# Color configuration for JSON output
|
68
|
+
# Default: nil (uses SemanticLogger defaults)
|
69
|
+
prop :color_map, T.nilable(T::Hash[Symbol, Symbol]), default: nil
|
70
|
+
|
71
|
+
# Filter noisy loggers (ActionView, etc.)
|
72
|
+
# Default: false
|
73
|
+
prop :filter_noisy_loggers, T::Boolean, default: false
|
74
|
+
|
75
|
+
# Enable SQL query logging through ActiveRecord instrumentation
|
76
|
+
# Default: false (can be resource intensive)
|
77
|
+
prop :enable_sql_logging, T::Boolean, default: false
|
78
|
+
|
79
|
+
# Only log SQL queries slower than this threshold (in milliseconds)
|
80
|
+
# Set to 0 or nil to log all queries
|
81
|
+
# Default: 100.0 (log queries taking >100ms)
|
82
|
+
prop :sql_slow_query_threshold, T.nilable(Float), default: 100.0
|
83
|
+
|
84
|
+
# Include bind parameters in SQL logs (disable in production for security)
|
85
|
+
# Default: true in development/test, false in production
|
86
|
+
prop :sql_log_bind_params, T::Boolean, factory: -> { !defined?(::Rails) || !::Rails.respond_to?(:env) || !::Rails.env.production? }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "handlers"
|
5
|
+
require_relative "config_struct/error_handling_modes"
|
6
|
+
require_relative "config_struct/integrations"
|
7
|
+
require_relative "config_struct/filters"
|
8
|
+
|
9
|
+
module LogStruct
|
10
|
+
# Core configuration class that provides a type-safe API
|
11
|
+
class Configuration < T::Struct
|
12
|
+
extend T::Sig
|
13
|
+
|
14
|
+
include Sorbet::SerializeSymbolKeys
|
15
|
+
|
16
|
+
# -------------------------------------------------------------------------------------
|
17
|
+
# Props
|
18
|
+
# -------------------------------------------------------------------------------------
|
19
|
+
|
20
|
+
prop :enabled, T::Boolean, default: true
|
21
|
+
prop :enabled_environments, T::Array[Symbol], factory: -> { [:test, :production] }
|
22
|
+
prop :local_environments, T::Array[Symbol], factory: -> { [:development, :test] }
|
23
|
+
const :integrations, ConfigStruct::Integrations, factory: -> { ConfigStruct::Integrations.new }
|
24
|
+
const :filters, ConfigStruct::Filters, factory: -> { ConfigStruct::Filters.new }
|
25
|
+
|
26
|
+
# Custom log scrubbing handler for any additional string scrubbing
|
27
|
+
# Default: nil
|
28
|
+
prop :string_scrubbing_handler, T.nilable(Handlers::StringScrubber)
|
29
|
+
|
30
|
+
# Custom handler for error reporting
|
31
|
+
# Default: Errors are handled by MultiErrorReporter
|
32
|
+
# (auto-detects Sentry, Bugsnag, Rollbar, Honeybadger, etc.)
|
33
|
+
prop :error_reporting_handler, T.nilable(Handlers::ErrorReporter), default: nil
|
34
|
+
|
35
|
+
# How to handle errors from various sources
|
36
|
+
const :error_handling_modes,
|
37
|
+
ConfigStruct::ErrorHandlingModes,
|
38
|
+
factory: -> {
|
39
|
+
ConfigStruct::ErrorHandlingModes.new
|
40
|
+
}
|
41
|
+
|
42
|
+
# -------------------------------------------------------------------------------------
|
43
|
+
# Class Methods
|
44
|
+
# -------------------------------------------------------------------------------------
|
45
|
+
|
46
|
+
# Class‐instance variable
|
47
|
+
@instance = T.let(nil, T.nilable(Configuration))
|
48
|
+
|
49
|
+
sig { returns(Configuration) }
|
50
|
+
def self.instance
|
51
|
+
@instance ||= T.let(Configuration.new, T.nilable(Configuration))
|
52
|
+
end
|
53
|
+
|
54
|
+
sig { params(config: Configuration).void }
|
55
|
+
def self.set_instance(config)
|
56
|
+
@instance = config
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module LogStruct
|
5
|
+
# Enum for error handling modes
|
6
|
+
class ErrorHandlingMode < T::Enum
|
7
|
+
enums do
|
8
|
+
# Always ignore the error
|
9
|
+
Ignore = new(:ignore)
|
10
|
+
# Always log the error
|
11
|
+
Log = new(:log)
|
12
|
+
# Always report to tracking service and continue
|
13
|
+
Report = new(:report)
|
14
|
+
# Log in production, raise locally (dev/test)
|
15
|
+
LogProduction = new(:log_production)
|
16
|
+
# Report in production, raise locally (dev/test)
|
17
|
+
ReportProduction = new(:report_production)
|
18
|
+
# Always raise regardless of environment
|
19
|
+
Raise = new(:raise)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module LogStruct
|
5
|
+
class ErrorReporter < T::Enum
|
6
|
+
enums do
|
7
|
+
RailsLogger = new(:rails_logger)
|
8
|
+
Sentry = new(:sentry)
|
9
|
+
Bugsnag = new(:bugsnag)
|
10
|
+
Rollbar = new(:rollbar)
|
11
|
+
Honeybadger = new(:honeybadger)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|