アプリケーションメトリクスが壊れたサイズ推定機能を検出してくれた話

Article by: (読了時間:15分)

 

 

動画のエンコードを数分待って、メッセージにドラッグ&ドロップした瞬間に「ファイルが大きすぎます」というエラーが出る… あの特有のイライラ。そこからは、あと数MBを削ろうと手探りで再エンコードを繰り返すことになります。解像度を下げてみたり、bitrate を小さくしてみたり、あと1〜2回で済むことを祈りながら。

この記事では、Sentry の Application Metrics を使って、より正確な動画サイズ推定機能を作った方法を紹介します。

最近、私は自分の vibe-coded なプロジェクトのひとつに取り組んでいました(よくあることです)。その名も Cliparr。動画からクリップを作成できるセルフホスト型のツールです。当然ながら、エクスポートする前に出力ファイルのサイズが分かれば理想的です。

理論上、動画のサイズ計算はかなりシンプルなはずです。目標 bitrate とクリップの再生時間が分かっていれば、両者を掛け合わせるだけで最終的な出力サイズが求められます。これは codec や container に関係なく、あらゆる動画フォーマットで成り立つはずです。

[bitrate] x [duration] = [size]

 

しかし、これが実際にさまざまなデバイス・ブラウザ・フォーマットで本当に成り立つのか、どうにも信じきれませんでした。動画編集の経験はそれなりにあり、少し調べもしましたし、いつでも魔法の AI ボックスに聞くこともできます。それでも、自分が正しいと思っていることが現実と一致しているかどうかをどうやって確信すればいいのでしょうか。

このシンプルな推定を狂わせてしまう「未知の要因」に、どんなものがあり得るのでしょうか。いくつか思い当たるものはあり、そのうちのひとつは後述しますが、私がより気にしていたのは「自分が知らないこと」の方でした。

最初は自分のパソコンにある動画を手作業でいくつも変換し、推定がどれくらい正確かを確認するところから始めました。かなり正確そうに見えました……。しかし、もう少し科学的にやりたくなってきました。フォーマット・codec・品質設定などの組み合わせのマトリクスを用意することもできます。

そこで気づいたのです。私はそこまでやるにはやや面倒くさがりであり、しかももっと良い方法があるかもしれない、と。ツールの実際の利用状況をそのまま記録して、人々が本当に使う状況で推定がどれくらい正確かを見ればいいのです。

Sentry の Application Metrics を使って変換結果をモニタリング・可視化したところ、推定が 83% も外れている例をひとつ見つけました。

 

オープンソースプロジェクトにとっての Win-Win-Win

Cliparr は Plex や Jellyfin と連携しますが、トランスコード処理はすべてデバイス上、つまりブラウザ内で MediaBunny を介して行われるため、サーバーには何もアップロードも処理もされません。ほぼ静的サイトにできるほどですが、認証とメディアファイルへのアクセスのために小さな proxy サーバーだけを持っています。

opt-in のテレメトリという方法も公平な選択肢ではありましたが、セルフホストのコミュニティは一般的にデータ送信を好みませんし、私も今のところセットアップの流れを変えたくありませんでした。その結果、アプリ自体から推定精度を測る手段がなくなってしまったのですが、この制約が、三重の見返りをもたらすアイデアにつながりました。

  • 誰かのセルフホスト環境に一切手を触れずに、推定を改善するためのリアルなデータが得られる
  • アカウントもホスティングも不要で、サイト上ですぐに使える新しいツールになる
  • サイトを訪れて再訪する、もうひとつの本当に役立つ理由になるという SEO 上のメリット

 

私はエクスポートエンジンをエディターから分離し、独立したパッケージとしてリリースしました。これを公開ウェブサイトで使い、Cliparr Convert を作ったのです。

 これは、シンプルなプリセットを備えたミニマルなブラウザ内動画コンバーターで、ファイル形式間の変換やサイズ制限が問題になりそうなときの動画圧縮に便利です。これは公開されている Cliparr サイト上で「ホスト」されており(こちらは本当に完全な静的サイトです)、誰でも何もインストールせずに使えます。また progressive web app(PWA)として利用することもできます。

