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

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

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

37b01da9150c1e789f35771b06d36890?s=128

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~


  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

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


  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 

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


  6. ActiveSupport::Instrumentation
 • Rails標準のPubSub(publisher/subscriber)ライブラリ
 • パフォーマンス計測やデバッグ中心に使われている
 • 便利な割に思ったより有効に活用されていない気がするので紹介
 6


  7. PubSubとは?
 • 基本の役割
 ◦ Publisher: Event配信する人
 ◦ Subscriber: Eventを受信したい人 


    ◦ Event: やり取りしたい情報。メッセージと呼ぶこともある 
 • PublisherはいつでもEventを配信できる
 ◦ 購読しているSubscriberはいないかもしれないし、複数いるかもしれないが気にしない 
 • SubscriberはいつでもEventを受信開始・解除できる
 ◦ 流れてくるEventはないかもしれないが、気にしない 
 7
 Redis、AWS SNS、Google Cloud Pub/Subなど色々な所で使われている設計モデル 

  8. トピック型PubSubシステム(AS::Instrumentation)
 • トピック型ではPublisherがEventをどのchannelに流すかを決める
 • Subscriberはchannelを指定してsubscribeし、流れてきたEventを受信する
 8
 ※コンテンツ型の場合はEventの仕分けをSubscriberが行う点が異なる 


  9. AS::Instrumentsの利用例
 9
 channel名
 channel名
 eventのpayload


  10. ActiveSupport::Notifications::Event
 AS::Notifications.subscribeのブロック引数に渡されるオブジェクト
 10
 元々パフォーマンス計測に使われている機能のため、instrumentにかかった時間を #durationで高精度に取ることもできる


  11. Regex指定によるchannel subscribe
 11
 ginza35で始まる全てのchannelを受信
 正規表現でchannel subscribe


  12. AS::Instrumentationの使い方まとめ
 • AS::Notifications.subscribe(channel)で購読したいchannelを指定 し、ブロックにやらせたい処理を仕込んでおく
 ◦ channelには正規表現も指定可能 
 • AS::Notifications.instrument(channel, payload)でイベントを送

    信する
 12
 これだけ!とてもシンプル 👍

  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のソースコードを読もう

  14. 例:でかい処理の中で実行されているSQLだけ取り出す
 このサービスクラス、何やってるかよくわからんのでとりあえず実行されてるSQLだけで も眺めてみるか・・・
 14
 ※sql.activerecord Eventのsqlはプレースホルダ化されているので、実際には:bindsも見ない とクエリ内に埋め込まれた値は分からないのに注意
 unsubscribeすればそれ以後は受信しない


  15. 例:特定のメール送信時にSlack通知したい
 15
 ※同期実行されるので、フロントから#deliver_now送信している場合などにはパフォーマンス に影響が出る可能性あり
 slack-notifier gemについては略


  16. Gemの例:Rack::Attack
 IPアドレスやAPIコール数制限などで良く使われるRack::AttackはInstrumentation対応
 16
 APIコール数制限に達したログを記録したい 、などのケースをカバーすることができる 


  17. 自分でinstrumentを定義して使う
 • 今すぐは使わないけど、後々このイベントは取得できるようにしたくなりそう
 • デバッグの時だけ簡単に情報を拾えるようにしたいけど、普段はOFFにしておきたい
 • Loggerに出すと他の大量のログと混じってしまうので、個別にイベントとして取得したい
 • Datadog他のAPMツールで扱うアプリケーションイベントを定義・出力したい
 17


    それAS::Instrumentationでできるよ(ドヤァ
 ロジックコードの中にprintデバッグコードを入れると入れたり消したりが大変だが、 AS::Instrumentationならsubscriberを付け外しするだけで良い
 ※環境変数によってON/OFFするようなコードもsubscribeするところだけでOK

  18. AS::Instrumentation使用上の注意点
 • channel名はRailsアプリケーション全体でglobalなので、名前の衝突に注意
 • instrumentメソッドの呼び出しはsubscriberの有無によらず発生するので、payload に渡すオブジェクト整形処理はパフォーマンスに悪影響を与える可能性がある
 • subscriberブロックの呼び出しは同期処理なので、重い処理を書くのは危険
 ◦ 非同期系クラウド系Pub/Subサービスのつもりで使うと危険

    
 ◦ きちんとやるならsubscriberブロックで非同期Jobを投入するような工夫が必要 
 • あくまで1プロセス内でのpubsubなので、リクエストを跨いだ処理には使えない
 ◦ ActionCableでは複数WebSocketを跨いだpub/subにRedisのpubsub機能を使うように推奨されてい る
 18

  19. まとめ
 • ActiveSupport::Instrumentationを使うとRails標準搭載の機能でPub/Subすることが できる
 • あらかじめHookしておきたいような処理に#instrumentを仕込んでおくことで、必要 になったときに#subscribeして利用することができる
 • どこで何回呼び出される分からない処理に対して予めHookを仕込んでおくような使 い方ができるので、コードのデバッグや障害調査に有用


    19

  20. 次回以降もブラッシュアップしていきます
 感想・リクエストなどあればTwitter
 #ginzarails
 @morimorihoge
 @hachi8833
 までお声かけください
 20