Upgrade to Pro — share decks privately, control downloads, hide ads and more …

kwargs warning → Sentry

pocke
July 25, 2020

kwargs warning → Sentry

https://docs.google.com/presentation/d/1i9DtFxDJlEqArtEuGQBP44K7rbQyIz-d74g3590NF-g/edit?usp=sharing
のコピーです。Google Slides上で見ることをおすすめします

pocke

July 25, 2020
Tweet

More Decks by pocke

Other Decks in Programming

Transcript

  1. kwargs warning → Sentry
    > Kaigi on Rails new
    Sat 25 Jul. 2020

    View full-size slide

  2. 誰?
    ● Pocke (ぽっけ)
    ● 株式会社ビットジャーニー勤務
    ○ Kibelaを作っています
    ● 最近の興味はRuby 3の型
    ○ Kaigi on Rails本編では型の話をできたらいいな

    View full-size slide

  3. 今日のテーマ
    ● Ruby 3のキーワード引数警告とは
    ● warning gemとは
    ● キーワード引数警告をSentryに送る
    前に日記に書いたものを清書した形になります。
    https://commits.hatenablog.com/entry/2020/07/14/100002

    View full-size slide

  4. Ruby 3のキーワード引数警告とは

    View full-size slide

  5. キーワード引数の警告とは?
    ● Ruby 3でキーワード引数の挙動が変わる
    ● それに合わせて、挙動が変わってしまうケースではRuby 2.7から警告が出る
    ● つまり警告が出るケースはゼロにしておかないと、Ruby 3で動かないコードになっ
    てしまう!
    https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keywo
    rd-arguments-in-ruby-3-0/
    https://discuss.rubyonrails.org/t/new-2-7-3-0-keyword-argument-pain-point/74980/
    47

    View full-size slide

  6. 挙動が変わる例
    def foo(k: 1)
    puts “ok”
    end
    foo({k: 1}) # => Ruby 2.7から警告
    # Ruby 3から ArgumentError
    foo(k: 1) # ok
    foo(**{k: 1}) # ok

    View full-size slide

  7. タイムライン
    ● 2019-12-25: Ruby 2.7.0 リリース
    ○ キーワード引数の警告が出るようになる
    ● 2020-??-??: Ruby 2.7.2 リリース (予定)
    ○ キーワード引数の警告が出ないようになる
    ○ https://discuss.rubyonrails.org/t/new-2-7-3-0-keyword-argument-pain-point/74980/47
    ● 2020-12-25: Ruby 3リリース (予定)
    ○ キーワード引数の警告が出ていたところの挙動が変わる

    View full-size slide

  8. ⚠warning gem

    View full-size slide

  9. warning gemとは
    ● https://github.com/jeremyevans/ruby-warning
    ● Rubyで起きた警告をいい感じにハンドルできるgem
    ● Ruby 2.4から導入されたWarning moduleを利用している
    いますぐ gem install warning

    View full-size slide

  10. 使い方の例 1: キーワード引数警告だけ無視する
    require 'warning'
    Warning.ignore(:keyword_separation)
    def foo(k:)
    end
    foo({k: 1}) # no warning!

    View full-size slide

  11. 使い方の例 2: キーワード引数警告をハンドルする
    require 'warning'
    Warning.process(__FILE__,
    keyword_separation: proc do |warning|
    system('say', warning)
    end
    )
    def foo(k:)
    end
    foo({k: 1}) # say the warning

    View full-size slide

  12. キーワード引数警告をSentryに送る

    View full-size slide

  13. なぜSentryに送りたいか
    ● Sentryとは: エラーをトラッキングするためのSaaS
    ○ bugsnagとかそういうやつ
    ● キーワード引数の警告は、Ruby 3までに直しておかないとアプリケーションの挙動
    が変わってしまうため、直さないといけない
    ● しかし放置していると気が付かない恐れがある
    ● → エラーと同様、警告もSentryに送っておけば良いのでは

    View full-size slide

  14. Sentryに警告を送るコードの実装例
    # config/initializers/warning.rb
    class WarningAsError < StandardError
    def initialize(warning, caller)
    super(warning)
    set_backtrace(caller)
    end
    end
    Warning.process('', keyword_separation: -> (warning) do
    caller = caller(2).drop_while { |path| path.match?(%r!/gems/warning-!) }
    message = warning.sub(/^.+: warning: /, '')
    err = WarningAsError.new(message, caller)
    Raven.capture_exception(err, level: 'warning')
    :default
    end)

    View full-size slide

  15. WarningAsError
    # config/initializers/warning.rb
    class WarningAsError < StandardError
    def initialize(warning, caller)
    super(warning)
    set_backtrace(caller)
    end
    end
    Warning.process('', keyword_separation: -> (warning) do
    caller = caller(2).drop_while { |path| path.match?(%r!/gems/warning-!) }
    message = warning.sub(/^.+: warning: /, '')
    err = WarningAsError.new(message, caller)
    Raven.capture_exception(err, level: 'warning')
    :default
    end)

    View full-size slide

  16. WarningAsError
    # 警告をSentryに送るために、例外として定義する
    class WarningAsError < StandardError
    def initialize(warning, caller)
    super(warning)
    # 警告にはbacktraceなどないので、手でセットする
    set_backtrace(caller)
    end
    end

    View full-size slide

  17. Warning.process
    # config/initializers/warning.rb
    class WarningAsError < StandardError
    def initialize(warning, caller)
    super(warning)
    set_backtrace(caller)
    end
    end
    Warning.process('', keyword_separation: -> (warning) do
    caller = caller(2).drop_while { |path| path.match?(%r!/gems/warning-!) }
    message = warning.sub(/^.+: warning: /, '')
    err = WarningAsError.new(message, caller)
    Raven.capture_exception(err, level: 'warning')
    :default
    end)

    View full-size slide

  18. Warning.process
    Warning.process('', keyword_separation: -> (warning) do
    # backtraceから、warning gemが出す部分を削除
    caller = caller(2).drop_while { |path|
    path.match?(%r!/gems/warning-!) }
    # 警告のメッセージ本文だけを抜き出す
    message = warning.sub(/^.+: warning: /, '')
    err = WarningAsError.new(message, caller)
    # Sentryに送信
    Raven.capture_exception(err, level: 'warning')
    # デフォルトの動作(stderrに警告を表示)をする
    :default
    end)

    View full-size slide

  19. 実装してみての感想
    ● 別の仕事が忙しくて、実はまだ警告つぶしができていない
    ● なんかやたら警告が飛んでいるケースがあるので見たほうが良いかも
    ● The called method `foo’ is defined here の方のメッセージは、Sentryに飛ばさなく
    てよさそう
    ○ キーワード引数の警告は 2行表示される。
    ○ こっちはbacktraceを見れば分かる。

    View full-size slide

  20. まとめ
    ● Ruby 3のキーワード引数についておさらいしました
    ○ https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-argumen
    ts-in-ruby-3-0/
    ○ https://discuss.rubyonrails.org/t/new-2-7-3-0-keyword-argument-pain-point/74980/47
    ● warning gemを紹介しました
    ○ https://github.com/jeremyevans/ruby-warning
    ● 警告をSentryに送る方法について紹介しました
    ○ ちょっと書き換えれば Sentry以外のサービスにも警告を送れると思います。

    View full-size slide