このページには、サイズ推定機能の改善のために私が重視する KPI(key performance indicators)を匿名で追跡できるよう、Sentry の Application Metrics を最小限だけ計装しました。ブラウザから出ていくのは数値だけで、メディアそのものやファイル名、URL は決して送信されません。今回のケースでは tracing すら使っておらず、metrics だけです。

 

counter と distribution で KPI を追跡する

metrics で答えを出したかった主な質問は、次の3つです。

  • サイズ推定は正確か?(推定は現実からどれくらいずれているか)
  • 人々が実際に変換しているメディアタイプは何か?(まず何の改善に注力すべきか)
  • そもそも動いているか?(変換は完了しているか)

 

これらは、誰かのセルフホスト環境に一切触れることなく、時間をかけて追跡・改善できる3つの KPI です。

集めたシンプルな匿名 metrics だけで、各 KPI をモニタリングするためのかなり詳細なダッシュボードに加えて、データから自然に見えてきたいくつかの興味深い metrics も可視化できました。

 

KPI #1:推定は正直か?

肝心の metric は、サイズ推定式が実世界でどれくらい正確か、です。

とはいえ、推定が完璧にはならないことは、そもそも織り込み済みです。なぜなら実世界では、完璧で一定の bitrate になることはめったにないからです。

現時点で Cliparr は目標 bitrate を持っていますが、使っているのは variable bitrate(VBR)の encoder です。つまり encoder は、動画の内容に応じて bitrate を変動させます。品質の観点ではこれは良いことで、最終的なサイズは本来よりも小さくなります。しかし同時に、私たちの計算式はすでにあくまで大まかな推定でしかなく、動画によっては理論上かなりの幅でずれる可能性があることも意味します。

それでも、今のところ平均でどれくらいずれているのでしょうか。そして外れ値はどう見えるのでしょうか。

変換が完了するたびに、実サイズと推定サイズの比率を distribution metric として記録し、生の数値も一緒に記録します。

 

// One completed conversion, recorded as a family of measurements.
const attributes = {
“estimate.basis”: outputSizeEstimate.basis, // transcode-plan | gif-profile | …
“output.format”: format, // mp4 | webm | gif | …
“export.quality”: selectedQuality, // sharp | balanced | compact
};

Sentry.metrics.distribution(“convert.output.bytes”, actualBytes, { unit: “byte”, attributes });

const estimateBytes = outputSizeEstimate.bytes;
if (typeof estimateBytes !== “number” || estimateBytes <= 0) return; // no estimate? skip the ratio

const ratio = Number((actualBytes / estimateBytes).toFixed(3));
Sentry.metrics.distribution(“convert.estimate.delta_bytes”, actualBytes – estimateBytes, { unit: “byte”, attributes });
Sentry.metrics.distribution(“convert.estimate.ratio”, ratio, { attributes }); // no unit, it’s a ratio

 

技術的には比率をダッシュボード側で計算することもでき、その方がむしろ正確かもしれませんが、これは私にとって少しラクな方法です。

この distribution は集計でき、output format・quality・どの推定式が生成したか、といった属性でグループ化できます。estimate.basis という属性を追加したのは、GIF には別の計算式を使っており、動画向けの計算式も後で変更・バージョン管理したくなるかもしれないからです。(伏線です。)

もし以前 Sentry を使ったことがあれば、なぜ代わりに logs を使わなかったのか、あるいは traces を使わなかったのか、と思うかもしれません。Logs・Traces・Metrics はいずれも属性付きのイベントを記録しますが、それぞれ挙動が少しずつ異なり、使うべきコンテキストも違います。

Traces でも技術的にはこれらの一部を運ぶことはできますが、traces は通常かなり重くサンプリングされます。私が知りたいのは、そのうちの一部ではなく、あらゆる変換すべてです。また trace は、システムの中を通る「ひとつの作業単位」を追跡してその時間を計測するために作られており、サイズ比率は作業単位ではなく、各変換が最後に生み出す単なる数値です。もし logs を考えていたなら、それはより理解できますが、それでもこのデータには正しい選択ではありません。Logs はデバッグのためにアプリケーションの状態を出力するものであり、可視化はできても、あるログが KPI モニタリングにとって重要だということが将来すぐに明らかになるとは限りません。

Metrics は数値を記録し、サンプリングされません。metric は、「これは私たちが計測する対象だ」という意図的な宣言であって、役目を終えたら削除されるデバッグログではないのです。

