AI・可観測性・蛇口 🚰


SmartHR 技術基盤部 / Fukuoka.rb
近藤 宇智朗 (@udzura)

2026年11月6日 Kaigi on Rails 2026事後勉強会

Kaigi on Rails 2026 Recap

こんな計測結果、ありましたよね

横棒の一本一本が span
出典: Zen and the Art of File Upload Maintenance (Kaigi on Rails 2026) p.55 — https://udzura.jp/slides/2026/kaigionrails/

どうやって測ったの?

orange_tap

  • メソッドの処理時間・呼び出しツリーの可視化ツール
  • 利用技術: TracePoint(Ruby), OpenTelemetry※, OTLP/JSON
  • Pure Ruby 製。RubyGems.org で公開中

※ OpenTelemetry: トレース・メトリクス・ログを扱う、ベンダー中立な可観測性の標準(CNCF)。
OTLP はそのデータ形式・転送プロトコル

名前の由来

  • SystemTap っぽい名前にしたかった
    • Linux の定番トレーサ
  • じゃあ「〇〇tap」... tap...

RubyKaigi 2025 Matsuyama

Orange tap...
🍊🚰

使い方

# Uploader / Storage はデモ用の小さなクラス
OrangeTap.trace_all_instance_methods(Uploader)
OrangeTap.trace_method("Storage#head", "Storage#put")

OrangeTap.open("POST /avatar") do
  Uploader.new.store!("me.png")
end
# => "out/orange_tap-1f0016....json"

内部実装: 全体像

アプリのスレッドで TracePoint が Event を Thread::Queue に積み、open ごとに 1 本の Worker スレッドが取り出して span を組み立て、OTLP/JSON に書き出す

どう可視化するの?

otel-oneshot

  • OTLP/JSON を ASCII のタイムライン にする CLI(Go 製)
  • 対話 UI なし、1 回描いて終わり
    • パイプ・CI・AI エージェントでそのまま使える
  • --only / --hide / --sort duration で絞り込み
  • brew install --cask udzura/tap/otel-oneshot

otel-oneshot で見る

$ otel-oneshot out/orange_tap-1f0016....json --hide '^tid='
span                              0ms                   200.65ms               401.31ms
└─ POST /avatar                   ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 401.31ms
   └─ Uploader#store!             ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 401.14ms
      ├─ Uploader#resize_all      ▓▓▓▓▓▓▓▓▓▓▓                                            82.46ms
      ├─ Uploader#store_version!             ▓▓▓▓▓▓▓▓▓▓                                  80.11ms
      │  ├─ Storage#head                     ▓▓▓                                         25.02ms
      │  └─ Storage#put                         ▓▓▓▓▓▓▓                                  55.04ms
      ├─ Uploader#store_version!                       ▓▓▓▓▓▓▓▓▓▓▓                       80.09ms
      │  ├─ Storage#head                               ▓▓▓▓                              25.03ms
      │  └─ Storage#put                                    ▓▓▓▓▓▓▓                       55.03ms
      ├─ Uploader#store_version!                                  ▓▓▓▓▓▓▓▓▓▓▓             79.8ms
      │  ├─ Storage#head                                          ▓▓▓                    25.06ms
      │  └─ Storage#put                                              ▓▓▓▓▓▓▓▓            54.68ms
      └─ Uploader#store_version!                                             ▓▓▓▓▓▓▓▓▓▓  78.63ms
         ├─ Storage#head                                                     ▓▓▓         23.51ms
         └─ Storage#put                                                         ▓▓▓▓▓▓▓  55.05ms

同じ形が並んだら N+1

$ otel-oneshot trace.json --only 'Storage#put'
├─ Storage#put  ▓▓▓▓▓▓▓▓▓▓                                           55.04ms
├─ Storage#put                ▓▓▓▓▓▓▓▓▓▓                             55.03ms
├─ Storage#put                              ▓▓▓▓▓▓▓▓▓▓               54.68ms
└─ Storage#put                                            ▓▓▓▓▓▓▓▓▓▓ 55.05ms
  • --only で見たい span だけ残す
  • --sort duration --top-n で遅い順に絞る

人間が使うだけじゃない

AI エージェントに使わせる

  • 計測 → 描画 → 読解 の手順を Skill※ にまとめた
  • Rails では around_action + OrangeTap.record で仕込む
    • spec の実行中に仕込む手もある

