【エラー・トレース・ログ・メトリクス】いつ何を使うか

Article by: Sergiy Dybskiy (読了時間:12分)     コードをインストルメントするとき、「ログを使うべきか、トレースか、メトリクスか」という問いに何度もぶつかります。コーディングエージェントも同じ壁にぶつかっているのを目にします。答えは明白なように思えますが、実はそうでもありません。エラー・トレース・ログ・メトリクス は、アプリの大半を支える4種類のテレメトリです。 4つはいずれも同じ道具箱に入ったツールであり、役割も重なる部分が多いため、正直なところ答えは開発者の口癖である「場合によります」です。ログに記録するはずのコンテキストをスパンの属性として持たせることもできますし、メトリクスを出力する代わりにログイベントをカウントすることもできます。また、duration を追加してスパンと見なすこともできます。 [スパイダーマンのミームを入れようとしたのですが、法務部門から著作権侵害になると言われたので削除しました。] ただし、「できる」と「すべき」は別の話です。各シグナルは異なる問いに答えるために存在しており、届いた後のワークフローもそれぞれ異なります。しっかりとした指針がなければ、慣れ親しんだものや既にあるものに手を伸ばしてしまい、他の種類のシグナルが本来何のためにあるかを見落としてしまいます。 この記事は、自分自身とエージェントのために書きたかった指針です。スキルだけ欲しい方は末尾まで読み飛ばしてください。 Sentry では、エラー・トレース・ログ・メトリクスのすべてがひとつの SDK から取得でき、すべてのプランに含まれています。エラーと Sentry Tracing は長年使われてきた機能ですが(それぞれ 2012年 と 2020年 から)、構造化ログは昨年追加され、Application Metrics は今年5月にラインナップが完成しました。Sentry をしばらく使っているなら、エラーとトレースはすでに送信されているはずです。ログとメトリクスは、テレメトリの全体像を完成させるための、残りの道具です。     エラー・トレース・ログ・メトリクス:それぞれが答える問い エラー:「何が壊れたのか」 スタックトレースと例外の種類が、Issue としてグルーピングされ、重複排除・アサイン・解決まで追跡されます。コードが例外を投げたなら、それはエラーです。 トレース:「リクエストは想定どおりに送信されたのか」 トレースは、タイミング付きのスパンのウォーターフォールです。リクエストがサービスを横断して、どのように送信されたかを追跡し、時間の使われ方を把握するためのものです。遅くなったDBクエリ、タイムアウトしたAPI呼び出し、200msのはずが8秒かかったLLMのツール呼び出しなどが見えてきます。 メトリクス:「時系列でどう推移しているのか」 Counter・Gauge・Distribution として保持され、任意の属性でスライスでき、集計値から背後にあるサンプル(およびトレース)まで掘り下げられます。「今週のチェックアウト件数は12,000件」という数字だけでなく、米国から8,400件・EUから2,600件・その他から1,000件という内訳も、直近のデプロイ前後で数値がどのように推移したかも把握できます。メトリクスは現在だけでなく過去のシグナルでもあるため、ダッシュボードやアラートとの相性が抜群です。(ただし Sentry ではほぼすべてのシグナルにアラートを設定できます。) ログ:「コードのこの箇所で何が起きていたのか」 コードのある瞬間のシステム状態を構造化イベントとして記録したものです。設定値・フィーチャーフラグ・関数の入出力・ユーザーIDなどが含まれます。ログは関数の意思決定ツリーをたどる手掛かりです。コードが分岐する地点に残すマーカーであり、後から人間やエージェントがその判断の流れを追えるようにします。エラーとトレースが「何が壊れたか」「どこに時間がかかったか」を教えてくれた後、「なぜ」を補うのがログです。   実例(に近いもの) React フロントエンドと Python API を持つストアフロントを運営しているとします。サポートからチケットが転送されてくるようになりました。アカウントページの商品レコメンドが、ログイン済みの一部ユーザーに対して汎用的な内容(パーソナライズされたおすすめではなくベストセラー)を表示しているというのです。どうも様子が変です。 何かクラッシュしていないか? 最初に確認するのは Issues です。React アプリに例外はなく、リクエストも失敗しておらず、/recommendations/{user_id} […]

