Ruby 3.2でException#detailed_messageが生えたらSentryのexceptionのvalueが変わった。
Ruby 3.1を使ってたコードで、Sentryのconfigに以下のようなことを書いていた。
code:ruby.rb
event.exception&.values&.each do |e|
if e.type == 'SignalException' && e.value == 'SIGTERM'
return nil
end
end
ようするにSIGTERMは無視するようなコード。
これ3.2にもっていくと何故か壊れた。
pry(main)> e.value
=> "SIGTERM (SignalException)"
覗いてみると、以前はSIGTERMだったvalueがSIGTERM (SignalException)になってた。
==してるところをこれにすれば解決ではあるんだけど、なんでこんなことになったのか?
このeは何かというと、Sentry::SingleExceptionInterfaceだったので、実装を見にいく。
code:signal_exception.rb
exception_message =
if exception.respond_to?(:detailed_message)
exception.detailed_message(highlight: false)
else
exception.message || ""
end
exception_message = exception_message.inspect unless exception_message.is_a?(String)
@value = Utils::EncodingHelper.encode_to_utf_8(exception_message.byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES))
e.valueはようするに飛んできた例外がdetailed_messageに反応すればそれ、そうでなければmessageを使っている。
ここで、Exception#detailed_messageがRuby 3.2の新機能であることを思い出すわけですね。
code:detail
nana@er % rbenv local 3.1.5
nana@er % irb
irb(main):001:0> e = SignalException.new 'INT'
irb(main):002:0> e.detailed_message
(irb):2:in <main>': undefined method detailed_message' for #<SignalException: SIGINT> (NoMethodError) from /Users/nana/.rbenv/versions/3.1.5/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
from /Users/nana/.rbenv/versions/3.1.5/bin/irb:25:in `load'
from /Users/nana/.rbenv/versions/3.1.5/bin/irb:25:in `<main>'
irb(main):003:0>
nana@er % rbenv local 3.2.4
nana@er % irb
irb(main):001:0> e = SignalException.new 'INT'
irb(main):002:0> e.detailed_message
=> "SIGINT (SignalException)"
これで動作が変わったことがわかりましたね。めでたしめでたし。
……そもそもこういう文字列を比較してるのがつらい気がするので、シグナル番号とかで比較できないのか?
SignalException#signoとかがあるので、例外が露出してたらなんとかなりそう……だったけど、single_exceptionの実装読むにそういうのは特になさそう……?