いくつかの変換を記録した後、推定機能を直す前と後の両方の結果は次のようになりました。比率はこう読みます。1.000 なら完璧。1.15 なら実ファイルが予測より15%大きく出たということ。0.85 なら小さく出たということ。そして推定式ごとにグループ化したので、各式のパフォーマンスが分かります。

推定式 サンプル数 平均比率 範囲 意味
AI 提案の式(旧) 16 1.57 1.30 – 1.83 出力が約束より最大83%大きい
Bitrate 式(新) 24 0.97 0.84 – 1.05 トランスコードは約5%以内に収まる
GIF 推定(別方式) 8 0.91 フラット 約9%の過大推定

最初の試みでは、私は単に AI に「サイズ推定機能を書いて」と頼んだだけで、なぜかシンプルな bitrate × duration の式を使ってくれませんでした。賢く振る舞おうとして、間違えていたのです。

一番上の行を見てください。いくつか例を記録した後、その最初の推定式は、推定より最大83%大きい出力ファイルを生み出していました。

推定が多少ずれることは予想していましたが、83%というのは推定式に何か問題がありそうだと感じました。そこでエージェントが書いたコードを実際に見直しに行ったところ、まったく筋が通っていませんでした。

最初の試みは、別の解像度で動画を再エンコードしたら何が起きるかを、下手に推測しようとしたもののように見えました。しかし、解像度はファイルサイズの計算に一切関わりません。「bitrate」でエンコードするとき、あなたは encoder に対して「動画1秒あたり何ビット使うか」を明示的に指示しています。encoder は解像度に関係なく、そのビット数を使います。解像度は品質には影響しますが、ファイルサイズには影響しません。

私が思うに、起きたことはこうです。最初にアシスタントにサイズ推定の追加を頼んだとき、それは私のプロンプトに引きずられすぎたのです。おそらく私は「解像度が変わったらどうなる?」のような聞き方をしてしまい、そうした質問によって、うっかりよりシンプルで正しい答えから遠ざけてしまったのではないか、と思います。

metrics ダッシュボードのおかげでその明らかな誤りに気づいた後、私は壊れた推定コードを正しい bitrate ベースの式に置き換え、「estimator basis」属性を追加しました。これにより、どの式が使われたかで結果を簡単に分割できます。新しい bitrate ベースの推定機能は、最大83%のずれから約5%以内へと改善してくれました。

こうした最悪ケースを手早く捉えるために、人気のある変換ワークフローそれぞれについて、ダッシュボードに「Max Estimate Ratio」タイルを追加しました。今回の場合は mp4 → webm です。

もし同じことをやってみたいなら、ダッシュボードで新しいウィジェットを作成し、Application Metrics データセットを選び、タイプを Big Number に設定します。Visualize で convert.estimate.ratio を選び、集計関数を avg から max に変えます。そして、各ワークフローごとに別々の数値がほしければ source.format = mp4output.format = webm のフィルターを追加します。フィルターを付けなければ、全体の最悪ケースをそのまま見ることもできます。

同じダッシュボードは、私が探しに行ったわけではない2つのことも捉えてくれました。

  • Copy モードは約16%過大推定する:Cliparr は必ずしも動画を再エンコードする必要はなく、単に新しい container へコピーするだけで済む場合もあります。しかしコピーの際も、Cliparr はトランスコード用の推定を使っています。各変換の所要時間も記録していたため、まとめてグループ化したときに何が起きているのかが明らかになりました。再エンコードを必要としない変換は1秒未満で終わっており、完成ファイルは推定より約16%小さく出ていたのです。これは次に、コピーモード用に元ファイルのサイズをそのまま使う別の推定機能を追加することで修正できます。

  • GIF は数パーセント一定して過大に出る:GIF の推定はまったく別の方法で行われますが、推定機能が一定して約9%過大推定していることが分かります。GIF 推定機能を手作業で微調整し、平均を1.0に近づけられるか試してみてもよいでしょう。

 

これらはどれも、私が検証しようと設定した仮説ではありませんでした。ひとつの distribution をいくつかの属性でグループ化したことから自然に出てきたものです。

 

KPI #2:人々は実際に何をしているのか?