【Next.js / Supabase オブザーバビリティ設計】バイブコーディングから本番運用へ

Article by: Sergiy Dybskiy   ここ数年で、ソフトウェアの作り方は大きく変化しました。一方で変わっていないのは、そのソフトウェアが最終的に「実際の人間」に届くという事実です。あなたや私、そして私の母のような人たちです。 そして、そうしたユーザーが必然的に何かしらの不具合に遭遇したとき、アプリケーションの開発者であるあなたは、何が壊れたのか、どこで壊れたのか、そしてそれをできるだけ早くどう修正するのかを理解するための適切なツールとコンテキスト、そして認識を備えている必要があります。 私たちは日々、「自己修復するソフトウェア」に少しずつ近づいています。Next.jsアプリケーションを構築し、バックエンドサービスとしてSupabaseを利用している場合、以下で説明するツールは、より高品質なソフトウェアを生み出すことと、すり抜けてしまった問題を最小限の影響で修正するという、自己完結的なループに一歩近づく助けになります。   要約 Supabaseはクエリパフォーマンスのインサイト、行レベルセキュリティ(RLS)のアドバイザリ、Edge Functionのログを標準で提供しているが、フルスタックを横断したトレースはできない Sentryはそのギャップを埋める:Next.jsのフロントエンドからSupabase Edge Functions、Postgresまでをまたぐ分散トレースを一箇所に集約できる SupabaseからSentryへログをドレインすることで、エラー・トレース・インフラログの単一の信頼できる情報源を作れる SentryはN+1クエリ、遅いスパン、パフォーマンス劣化を手動設定なしで自動検出する SentryのAIデバッガー「Seer」は新しい問題に対して原因を自動で推定し、修正をコーディングエージェントに引き渡すことができる     エージェントが生み出すスタック問題 AI支援開発には特有の失敗モードがあります。エージェントは動作するコードを生成できますが、そこにオブザーバビリティが組み込まれていないことが多いという点です。その結果、Next.jsアプリがSupabaseと通信する方法が3種類(直接Postgres接続、Supabase JS SDK、そしてDrizzle、エージェントが戦略を切り替え続けたため)混在することもあり得ます。さらにDeno上で動くEdge Functionが加わり、実行時に何が起きているのかを統一的に把握できない状態に陥ります。 もう一つの失敗モードはより見えにくいものです。エージェントはインデックスを忘れることがあります。ローカル環境ではデータが40行程度しかないため問題にならず、N+1クエリを書いてしまうこともあります。しかし本番にデプロイし、データベースが400行に増えると、検索クエリが突然10秒かかるようになります。Sentryはこれを自動的に検出できますが、それは最初から正しく計装されている場合に限られます。 この計装を正しく行うには、SupabaseとSentryがどのように組み合わさるかを理解する必要があります。   Supabaseの組み込みオブザーバビリティとその限界 Supabaseには堅牢な組み込みオブザーバビリティがあります。ダッシュボードのQuery Performanceパネルでは、どのクエリが最も頻繁に実行されているか、どれが最も時間を消費しているかを確認できます。パフォーマンス問題が発生した際に最初に見るべき場所です。 またAdvisorsは、RLSポリシーの不足などのセキュリティ問題を検出し、重要度に応じて優先順位付けします。Index Advisorは不足しているインデックスを指摘し、それらが本番インシデントになる前に可視化します。 Logsセクションでは、Supabaseのすべてのサブシステムから構造化ログを取得できます。対象にはEdge Functions、Postgres REST API(PostgREST)、コネクションプーラー、ストレージ、cronジョブなどが含まれます。これらのログはダッシュボード上でSQLを使って直接クエリすることも可能です。 これは確かに非常に有用です。ただし、Supabaseの内部で観測できる範囲に限定されるという制約があります。つまり、Supabaseの外側で起きていることまでは見えません。例えば、遅いPostgresクエリがNext.jsフロントエンドのどのユーザーアクションによって発生したのか、あるいはEdge FunctionのタイムアウトがAPIレイヤー全体にどのようなエラーの連鎖を引き起こしたのか、といった因果関係は把握できません。こうした情報を得るには、フルスタックを横断した分散トレーシングが必要になります。   SupabaseログをSentryに接続する SupabaseのデータをSentryに取り込む最も簡単な方法は、log drainを使うことです。Supabaseダッシュボードの「Logs > Drain」で送信先を追加し、SentryのDSNを貼り付けると、そのSupabaseプロジェクトのすべてのログが対応するSentryプロジェクトへ流れ込むようになります。 この仕組みについて、いくつか重要な点があります。 現時点では「全量送信(all-or-nothing)」であり、Supabase側でログレベルによるフィルタリングはできません。 ログがSentryに入った後は、Log Explorer上で severity:warn や severity:error のようにフィルタリングできます。 log drainはNext.jsアプリやEdge […]

