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

20210730_出張!Railsウォッチ in 銀座Rails#35

20210730_出張!Railsウォッチ in 銀座Rails#35

Masato Mori

July 30, 2021
Tweet

More Decks by Masato Mori

Other Decks in Programming

Transcript

  1. 出張!Railsウォッチ

    in 銀座Rails#35

    森 雅智 / @morimorihoge
    2021/07/30
    1

    特集:~何かと便利なActiveSupport::Instrumentation~


    View full-size slide

  2. About Me

    ● 森 雅智: @morimorihoge

    ● BPS株式会社でRailsの受託開発チームをやってたり、週1大学非常勤で
    Web開発を教えてたりします

    ● Ruby/Rails歴は11年くらい。Web開発は17年くらい

    ● 銀座Ralis #10でActiveRecordでVIEWを使おうという話をしました

    ● 銀座Rails #27でアプリケーションコンフィグの話をしました

    About BPS & TechRacho

    ● Web受託開発や電子書籍製品開発をやっている会社です

    ● TechRachoという自社技術Blogを運営しています

    ○ 5年ほど前から平日毎日更新してます

    ○ https://techracho.bpsinc.jp/
    ● お仕事相談、転職相談、TechRachoへのご意見など気軽にどうぞ

    ○ https://www.bpsinc.jp/ 2


    View full-size slide

  3. Railsウォッチとは?

    技術ブログTechRachoで毎週連載しているRails / Ruby界隈を中
    心とした雑多な情報を提供する技術雑談マガジン

    3


    View full-size slide

  4. これまでの出張Railsウォッチのピックアップテーマ

    ● 銀座Rails#12: 複数DB対応

    ● 銀座Rails#13: ActionText、Trix

    ● 銀座Rails#14: ActionMailbox

    ● 銀座Rails#15: production、development、staging環境について

    ● 銀座Rails#16: 機能開発の設計レビューについて

    ● 銀座Rails#17: リソース管理スコープについて

    ● 銀座Rails#19: 開発チームの冗長化について

    ● 銀座Rails#20: Excelと仲良くしよう

    ● 銀座Rails#21: 標準仕様を読むためのABNF

    ● 銀座Rails#22: CLIプログラムにOptionParserを使う

    ● 銀座Rails#23: ActiveRecordのSELECTベンチマーク

    ● 銀座Rails#24: 令和Devise事情

    ● 銀座Rails#28: 2020年の銀座Railsを振り返る

    ● 銀座Rails#29: Serverless Railsを試す

    ● 銀座Rails#30: Railsインフラ環境Overview

    ● 銀座Rails#31: Railsプロジェクトあるある

    ● 銀座Rails#32: MimeMagic騒動を振り返る

    ● 銀座Rails#33: Rails 7.0で入る予定の新機能(暫定版)

    ● 銀座Rails#34: もっとDBコメントを書こう

    4

    各回資料に興味がある方はこちらからどうぞ:https://speakerdeck.com/morimorihoge 


    View full-size slide

  5. 何かと便利なActiveSupport::Instrumentation

    5


    View full-size slide

  6. ActiveSupport::Instrumentation

    ● Rails標準のPubSub(publisher/subscriber)ライブラリ

    ● パフォーマンス計測やデバッグ中心に使われている

    ● 便利な割に思ったより有効に活用されていない気がするので紹介

    6


    View full-size slide

  7. PubSubとは?

    ● 基本の役割

    ○ Publisher: Event配信する人

    ○ Subscriber: Eventを受信したい人 

    ○ Event: やり取りしたい情報。メッセージと呼ぶこともある 

    ● PublisherはいつでもEventを配信できる

    ○ 購読しているSubscriberはいないかもしれないし、複数いるかもしれないが気にしない 

    ● SubscriberはいつでもEventを受信開始・解除できる

    ○ 流れてくるEventはないかもしれないが、気にしない 

    7

    Redis、AWS SNS、Google Cloud Pub/Subなど色々な所で使われている設計モデル 


    View full-size slide

  8. トピック型PubSubシステム(AS::Instrumentation)

    ● トピック型ではPublisherがEventをどのchannelに流すかを決める

    ● Subscriberはchannelを指定してsubscribeし、流れてきたEventを受信する

    8

    ※コンテンツ型の場合はEventの仕分けをSubscriberが行う点が異なる 


    View full-size slide

  9. AS::Instrumentsの利用例

    9

    channel名

    channel名
 eventのpayload


    View full-size slide

  10. ActiveSupport::Notifications::Event

    AS::Notifications.subscribeのブロック引数に渡されるオブジェクト

    10

    元々パフォーマンス計測に使われている機能のため、instrumentにかかった時間を
    #durationで高精度に取ることもできる


    View full-size slide

  11. Regex指定によるchannel subscribe

    11

    ginza35で始まる全てのchannelを受信

    正規表現でchannel subscribe


    View full-size slide

  12. AS::Instrumentationの使い方まとめ

    ● AS::Notifications.subscribe(channel)で購読したいchannelを指定
    し、ブロックにやらせたい処理を仕込んでおく

    ○ channelには正規表現も指定可能 

    ● AS::Notifications.instrument(channel, payload)でイベントを送
    信する

    12

    これだけ!とてもシンプル 👍


    View full-size slide

  13. ここから本編

    Railsにはあちこちにinstrumentが仕込んである

    ● [Edge Guide] https://edgeguides.rubyonrails.org/active_support_instrumentation.html#rails-framework-hooks 

    ● [日本語Guide] https://railsguides.jp/active_support_instrumentation.html 

    13

    眺めてみるとRailsのログに出ているような情報が取れることがわかる

    ※実際にはAS::LogSubscriberを使ってEventをログ出力用に整形している。詳しくは
    Railsのソースコードを読もう


    View full-size slide

  14. 例:でかい処理の中で実行されているSQLだけ取り出す

    このサービスクラス、何やってるかよくわからんのでとりあえず実行されてるSQLだけで
    も眺めてみるか・・・

    14

    ※sql.activerecord Eventのsqlはプレースホルダ化されているので、実際には:bindsも見ない
    とクエリ内に埋め込まれた値は分からないのに注意

    unsubscribeすればそれ以後は受信しない


    View full-size slide

  15. 例:特定のメール送信時にSlack通知したい

    15

    ※同期実行されるので、フロントから#deliver_now送信している場合などにはパフォーマンス
    に影響が出る可能性あり

    slack-notifier gemについては略


    View full-size slide

  16. Gemの例:Rack::Attack

    IPアドレスやAPIコール数制限などで良く使われるRack::AttackはInstrumentation対応

    16

    APIコール数制限に達したログを記録したい 、などのケースをカバーすることができる 


    View full-size slide

  17. 自分でinstrumentを定義して使う

    ● 今すぐは使わないけど、後々このイベントは取得できるようにしたくなりそう

    ● デバッグの時だけ簡単に情報を拾えるようにしたいけど、普段はOFFにしておきたい

    ● Loggerに出すと他の大量のログと混じってしまうので、個別にイベントとして取得したい

    ● Datadog他のAPMツールで扱うアプリケーションイベントを定義・出力したい

    17

    それAS::Instrumentationでできるよ(ドヤァ

    ロジックコードの中にprintデバッグコードを入れると入れたり消したりが大変だが、
    AS::Instrumentationならsubscriberを付け外しするだけで良い

    ※環境変数によってON/OFFするようなコードもsubscribeするところだけでOK


    View full-size slide

  18. AS::Instrumentation使用上の注意点

    ● channel名はRailsアプリケーション全体でglobalなので、名前の衝突に注意

    ● instrumentメソッドの呼び出しはsubscriberの有無によらず発生するので、payload
    に渡すオブジェクト整形処理はパフォーマンスに悪影響を与える可能性がある

    ● subscriberブロックの呼び出しは同期処理なので、重い処理を書くのは危険

    ○ 非同期系クラウド系Pub/Subサービスのつもりで使うと危険 

    ○ きちんとやるならsubscriberブロックで非同期Jobを投入するような工夫が必要 

    ● あくまで1プロセス内でのpubsubなので、リクエストを跨いだ処理には使えない

    ○ ActionCableでは複数WebSocketを跨いだpub/subにRedisのpubsub機能を使うように推奨されてい
    る

    18


    View full-size slide

  19. まとめ

    ● ActiveSupport::Instrumentationを使うとRails標準搭載の機能でPub/Subすることが
    できる

    ● あらかじめHookしておきたいような処理に#instrumentを仕込んでおくことで、必要
    になったときに#subscribeして利用することができる

    ● どこで何回呼び出される分からない処理に対して予めHookを仕込んでおくような使
    い方ができるので、コードのデバッグや障害調査に有用

    19


    View full-size slide

  20. 次回以降もブラッシュアップしていきます

    感想・リクエストなどあればTwitter

    #ginzarails

    @morimorihoge

    @hachi8833

    までお声かけください

    20


    View full-size slide