近いうちに推定の改善に注力する必要があるという前提に立つと、どんなファイルが最も変換されやすく、何に変換されるのかを知っておけると助かります。そうすれば、最も一般的なケースから優先的に取り組めます。各変換に output format と変換設定を属性として追加することで、人々が実際に何をしているのかを見ることができます。

  • 出力フォーマット:mp4 が他のどのフォーマットよりも2.5倍多く、webm がかなり離れて2位、gif・mkv・mov がその後ろで並んでいます。
  • 品質と解像度:このサンプルサイズでは、元の解像度での sharp 品質が最も多い設定で、人々が圧縮よりも変換をしていることをうかがわせます。

 

これでユーザーが何を求めているか分かったので、最も一般的なユースケースから推定機能を優先的に改善でき、今後の機能開発の際にも人々がツールで実際に何をしているかを念頭に置けます。チャットアプリ向けの動画圧縮は私にとって重要でしたが、多くのユーザーにとってはそうではないのかもしれません。もしかすると彼らは、互換性のために動画を別のフォーマットに変換したいだけで、サイズはまったく気にしていないのかもしれません。

 

KPI #3:そもそも動いているのか?

最も面白い KPI ではないかもしれませんが、明らかに重要なものです。変換は実際に完了しているのか、ということです。

このツールは完全にブラウザ内で動作し、オフライン対応かつモバイルフレンドリーだと謳っています。それは不誠実ではないでしょうか。

私は、異なるブラウザやデバイスが WebCodecs を内部でどう扱っているのかを把握していません。エラーは Sentry で追跡できますし、実際にそうしますが、特定の issue から切り離した、成功率・失敗率の履歴ビューを持っておくことも有用です。

3つの counter を使って変換のファネルを描き、どれだけの変換が開始・完了・失敗したかを見てみます。

私のテストでは、データセット内のすべての変換を通して、convert.export.failed は一度も記録されませんでした。良い知らせです! 今はまだほとんど私がテストしているだけですが、将来に向けてきちんと準備が整っています。

とはいえ現時点では、tracing を実装しておらず、metric 自体にデバイス情報を意図的に記録してもいないため、もし問題が起きても、それがどのデバイスやブラウザで発生したのかは実際には分かりません。

私はあえて最小限の情報だけを記録し始めており、後から追加できます。近いうちに tracing を追加する予定で、それによって基本的なデバイス情報が取得され、Sentry 上で metrics とエラーが紐づくようになります。そうすれば、どのデバイスが失敗しているのか、そしてそのエラーが何なのかを見られるようになります。

metrics とデバッグデータの接続については別の記事に譲りますが、今のところ、ツールが意図どおり動作していることを知るには counter で十分です。

 

KPI #4:人々はインストールしているのか?

まだ配線中の、最も新しい KPI です。導入(adoption)のことです。Cliparr Convert はモバイルとデスクトップに PWA としてインストール可能ですが、レポートを出せるアプリストアがないため、人々が実際にインストールしているかどうかをネイティブに知る術がありません。しかし、metrics で追跡することはできます。

ただし、インストールは単一の yes/no ではありません。ブラウザがそのアプリをインストール可能と判断し、私たちがプロンプトを表示し、そして本人がクリックして承諾し、実際にインストールを完了する必要があります(もちろんエラーなどが起きなければ、の話です)。どの段階でも離脱し得るため、いくつかの counter で「ファネル」全体を追跡し、問題があればどこで人々が離脱しているのかを正確に見られるようにします。

各段階が counter になっており、form_factor(desktop か mobile か)と install_mode(ios か native か)でタグ付けされています。Android の Chrome は本物のインストールプロンプトを開けますが、iOS には同等の API がないため、そこでは手動の「ホーム画面に追加」となり、私はユーザーにその手順をお願いすることしかできません。

このようにファネルを分割することで、おそらく私の予想どおりのこと(iOS ではインストールがずっと少ないだろうということ)が見えてくるでしょう。ですが、それを追跡し、時間をかけて改善できることがないかを見られるのは良いことです。

まだ初期段階で、正直に言えば今はほぼ私だけが使っている状態ですが、すべては配線され、準備万端です。実際のトラフィックが来れば、誰がどのデバイスでこのツールを使い、それがどれくらいうまく機能しているのかを、しっかり把握できるようになります。

 