JavaScript のオブザーバビリティを修正する:ライブラリ単位での改善

Article by: Abdelrahman Awad   ここ数週間、私たちはクロスエコシステムでの取り組みとして、現在すべての JavaScript APM ツールを支えている「モンキーパッチング」をランタイムに組み込まれた仕組みに置き換える作業を進めてきました。ここでは、その背景と仕組み、そして現状について説明します。 この内容はサーバーサイド JavaScript(Node.js、Bun、Deno、Cloudflare Workers)のみに適用されます。ブラウザには diagnostics_channel が存在せず、またそれをポリフィルするために必要な非同期コンテキスト伝播の仕組みも備わっていません。   モンキーパッチングはスケールしない 私のチームメイトである Sigrid は、なぜモンキーパッチングが破綻しつつあるのか、そして TracingChannel がそれをどう解決するのかについて詳しく解説しています。 要点をまとめると、JavaScript のすべての APM ツール(Sentry を含む)は、実行時に require() や import をフックし、import-in-the-middle(IITM)や require-in-the-middle(RITM)を使ってライブラリをインストルメントしています。しかしこの仕組みは ECMAScript Modules(ESM)で壊れやすく、Node 以外のランタイムでは動作せず、バンドラとも衝突し、さらに制御できない内部実装に依存する構造になっています。また SDK は対象ライブラリより先に読み込まれていなければならず、そうでない場合は計測が静かに失敗します。 これは Sentry 固有の問題ではありません。JavaScript のインストルメンテーションを提供するすべての APM ベンダーが、同じ不安定さを抱えています。エコシステム全体が行き詰まっている状態です。 多くのライブラリメンテナーはオブザーバビリティを前提にしていません。何を公開すべきかも分からず、OpenTelemetry のような仕組みを導入することは標準化というより実装負担になります。これまで APM 側がパッチで吸収してきたため、ライブラリ側が対応する必要がありませんでした。 しかし、より良い方法があります。   TracingChannel:パッチ不要のオブザーバビリティ 2025年後半、私たちは Nitro、h3、そして unjs エコシステムの開発者である Pooya Parsa […]

【Android tombstone】ネイティブクラッシュ解析の大幅改善

