Ruby 3.2でException#detailed_messageが生えたらSentryのexceptionのvalueが変わった。
Ruby 3.1を使ってたコードで、Sentryのconfigに以下のようなことを書いていた。
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
だったので、実装を見にいく。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の新機能であることを思い出すわけですね。detail
nana@er % rbenv local 3.1.5
nana@er % irb
irb(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.4
nana@er % irb
irb(main):001:0> e = SignalException.new 'INT'
=> #<SignalException: SIGINT>
irb(main):002:0> e.detailed_message
=> "SIGINT (SignalException)"
これで動作が変わったことがわかりましたね。めでたしめでたし。
……そもそもこういう文字列を比較してるのがつらい気がするので、シグナル番号とかで比較できないのか?
SignalException#signo
とかがあるので、例外が露出してたらなんとかなりそう……だったけど、single_exceptionの実装読むにそういうのは特になさそう……?