※ Skill: AI エージェント(Claude Code など)に読ませる手順書。
「こういう作業はこの手順で」をリポジトリに置いておく

AI に使わせた例

Claude Code とのセッションより

AI に使わせた例(続き)

Claude Code とのセッションより

学び: AI 時代こそ可観測性

  • Before AI: アプリに可観測性を入れても、
    人間が使いこなしきれなかった
  • AI は可観測性が大好き、というか 前提
  • debug-mcp※ も似た発想でしたね

※ Kaigi on Rails 2026「AIエージェントのデバッグ能力を向上させよう — AI時代にRailsが輝く理由」(rira100000000 さん)。
debug gem を MCP で AI エージェントにつなぎ、ブレークポイントで止めて実行中の状態を見せる

まとめ

  • orange_tap: メソッドの呼び出しをコールツリーとして記録
  • otel-oneshot: タイムラインをターミナルで可視化
  • 人間だけでなくAIも使える可観測性ツールを作ろう!

github.com/udzura/orange_tap
github.com/udzura/otel-oneshot

We are Hiring!

「AI・可観測性・蛇口」、近藤です。

Kaigi on Rails 2026 で「Zen and the Art of File Upload Maintenance」という話を発表させていただきました。CarrierWave との戦いの記録、信頼性、アップグレード、そしてパフォーマンスの話をしたわけですけど、

パフォーマンスといえば、こんな図を出していたんですけど、覚えていますか?

しれっと出てますけど、どうやって測ったのか、気になりませんか? これはですね、自分で作った gem である orange_tap を使って測っています。

orange_tap が何かというと、Ruby の TracePoint を使ってメソッドの呼び出しと戻りをフックして、OpenTelemetry 形式の JSON ファイルを出力するツールです。OSS で公開しています。

名前は、SystemTap という Linux の定番のトレーサーの名前から取っていて、なんとか tap にしたかったんですけど、

tap といえば、松山にありましたよね。

オレンジの蛇口ですね。ということで、ロゴも作ってます。

orange_tap の使い方を見ると、どういうものかすぐ分かるんですけど、open で囲んだところの処理のトレースを取って、span のツリーを作ります。

仕組みとしてはこんな感じで、TracePoint で call と return をフックして、イベントをどんどん別のスレッドに送り込んで、span を組み立てて、JSON を吐き出すという感じになります。

この JSON はそのままだと可視化できないので、

OpenTelemetry 互換の JSON をパースできる otel-oneshot というコマンドを作って、span を可視化できるようにしました。これも CLI で可視化できるようにしています。

こんな感じで可視化ができます。

絞り込むこともできて、Storage#put が N+1 で起こってます、みたいなのが可視化できます。

ここまでは普通に OSS を作ったんですけど、何が面白いかって、

このツールは全部 CLI で完結したり、Ruby に組み込むものなので、AI エージェントに使わせることができます。実際、計測して、可視化して、読解させて、ボトルネックを探る、というのをスキルにまとめて Claude Code に使わせて、実際の値を測ったり、ボトルネックを突き止めたりしました。

こんな感じで、「ファイルアップロードの前処理のパフォーマンスの違いを計測したいので、orange_tap を使ってください」と指示をしたら、スキルを使って指示を受け取って、計測をしてくれる。

処理の呼び出しの回数も見えるし、そのままグラフも作ってくれる、みたいな感じで、可視化がめちゃくちゃはかどるなと。

学びとしては、なんとなく中身を知りたいなと思って作ったんですけど、昔作った Vivarium を応用しただけなんですけど、作ってみたらいい感じに刺さって、AI 時代こそ可観測性だと思ったんですね。以前は、可観測性がブームだからと導入したとしても、人間がそのデータを使いこなせなかったんですよ。ちょっと人間が弱くて。AI は可観測性を見事に使いこなせるので、debug-mcp なんかも似たような感じだと思うんですけど、アプリの可観測性を上げるのが重要だなというのは、すごく感じました。

まとめると、orange_tap を作って、あと otel-oneshot で AI に可視化させて活用して、こんな感じで可観測性を上げていけば、負債にも対応しやすくなるのかなと思います。

SmartHR をよろしくお願いします。ご清聴ありがとうございました。