Article by: Mischan Toosarani-Hausberger , Roman Zavarnitsyn (了読時間:13分)     Androidにおけるネイティブクラッシュは、これまで本来あるべきよりもデバッグが難しいものでした。 Androidには独自のクラッシュレポーター(debuggerd)があり、クラッシュしたスレッド、実行中の他のすべてのスレッド、レジスタ状態、メモリマップを tombstone と呼ばれるファイルに記録します。tombstone は長年Androidの一部であり、実際にはAndroid最初期のコミットの頃から、形を変えつつ存在してきました。 問題は、Androidの歴史の大半において、アプリ内部から tombstone をプログラム的に読み取ることができなかったことです。そのため、SDKベースのネイティブクラッシュレポート機能(私たちのものを含む)は、プラットフォーム側ですでに存在している仕組みを独自に再実装せざるを得ませんでした。その代償として、バイナリサイズの増加、不完全なJavaフレームのシンボリケーション、さらに変化し続けるAOSPに追従するために維持しなければならないC++フォークが発生していました。 Android 11(SDK level 30)では ApplicationExitInfo が導入されました。さらに Android 12(SDK level 31)では、ApplicationExitInfo.REASON_CRASH_NATIVE に対する trace input stream へのアクセスが追加されました。 SentryのAndroid SDKは、バージョン8.30.0以降、Android 12以上を実行しているすべてのデバイスでこのストリームを読み取り、ネイティブクラッシュイベントとして送信します。これにより、ネイティブコードを使用するAndroidアプリのクラッシュレポートは大幅に改善されました。基本的なクラッシュ通知だけが必要なチームにも、詳細なデバッグ情報が必要なチームにも有効です。 ここからは、以前はどのように動作していたのか、既存のNDK統合を壊さずにこれをSDKへ組み込むために何が必要だったのか、そしてこれによってどのような改善がもたらされたのかを見ていきます。   tombstoneサポート以前:変化し続けるターゲットを追い続けるフォーク tombstoneサポート以前、Android SDKでは Native SDK(sentry-native)がネイティブエラーレポートの主要な仕組みとして使用されていました。AndroidはLinuxベースであるため、SDKのかなりの部分を再利用できました。しかし再利用できない部分については、2019年からAndroid固有コードの統合作業が始まりました。 特に、libunwindstack(現在も debuggerd、そして tombstone のスタックトレース生成に使用されているAOSPのプラットフォームアンワインダ)を統合したことは、Sentry Android SDKでネイティブクラッシュをサポートする上で重要な転機となりました。なぜかというと、Native Development Kit(NDK)には汎用的なスタックウォーカーが存在しなかったからです(今でも存在しません)。 libunwindstack はNDKの一部ではなく、Android Open Source Project(AOSP)のプラットフォームコードの一部であるため、通常の方法ではアプリ開発者から直接利用できません。Sentryは、NDKでビルドできるようプラットフォームコードへパッチを当てたリポジトリをフォークし、その後も上流のパッチ版に変更がないまま、そのフォークを維持してきました。 これにより、非常に複雑なAndroid […]

【React Native】Sentry にログを送る

Article by: Lewis D.       Logs は、開発チームが問題を調査するときに最初に確認することが多い場所です。しかし、Logs は後回しで追加されることが多く、開発者は「ログを出しすぎる/出さなさすぎる」のバランスに悩みがちです。 経験豊富な開発者なら、調査を頼まれて 200MB のプレーンテキストのログファイルを渡された経験を覚えているかもしれません。3 時間と 4 本の Python スクリプトを費やした末に、問題が別のコンポーネントにあると分かる、というようなことです。 これまで、ロギングを簡単にするための多くの標準やライブラリが作られてきましたし、React Native にはロギング関数も豊富にあります。私たちの React Native ロギング入門ガイドは良い出発点です。ただ、さらに一段レベルを上げたいなら、このガイドで Sentry のロギング機能を使う方法を紹介します。これにより、ログが有用になり、必要な情報をすぐに取り出せるようになります。   Sentry に Logs を取り込む このガイドでは、シンプルな React Native(Expo)アプリを使って、Sentry のさまざまなロギング機能の例を示します。 このアプリは、フィールドに基本的なバリデーションがある問い合わせフォームです。手元で同じように試したい場合は、デモリポジトリ内にこのアプリがあります。 デモの React Native アプリのインターフェース   既存の React Native アプリケーションがある場合やこれから作る予定がある場合でも、このガイドでは、Sentry を使ったロギングを最大限に活用するために必要な手順を説明します。   セットアップ Sentry の機能を使い始めるには、まずプロジェクトに Sentry を導入する必要があります。最初に Sentry で新しいプロジェクトを作成し、プラットフォームとして React […]

【Logs と Next.js】壊れたものがすべてエラーとは限らない

