Feature #18564

Updated by mame (Yusuke Endoh) 6 months ago

(This ticket is for recording the final spec of #18438) 

 ## Proposal 

 I would introduce a method `Exception#detailed_message`, and let the default error printer use it instead of `Exception#message` to create a error output. 

 class MyClass < StandardError 
   def message = "my error!" 
   def detailed_message(highlight: false, **opt) 
     super + "\nThis is\nan additional\nmessage" 

 raise MyClass 

 $ ./miniruby test.rb 
 test.rb:8:in `<main>': my error! (MyClass) 
 This is 
 an additional 

 Here is the implementation: 

 ## Spec 

 `Exception#detailed_message(highlight: false)` calls `#message` and decorates the returned string. It may add the class name of exception and, when `highlight` keyword is true, some escape sequences for highlights. 

 e ="my error!") 
 p e.detailed_message                    #=> "my error! (RuntimeError)" 
 p e.detailed_message(highlight: true) #=> "\e[1mmy error! (\e[1;4mRuntimeError\e[m\e[1m)\e[m" 

 Previously, the default error printer and `Exception#full_message` called `#message` to get the error message, applied some processing (adding the error class name and adding escape sequences) to the string, and added backtrace. Now, they now use `#detailed_message(highlight: Exception.to_tty?)` instead of `#message`. 

 All keyword arguments passed to `Exception#full_message` are delegated to `detailed_message`. 

 ## Motivation 

 The primary motivation is a clean integration of did_you_mean and error_highlight gems. 

 At the present time, they overrides `Exception#to_s` to add their suggestions. However, there are some known problems in this approach: 

 * It may break some tests to check the result of `Exception#to_s` depending on whether the gems add suggestions or not. 
 * Some Ruby scripts re-raise an exception by `raise e.class, e.message, e.backtrace`, which makes the gems add their suggestion multiple times (currently, [the gems ad-hocly check and avoid multiple addition]( 
 * Sometimes a user needs to get the original message without their addition. For the sake, did_you_mean provides `Exception#original_message`, but [the workaround is not very well known]( 

 This proposal allows the gems to override `Exception#detailed_message`. `Exception#to_s` is kept as-is, so the above problems will no longer occur. 

 Also, the proposal allows a user to get a full_message without the suggestions by `err.full_message(did_you_mean: false, error_highlight: false)`. 

 Here is a proof-of-concept patch for did_you_mean and error_highlight: I'll create PRs for the gems after `Exception#detailed_message` is merged. 

 # Cooperation needed 

 This change requires application monitoring services such as Sentry, DataDog, ScoutAPM, etc. They need to use `Exception#detailed_message(highlight: false)` instead of `Exception#message` to log the error messages after Ruby 3.2. Thankfully, @st0012 (the maintainer of Sentry's Ruby SDK) and @ivoanjo and @marcotc (the maintainers of Datadog's application monitoring gem) have agreed with this change. 

 @matz has already approved this proposal in #18438 . I'll merge my PR in a few days after some reviews.