まとめ

今回のことは、特別に凝ったものでも難しいものでもありませんでした。私はいくつかの counterdistribution を配線し、各 metric に、後でデータをグループ化・フィルターしやすくするための属性(output format・quality・resolution など)をいくつか追加しただけです。そうして、かつて手作業で作ろうかと考えていた、フォーマット・codec・品質設定のマトリクスを、実際にすべての組み合わせを回すことなく、事実上そのまま再現するダッシュボードを作ることができました。

私はこれらのダッシュボードウィジェットを「昔ながらのやり方」で作りましたが、Sentry のダッシュボードは Seer を使ってアプリ内で作ることもできます。たとえば「create a dashboard showing the average estimate ratio for each output format, grouped by quality setting and resolution(各 output format の平均推定比率を quality 設定と resolution でグループ化して表示するダッシュボードを作って)」のようなプロンプトを与えれば、パネルを生成してくれます。

そもそもダッシュボードを作る必要すらありません。アプリ内でも MCP サーバー経由でも、あなたのエージェントを通して metrics について直接質問することができます。ここで今後に向けて私が面白いと感じるのは、コードベースに比較的少数の metrics と属性を追加するだけで、プレゼンテーションやレポートのことをすぐに気にしなくても、どれだけ多くの質問に答えられる可能性があるか、という点です。

 

Application Metrics を始めるには

アプリに10個の metrics を追加し、それぞれに5つの属性を付ければ、クエリを1本も書くことなく、ユーザーがアプリをどう使っているか、あるいはアプリのパフォーマンスについて、数百もの質問に答えられる可能性があります。

繰り返しになりますが、ダッシュボードを作る必要すらありません。アプリ内でも MCP サーバー経由でも、あなたのエージェントを通して metrics について直接質問できます。

すでに TracingLogs を使っているなら、Metrics は自然な次の一歩であり、始めるのに必要なコード量は上のスニペットと同程度です。無料の Developer tier を含むすべての Sentry プランに、5GB の Application Metrics が付いてくるので、始めるのにコストはかかりません。Metrics はあなたのテレメトリを単なるエンジニアリングレベルのデバッグを超えて、プロダクトレベルの質問(人々が何をしているか、何がうまくいっているか、そして変更が本当に効果をもたらしたか)にも答えられる領域へと引き上げてくれます。

私の AI エージェントは、最大83%も外れるサイズ推定機能を書きました。そして、いくつかのシンプルな KPI を Application Metrics でモニタリングしていなければ、私はそれに気づかなかったかもしれません。もしアプリにとって重要な数値があるなら、それが logs や traces に属するのか、それとも独自の metric に値するのかを、ぜひ考えてみてください。

 

FAQ


 
■ logs や traces ではなく Application Metrics を使うべきなのはどのような場合ですか? 

アラートを設定したい数値(count、rate、あるいは1つ1つの計測が重要になる distribution)があるときは、metrics を使いましょう。counter・gauge・distribution は KPI のために作られています。logs は調査や、豊富なコンテキストを保持するのに向いており、traces は1つのリクエストをシステム内で追跡するのに向いていますが、traces は一般的にサンプリングされるため、正確な合計を必要とする KPI には不向きです。

■ Sentry Metrics における counter・gauge・distribution とは何ですか?

これらは3つの metric タイプです。counter は何かが起きた回数(完了した変換、投げられたエラー)を追跡します。gauge はある時点で上下する値(キューの深さ、アクティブユーザー数)を記録します。distribution は多数の計測値の広がりを記録するため、p50 や p90 のようなパーセンタイルを読み取れます。レイテンシや今回のケースのような推定精度に最適です。

■ Sentry Application Metrics は traces のようにサンプリングされますか?

デフォルトでは、いいえ。metrics はすべての計測を取得しますが、traces は一般的にサンプリングされ、span の一部だけを保持します。そのため metrics は、1つ1つのイベントが重要な count・rate・distribution により適しています。サンプリングされたデータから計算した成功率や稀な失敗のカウントは、まさにあなたが気にしているイベントを取りこぼす可能性があります。

 


 

 

Original Page: Application Metrics caught my broken size estimator

 

 




IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談は「お問い合わせ」からお気軽にお問い合わせください。

 

シェアする

Recent Posts

;