Article by: Sergiy Dybskiy     スタックトレースは便利ですが、教えてくれるのは「何が壊れたか」だけで、「なぜ壊れたのか」を教えてくれることはほとんどありません。例外が発生すると、物事が崩れた瞬間のスナップショットは得られますが、そこに至るまでのコンテキストは消えてしまいます。 そこで Logs の出番です。適切な場所に Logs があることで、何時間も悩む羽目になるか、5 分で直せるかの分かれ道になります。最近私が遭遇した実際のバグを例に、その意味をご説明します。     ボットから AI 搭載の Next.js エンドポイントを守る 私は WebVitals という、AI を活用した Next.js アプリケーションを開発していました。ドメインを入力すると、パフォーマンスデータを取得するために一連のツール呼び出しを実行し、その結果を AI エージェントが解析して、Web Vitals を改善するための実行可能な提案を返します。 フロントエンドでは会話のやり取りを扱うために、AI SDK の useChat フックを使っています。 /api/chat エンドポイントは標準的な Next.js の API ルートなので、誰でもどこからでもアクセスでき、各リクエストにはコストがかかります(OpenAI は無料ではありません)。そのため、ボットや悪意ある攻撃者がリクエストを大量に投げて請求額を跳ね上げようとするのを防ぐ仕組みが必要でした。 Vercel にはそのための良い解決策があります。 checkBotId 関数によるボット対策です。受信したリクエストを見て、ボットからのものかどうかを判定します。シンプルで効果的で、ユーザーに横断歩道を選ばせる CAPTCHA も不要です。   Firefox と Safari にだけ影響する本番バグ ローカル開発ではすべて完璧に動いていました。本番にデプロイして、Chrome でテストしても問題なし。ところが、Firefox […]

【Unity SDK 4.0.0】ゲーム機対応、ログ、ユーザーフィードバックなど

Article by: Stefan Jandl      Sentry の Unity 向け SDK 4.0.0 をリリースしました。 これはこれまでで最大のアップデートです。このメジャーリリースでは、ゲーム機への包括的な対応、構造化ログ、ユーザーフィードバック機能、そしてあらゆるプラットフォームでより良いゲームを作るための重要な改善が追加されています。新機能は以下のとおりです。     ゲーム機対応 Unity 向け Sentry SDK は、Xbox と PlayStation をネイティブにサポートするようになりました。 これにより、Sentry のエラートラッキングの全機能がゲーム機にも提供されます。SDK は scope をネイティブ層へ自動的に同期するため、ゲームがゲーム機上でクラッシュした場合でも、取得された issue には C# の適切な行番号を含む完全なスタックトレースが付与されます。 さらに Sentry は、カスタムコンテキスト、タグ、breadcrumbs も提供します。こうした全プラットフォームで統一された体験により、問題がどこで発生したかに関わらず、トリアージと修正が容易になります。   構造化ログ 構造化ログが、Unity 向け Sentry SDK で本番利用可能になりました。つまり、ログ出力がゲーム内のエラー、クラッシュ、パフォーマンス問題に直接つながるようになります。 SDK は設定に応じてデバッグログの出力を自動的に取り込み、Sentry 上で閲覧・検索できる構造化ログエントリを作成します。プレイヤーがシーン読み込み中にクラッシュしたり、ロード画面で止まってしまったりした場合でも、問題に至るまでのログの流れをすべて追えるため、再現が難しい問題の診断が大幅に容易になります。   User Feedback(ユーザーフィードバック) User Feedback のサポートが、Unity 向け […]

よくある Unity エラーと対処法

Article by: Abuld D.     Unity では、開発中に思いがけない挙動に出会うことがあります。ホットリロード直後のプレイモードのフリーズ、突然広がるピンク一色のマテリアル、あるいは「transform はずっと null でしたよ」と丁寧に思い出させてくるスタックトレースなど。そんな瞬間にスプリントの残りが崩されないように、本記事では実行時によくある厄介者を4つに絞り、それぞれをどう再現し、どう見分け、どう直すかを具体的に紹介します。 扱う内容は次のとおりです。 NullReferenceException: Object reference not set to an instance(オブジェクト参照がインスタンスに設定されていません) IndexOutOfRangeException: Array index problems(配列/リストのインデックスが範囲外です) MissingComponentException: Component not found(必要なコンポーネントが見つかりません) MissingReferenceException: Destroyed object access(破棄済みオブジェクトへの参照にアクセスしています)   具体性を担保するために、まっさらな HDRP サンプルプロジェクト上で各エラーをすべて作り直し、余計なものを省いた SentryCube スクリプトを組み込んで、問題(と修正)がリアルタイムでどう起きるかを確認できるようにしました。コードをそのままコピーしても良いですし、コンソールに出ている内容に一致するスニペットだけ流し読みしても良いですし、解決策セクションに飛んでも構いません。とにかく、より早く開発に戻れるやり方で進めてください。     1. Unity で NullReferenceException(Object reference not set to an instance)を修正する方法 このエラーはスクリプトが null の参照を使おうとしたときに発生します。ゲームのコンソールやログファイルでは、通常次のような表示になります。 UnassignedReferenceException: The […]

