Ruby 3.2でException#detailed_messageが生えたらSentryのexceptionのvalueが変わった。
Ruby 3.1を使ってたコードで、Sentryのconfigに以下のようなことを書いていた。
ruby.rbevent.exception&.values&.each do |e| if e.type == 'SignalException' && e.value == 'SIGTERM' return nil endendようするにSIGTERMは無視するようなコード。
これ3.2にもっていくと何故か壊れた。
pry(main)> e.value
=> "SIGTERM (SignalException)"
覗いてみると、以前は
SIGTERM だった value が SIGTERM (SignalException) になってた。 == してるところをこれにすれば解決ではあるんだけど、なんでこんなことになったのか?この
e は何かというと、 Sentry::SingleExceptionInterface だったので、実装を見にいく。signal_exception.rbexception_message = if exception.respond_to?(:detailed_message) exception.detailed_message(highlight: false) else exception.message || "" endexception_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の新機能であることを思い出すわけですね。detailnana@er % rbenv local 3.1.5nana@er % irbirb(main):001:0> e = SignalException.new 'INT'=> #<SignalException: SIGINT>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.4nana@er % irbirb(main):001:0> e = SignalException.new 'INT'=> #<SignalException: SIGINT>irb(main):002:0> e.detailed_message=> "SIGINT (SignalException)"これで動作が変わったことがわかりましたね。めでたしめでたし。
……そもそもこういう文字列を比較してるのがつらい気がするので、シグナル番号とかで比較できないのか?
SignalException#signo とかがあるので、例外が露出してたらなんとかなりそう……だったけど、single_exceptionの実装読むにそういうのは特になさそう……?