
Issue #20864 has been updated by shyouhei (Shyouhei Urabe). I also want something like this. In order to move things forward we have to clear some points: - There could be programs that redefine `Kernel#warn` on the fly in the wild. They might suffer from the API change. About the only thing we can do here is let them die miserably. Is it an acceptable choice? (I guess so though) - The other issue is `Warning.warn` side. We already have it, which also doesn't expect unknown arguments for now. We acknowledge that Warning.warn could take exactly one argument (per https://bugs.ruby-lang.org/issues/17122#note-15). We are checking if it takes `category:` every time now. If we were to pass arbitrary keyword arguments to Warning.warn is the check... kind of possible in practice? These two might be related, but are not the same thing. ---------------------------------------- Feature #20864: Allow `Kernel#warn` to accept `**options` and pass these to `Warning.warn`. https://bugs.ruby-lang.org/issues/20864#change-110525 * Author: ioquatix (Samuel Williams) * Status: Open ---------------------------------------- ## Background Structured logging is a practice that organizes log data in a consistent, easily parseable format. Unlike traditional unstructured logs, which often consist of plain text entries, structured logs format information in key-value pairs or structured data formats such as JSON. This allows for better automation, searchability, and analysis of log data. In Ruby, `Kernel#warn` is extremely useful, especially because there is a mechanism for loggers to redirect warnings using the `Warning` module. However, it is difficult to generate structured logs with `Kernel#warn` as all the positional arguments are converted to a single string, and arbitrary keyword options are rejected. As a consequence, code like this is not possible: ```ruby begin ... rescue => error warn "Something went wrong!", exception: error end ``` It is very desirable to have a standard interface in Ruby for emitting structured warnings. ## Proposal I'd like to extend the current implementation to allow all options to be forwarded to `Warning.warn`. This would allow us to add more details to warnings and emit structured logs using `Warning.warn`. A simple example of the proposed interface: ```ruby module Kernel def warn(*arguments, uplevel: ..., **options) # Existing processing of arguments -> message ::Warning.warn(message, **options) end end ``` Current behaviour rejects any unknown options: ``` warn("Oops", exception: error) # => <internal:warning>:50:in `warn': unknown keyword: :exception (ArgumentError) ``` I don't have an opinion about the implementation, but I wanted to get feedback on the interface. Regarding the default behaviour, I propose no changes. -- https://bugs.ruby-lang.org/