【Cocoa SDK 9.0.0】リリース!

Article by: Philipp Hofmann     Cocoa SDK 9.0.0 をリリースしました。新機能と変更点をご紹介いたします。 前回のメジャーバージョンアップから、ずいぶんと時間が経ちました。前回のメジャーリリースであるバージョン 8.0.0 が公開されたのは、2023年1月16日のことです。その後、57回のマイナーアップデートと47回のバグ修正リリースを経て、ついに新しいメジャーバージョン 9.0.0 をお届けする時が来ました。   なぜ今なのか 私たちの最小サポート OS バージョンはかなり古くなっており、その結果、一部のユーザーが望まないほど多くの Xcode の警告を目にするようになっていました。「互換性は絶対(Compatibility is King)」を少し重視しすぎていたようです。だからこそ、メジャーアップデートを実施し、サポートする最小 OS バージョンを引き上げるのに最適なタイミングだと判断しました。     今回はどのようなリリースなのか バージョン 9 は「メンテナンス系メジャー」リリースです。 具体的には以下の通りです。 最小 OS バージョンの引き上げ いくつかの機能をデフォルトで有効化 多くの細かい API の問題を整理   アップグレードは簡単に行えるはずです。…そう言ってハマるのがお約束ですが。     知っておくべき変更点 バージョン 9 における変更点のほとんどは、「プラットフォーム要件」「デフォルトで有効になった機能」「以前から予定していたクリーンアップ」の 3 つに分類されます。 主要なポイントは以下の通りです。   サポート対象の最小 OS バージョンを更新 […]

「ミニ」じゃなかったミニダンプ!SteamOSで見逃されていたクラッシュを発見

Article by: Amir Mujacic   私たちは Sentry のゲームエンジンとネイティブ SDK のアップデートをリリースしましたが、Windows でビルドしたゲームを Linux 上で Wine / Proton 互換レイヤーを使って意図的にテストしている場合を除いて、おそらくほとんどの開発者はこれまで気づいていなかったと思います。それこそが狙いです。 ゲームエンジン SDK の改善に取り組んでいる最中、謎の問題を調査する中で得た知見は、Wine やその他の互換レイヤーを介して Linux 上で動作するあらゆる Windows アプリケーションにも当てはまります。そしてそこに至るまでの経緯自体が語る価値のあるストーリーだったのです。     謎:なぜクラッシュレポートが届かないのか きっかけは、あるゲームスタジオからのサポートチケットでした。 「Sentry は Windows ではうまく動いているのですが、Steam Deck のクラッシュでは何も届きません。」 おかしい… 私たちはテスト用ゲームを SteamOS 上で動かしましたが、Linux ビルドをテストすれば、問題なく動作します。次のステップは、多くのゲームと同じように互換レイヤーを介して、SteamOS 上でテスト用ゲームを動かすことでした。非致命のエラーはきちんと拾える。ログも例外もパフォーマンスデータも一通り見えます。ところが実際のクラッシュだけは、反応ゼロ…。 最初の直感:アップロードパイプラインを確認しました。ネットワークの問題?認証?いいえ。非クラッシュイベントに関してはすべて正常に見えました。 そこで Steam Deck のテストデバイス上のローカルストレージを確認しました。 すると 15 個のクラッシュダンプがありました… それぞれが 500MB 超えで、デモゲームなのに、ヒープメモリがダンプされていない状態としては異常な大きさです。 参考までに言えば、同じゲームの通常の Windows クラッシュダンプは 50〜80KB 程度です。何かが壊滅的におかしかったのです。 […]

;