Description
Rage's structured logging system makes it easy to add context to log entries using key-value pairs. However, there is currently no built-in mechanism to prevent sensitive information — such as passwords, tokens, credit card numbers, or personal data — from being written to logs.
For example, a developer might accidentally log sensitive data through with_context or append_info_to_payload:
Rage.logger.info "user signed in", email: user.email, token: session_token
Or sensitive parameters might leak through request logs if a controller doesn't properly filter them.
A redaction setting would allow users to define matching rules for keys whose values should be automatically replaced with [REDACTED] (or similar) before the log entry is written.
Example:
Rage.configure do
config.logger.redact_keys = [:password, :token, :secret, :authorization, :credit_card]
end
Since Rage logs are structured as key-value pairs, the implementation boils down to iterating the log context and replacing values for matching keys. The more interesting design question is how the matching rules should work.
Design considerations
- Exact vs. pattern matching. Should keys match exactly (
:password matches only password) or should they support substring/pattern matching (:password also matches password_confirmation, old_password, etc.)? Substring matching is more forgiving but could produce false positives. Consider whether the default should be substring matching with an option for exact matching, or vice versa.
- Nested keys. If log context contains nested hashes (e.g.
{ user: { email: "...", password: "..." } }), should redaction apply recursively? This adds complexity but is important for safety.
- Custom matchers. Beyond key names, some use cases require value-based redaction (e.g. redacting strings that look like credit card numbers regardless of the key name). Consider whether custom matcher procs should be supported in the initial implementation or deferred to a follow-up.
- Request log integration. Redaction should apply consistently across all log entry points —
Rage.logger.info with context, append_info_to_payload, global log_context.
- Performance. Redaction runs on every log entry, so the matching logic should be fast.
Tips
- Review the Logging docs to understand how structured logging,
with_context, append_info_to_payload, and external loggers work.
- Look at how
Rage::Logger#rebuild! and Rage::LogProcessor#rebuild! use dynamic code generation — this may be a good place to integrate redaction logic efficiently.
- Check the architecture doc to see how Rage's core components interact and to understand the design principles.
- Read the contributing guide for coding conventions and design principles used across the codebase.
- Before starting the implementation, please share your proposed design approach. The matching rules for keys need careful designing, so discussing the approach early will drastically increase the chances of acceptance and help avoid rework.
- Feel free to ask any questions or request help in the comments below!
Description
Rage's structured logging system makes it easy to add context to log entries using key-value pairs. However, there is currently no built-in mechanism to prevent sensitive information — such as passwords, tokens, credit card numbers, or personal data — from being written to logs.
For example, a developer might accidentally log sensitive data through
with_contextorappend_info_to_payload:Or sensitive parameters might leak through request logs if a controller doesn't properly filter them.
A redaction setting would allow users to define matching rules for keys whose values should be automatically replaced with
[REDACTED](or similar) before the log entry is written.Example:
Since Rage logs are structured as key-value pairs, the implementation boils down to iterating the log context and replacing values for matching keys. The more interesting design question is how the matching rules should work.
Design considerations
:passwordmatches onlypassword) or should they support substring/pattern matching (:passwordalso matchespassword_confirmation,old_password, etc.)? Substring matching is more forgiving but could produce false positives. Consider whether the default should be substring matching with an option for exact matching, or vice versa.{ user: { email: "...", password: "..." } }), should redaction apply recursively? This adds complexity but is important for safety.Rage.logger.infowith context,append_info_to_payload, globallog_context.Tips
with_context,append_info_to_payload, and external loggers work.Rage::Logger#rebuild!andRage::LogProcessor#rebuild!use dynamic code generation — this may be a good place to integrate redaction logic efficiently.