【Sentry JavaScript SDK v11】すべてのJSプラットフォームでトレーシングに対応

Article by: Isaac Z. Schlueter(読了時間:12分)     本記事では、Sentry JavaScript SDKの最近の変更について紹介します。JavaScriptでSentryを使っていない方にも、変更の経緯や背景を知るうえで参考になる内容です。 Sentry JavaScript SDK v11では、トレーシングインテグレーションの仕組みを作り直しました。OpenTelemetry標準には引き続き対応していますが(詳しくは後述)、以前のバージョンのようにOpenTelemetryのインストルメンテーションクラスを使うのではなく、コードトランスフォーマーで依存関係をインストルメントするようになりました。 この仕組みは、アプリケーションパフォーマンス監視(APM)ベンダー各社が共同で取り組んでいるapm-js-collabのパッケージ、@apm-js-collab/code-transformerと@apm-js-collab/tracing-hooksをベースにしています。   インジェクションとサブスクリプション 新しいトレーシングインストルメンテーションは、2つの部分で動作します。1つ目はモジュールの読み込み時にdiagnostics channelを注入し、2つ目はそのチャネルのイベントを受け取ってトレーシング情報を集め、Sentryに送信します。   パート1:インジェクション 対応するモジュールが読み込まれると、実行時でもバンドラーの処理の中でも、トランスフォームがソースを書き換え、対象となる関数をtracingChannel()の呼び出しでラップします。 各トランスフォームは、パッケージ名、semver範囲、パッケージ内のファイル、関数を指定した設定に基づいて動作します。 トランスフォーム後のmysqlモジュールは、query関数が呼ばれるたびにstart、end、error、asyncStart、asyncEndのdiagnosticsイベントを発行するようになります。   パート2:サブスクリプション 各Sentryインテグレーション(mysqlIntegration、redisIntegration、openAIIntegrationなど)は、それぞれのチャネルをサブスクライブし、イベントをSentryのスパンに変換します。 サブスクライバーは余分なチャネルを作らないよう、対象のモジュールが実際に読み込まれたことを確認するまで待機します。   実行時とビルド時のインジェクション 同じトランスフォームが2つの場所で実行され、両方を同時に有効にすることもできます。モジュールはバンドラー経由かnode_modulesからのどちらか一方で読み込まれるため、二重にラップされることはありません。   実行時 最近のバージョンのNodeやDeno 2.8.3以降では、Sentry.init()が自動的にregisterDiagnosticsChannelInjection()を呼び出し、Module.registerHooks APIを使って、それ以降に読み込まれる対応モジュールをインストルメントします。 DenoとNodeのSDKが提供するimportエンドポイントを使えば、アプリの読み込み前にフックを登録することもできます。   ビルド時 bun buildを使っている場合や、Viteやesbuildなどのバンドラーでプログラムをバンドルしている場合は、提供されているプラグインを使って、アプリケーションへのビルド時にモジュールをインストルメントできます。 @sentry/nodeはVite、Rollup、webpack、esbuild向けのプラグイン、@sentry/cloudflareはVite向けのプラグイン、@sentry/bunはbun build向けのプラグインを提供しています。Next.jsでは、webpackローダーがwebpackとTurbopackの両方に組み込まれます。 プラグインはインストルメント対象の依存関係をバンドル時にトランスフォームし、バンドルされたモジュールが最初に評価されたときに、そのモジュール(およびサブスクライバーファクトリー)をグローバルマーカーに登録するスニペットを差し込みます。 使い方は、ほかのSentryバンドラープラグインと同じです。   v11以前のアプローチ v11以前、Sentryのインテグレーションはほぼすべて、OpenTelemetryのインストルメンテーションAPIをベースにしていました。オープンソースコミュニティの成果を活用できましたが、JavaScriptプラットフォームの選択肢が広がるにつれて深刻になっていくという大きな欠点がありました。   OpenTelemetryインストルメンテーションの内部 @opentelemetry/instrumentation-expressのようなOpenTelemetryインストルメンテーションパッケージは、InstrumentationBaseを継承したクラスをエクスポートします。このクラスでは、パッケージ名、対応するsemver範囲、patch(moduleExports, version)関数を宣言します。また、InstrumentationNodeModuleFileエントリを宣言して、パッケージ内の個別のファイルだけにパッチを当てることもできます。 registerInstrumentations()は、2つのローダーフックをインストールします。 require-in-the-middle — […]

Unreal MCPがSentryに対応しました

Article by: Ivan Tustanivskyi(読了時間:7分)     ゲームのリリース作業の中で、クラッシュレポートの設定が一番楽しい作業だということはまずありません。DSNを貼り付け、Project Settingsでいくつかのチェックボックスを切り替え、シンボルアップロードを有効にし、ビルドをパッケージ化して、わざとクラッシュさせ、イベントがSentryに届いているか確認する…。難しくはありませんし(重要な作業でもあります)、それでも、できれば誰かに任せたいと思うような作業です。 Unreal Engine 5.8では、その「誰か」をコーディングエージェントにできます。これまでエージェントにできたのはC++の読み書きだけで、エディタはエージェントにとってブラックボックスのままでした。 Unreal MCP は、エディタ内でファーストパーティのMCPサーバーを動かし、エージェントがエディタを直接操作できるようにする、新しい実験的なエンジン機能です。Epicは標準で、アクターのスポーン、マテリアルの作成、自動テストの実行など、数百ものツールを提供しています。 Sentryにとって重要なのは、このツール一覧が固定ではないという点です。プラグインはC++またはPythonで独自のツールをエディタに登録でき、エージェントからはEpicのツールと同じように見えます。Unrealプラグインが利用しているのはまさにこの仕組みです。Claude Code、Cursor、Codexなど、どのエージェントを使っていても、Sentryのセットアップ、プロジェクトのインストルメント、キャプチャしたクラッシュのデバッグ支援に必要なものがすべて揃いました。   Sentryプラグインでできること MCPを有効にした状態でエディタを起動すると、Sentryプラグインは、実行中のエディタ内からSDKを確認・変更できる小さなツールセットと、その使い方をエージェントに伝える複数のエージェントスキルを登録します。 ツールが「手」なら、スキルは「手順書」です。Claude CodeやCursor向けのSentry agent pluginを使ったことがあれば、見覚えがあるはずです。同じワークフローをUnreal向けに調整したものだからです。 Get Started — SentryアカウントからDSNを取得して適用し、テストイベントが届くことを確認します。 Fix Stack Traces — デバッグシンボルの自動アップロードを有効にし、必要な認証情報の設定を手伝います。 Instrument — クラッシュのキャプチャに加えて、トレーシング、構造化ログ、メトリクス、セッションリプレイ、ユーザーフィードバックを設定します。 Debug Issue — Sentryのイシューのコンテキストをすべて取得し、プロジェクトのソースと照らし合わせて根本原因を特定し、修正のリリースまでを支援します。   各スキルには、セットアップのときに隣に座っていたら伝えるようなアドバイスが組み込まれています。 Get Started は、エディタのDSNがプロジェクトのDSNより優先されることを把握しているので、何かを変更する前にDSNの出どころを確認します。 Fix Stack Traces は、シンボルアップロードがパッケージビルドでしか実行されないことを把握しているので、フルビルドを待ってから問題に気づく、ということがないよう、先に認証情報を検証します。 さらに、どのスキルも同じ基本ルールに従います。プロジェクトを変更する前に確認を取り、認証トークンなどのシークレットを読み取ったり表示したりすることは一切ありません。設定はその場で適用されるため、エディタを再起動する必要もありません。   セットアップ手順 必要なのはUnreal Engine 5.8とSentryプラグイン1.24.0以降だけです。それ以外はすべて同梱されています。 1. […]

【Sentry Laravel AI】インテグレーションができるまで

Article by: Martin Linzmayer(読了時間:4分)   先日のAgent Hackweek(好きなAIやエージェント関連のプロジェクトに1週間取り組めるSentryの社内イベント)で、同僚からLaravel AIインテグレーションを作らないかと誘われました。他のフレームワーク向けにすでに提供しているAgent TracingのサポートをLaravel AIで構築したエージェントにも広げることが目的です。 いいアイデアだと思いました。彼は以前、PythonベースのエージェントのためにSentryのAgent Tracingを構築しており、ドメイン知識をすでに持っていましたし、このイベントではAIを使うことになっていたので、言語の壁も大きな問題にはなりませんでした。   不要だった防御的なコード Claudeならコーディングはそれなりにこなしてくれるだろうと、かなり自信がありました。Laravelは型付きのデータを持つEventsを公開しているので、データの形はほぼ把握できるはずです。 ところが最初のレビューで、Claudeは実際にはデータの正しい形を把握できておらず、フィールドにできるかぎり汎用的な方法でアクセスするヘルパーを作っていたので、少し驚きました。 しばらくPHPから離れている方のために説明すると、このスニペットは構造に関係なく、配列やオブジェクトから値を取り出そうとする汎用ヘルパーです。$source->{$key} は $key を文字列の値に解決し、そのフィールドにアクセスします。言うまでもなく、これは良いPHPコードとは言えません。たいていの場合、データの形はもっと限定されているため、役に立つ場面はほとんどありません。   Laravel AIのライフサイクルにフックする PythonやJavaScriptでのインストルメンテーションは、比較的簡単なことが多く、関数をラップしたり、パッチを当てたりするだけで済みます。しかし、PHPではそうはいきません。フレームワークやライブラリのフックに頼るか、ユーザーにクラスを独自のものへ置き換えてもらう必要があります。後者をできるだけ避けているのは、ユーザーにコードの書き換えを求めるようでは、インテグレーションとは呼べないからです。幸い、Laravel AIは重要な部分のほとんどでイベントを発行します。ただし、すべてではありません。 Laravel AIにはライフサイクルにフックする手段が十分そろっているように見えました。PromptingAgent と AgentPrompted イベントはエージェントとのやり取り全体を、InvokingTool と ToolInvoked は個々のツール呼び出しをカバーしています。 Agent Tracingには、もう一段細かい粒度が必要です。LLMの呼び出しを1回ずつ、個別のChatスパンとして表示しなければなりません。Laravel AIはこうした呼び出しに対するイベントを公開していないため、ライフサイクルイベントだけに頼ると、トレースに大きな抜けが生じてしまいます。   LLM呼び出しとHTTPリクエストを照合する ほとんどのLLM呼び出しは、最終的にHTTPリクエストになります。Laravelにはそのためのイベントとして RequestSending と ResponseReceived があります。エージェントとのやり取り中に発生したすべてのHTTPリクエストにChatスパンを作成することもできますが、それではツールによるHTTP呼び出しなど、無関係なリクエストまでキャプチャしてしまいます。 LaravelのHTTPイベントにはAI呼び出しのIDが含まれていないため、リクエストを直接関連付けることはできません。そこで、アクティブな呼び出しごとに設定済みのプロバイダーURLのプレフィックスを保存し、送信されるすべてのリクエストのURLと比較することにしました。複数のアクティブな呼び出しが一致した場合は、最後に開始されたものにリクエストを関連付けます。一致したリクエストだけがChatスパンになるため、個々のLLM呼び出しを取りこぼすことなく、無関係なHTTPトラフィックを除外できます。   設定不要のトレーシング Laravel AIインテグレーションは、sentry-laravel 4.27でリリースされました。すでにSentryのトレーシングを有効にしているアプリケーションなら、SDKをアップデートするだけです。インテグレーションの登録も、Sentry固有のコードの追加も必要ありません。通常のLaravel AIエージェントは自動的にトレースされ、Conversational を実装すればConversationsにも対応します。 Sentryのコードはどこにもありません。このクラスからのエージェント呼び出し、LLMリクエスト、ツール呼び出しはAgent Tracingに表示され、会話のコンテキストはExploreのAgentsセクションに表示されます。   Sentryで確認する […]

【dataCollection のご紹介】スイッチ1つからコントロールパネルへ

Article by: Sigrid Huemer(読了時間:6分)     本記事とコード例はJavaScript SDKを対象としています。別のプラットフォームをお使いの場合でも、今回の変更の背景や今後の展開を理解するために、ぜひご一読ください。 Sentry では、真偽値(boolean)の sendDefaultPii を、dataCollection という新しいオプションに置き換えます。従来のスイッチはオンにすればすべて取得、オフにすればごく一部しか取得できない、オールオアナッシングの仕組みでした。cookie は除いて request header だけがほしい、あるいはユーザーのメールアドレスまで送らずに GenAI の入力だけがほしい。そんな場面に出くわしたことがあれば、この仕組みの物足りなさはおわかりでしょう。dataCollection はこの1つのスイッチをいわばコントロールパネルに近いものへと変えます。データのカテゴリごとに、上げる・下げる・絞り込むといった調整ができるダイヤルになるのです。   変わる内容とその時期 dataCollection はすべての Sentry SDK に導入されます。JavaScript SDK では 10.57.0 から利用できるため、すでにこのオプションを見かけた方もいるかもしれません。dataCollection が新しいデフォルトのオプションとなり、sendDefaultPii が完全に廃止されるのは、バージョン11のリリースです。考え方はどのプラットフォームでも共通ですが、具体的なデフォルト値や移行手順は異なる場合があり、SDK ごとの詳細はそれぞれのリリースノートで説明されます。 v11 の JavaScript SDK にとって、これは単なる名称変更ではなく、挙動の変更です。新しいデフォルトは、従来よりも多くのデータを収集します。sendDefaultPii はすでに非推奨となっており、v11 で削除されます。他の Sentry SDK もそれぞれのタイミングで廃止していく予定であり、最終的な行き先はいずれも dataCollection です。   PII とセンシティブデータ SDK は2種類のデータをそれぞれ異なる方法で扱います。PII(個人を特定できる情報、Personally Identifiable Information)とは、ユーザー ID、メールアドレス、ユーザー名、氏名など、個人に結びつくあらゆる情報を指します。センシティブデータとは、パスワード、トークン、API キーといった認証情報や秘密情報のことです。 […]

【Unreal Engine Session Replay】クラッシュ前のクラッシュ

Article by: Ivan Tustanivskyi(読了時間:6分)   よくある話です。クラッシュレポートがキューに届きます。スタックトレースはきれいに取れているものの、指しているのはいかにも無害そうな関数だけ。プレイヤーがその直前に何をしていたのかを示す手がかりは、どこにもありません。ボス戦の真っ最中だったのか、ロード画面で Alt+Tab を押していたのか、チュートリアルで立ち止まっていただけなのか、QAでは再現できず、プレイヤーからのバグ報告は「ゲーム落ちたw」の一言。残されたコアダンプとコールスタックを前に、当てものクイズを始めるしかありません。 スタックトレースは、コードがどこでクラッシュしたかは教えてくれます。しかし、なぜクラッシュしたのかまでは教えてくれません。ゲームは、一般的なデスクトップアプリケーションやモバイルアプリケーションに比べて、実行環境による影響をはるかに受けやすいソフトウェアです。だからこそ、「なぜ」の答えは、たいていクラッシュ直前の数秒間にあります。 Session Replayが埋めてくれるのは、まさにそのギャップです。新たに Session Replay に対応したことで、Unreal Engine 向けの Sentry SDK は直近数秒のゲームプレイを継続的に録画し、そのクリップをクラッシュレポートに添付できるようになりました。クラッシュが Sentry に届くと、その映像も一緒に届きます。おかげで物事がおかしくなった瞬間まで、プレイヤーが見ていたものをそのまま見られるのです。   Session Replay で得られるもの リプレイ付きのクラッシュが届くと、クラッシュイベントにひも付いた形で Replays ページに表示されます。そこでは、ゲームの実際のレンダリング済みフレームを再生できるほか、その過程で発生した重要な出来事を時系列に並べた、スクラブ可能なタイムラインも確認できます。 ▶ インタラクティブデモ:https://demo.arcade.software/8AgdLvo1bz99viH3a842/?embed デバッグの主役は、プレイヤーの隣に並ぶパネルです。映像と AI によるリプレイ要約に加えて、各リプレイでは次の情報も確認できます。 タグとコンテキスト — OSとそのバージョン、リリース、クラッシュの種類、リージョンなど、本来ならプレイヤーに確認しなければ分からない情報です。 Breadcrumbs — エラーやゲームプレイ中のイベント、独自に記録したカスタム breadcrumbs が映像と同期したタイムライン上に表示されます。 ログ — ゲームのログ出力を映像に合わせてタイムスタンプ付きで確認できます。 トレース — クラッシュに至るまでのスパンが共通のトレースIDで結び付けられています。バックエンドが関係するクラッシュであれば、同じトレースに含まれるサーバー側のスパンもここからたどることができます。   上の例では、これだけで何が起きたのかが分かります。開始から3秒後、チェックアウトのHTTPリクエストが不正な値を返し、ensure が発火。プレイヤーはレベル2に到達し、「Wrath」の攻撃モディファイアを選択。そして00:22、ASentryTowerTurret::Shoot で致命的なクラッシュが発生します。 これは、クラッシュそのものが再現手順を教えてくれるようなものです。しかも、映像を確認するためにクラッシュの詳細画面を離れる必要はありません。リプレイはクラッシュイベントのページにそのまま埋め込まれているため、Issueのトリアージは直前数秒のゲームプレイを確認するところから始められます。さらに詳しく調べたくなったら、ワンクリックでリプレイの全画面表示へ切り替えられます。 ▶ インタラクティブデモ:https://demo.arcade.software/wbJ8cKhmNjSzcdAECCz1/?embed   […]

【Godot .NET サポート】一般提供開始

Article by: Serhii Snitsaruk(読了時間:2分)     先日、Sentry の Godot Engine SDK のバージョン 2.0.0 をリリースし、C#/.NET サポートとアプリケーションメトリクスを一般提供(GA)しました。これにより、マネージド C# コードからエラーを捉え、開発ビルドと製品版ビルドの両方でカスタムメトリクスを追跡できるようになりました。   C#/.NET サポート Godot は非常に性格の異なる2つのスクリプティングの世界、GDScript と C# をサポートしています。1.x のリリースでは、GDScript、エンジン本体、ネイティブの C/C++ コードから Issue を捉えられるよう SDK をインストルメントし、公式にサポートされるすべてのプラットフォームへとサポートを広げてきました。2.0.0 のリリースでは、Godot Engine 上での .NET 向けの第一級のエラーレポートを導入します。 マネージドコードからのエラーは、GDScript やエンジンの Issue と同じトレース上に並んで表示されるようになり、タグ・breadcrumbs・ユーザーコンテキストといった scope の要素も、現時点で同期されている範囲で付与されます。 では、これが実際にどう動くのかを見てみましょう。以下は私たちの Godot ゲームで実行時に例外を投げる C# コードの短縮版です。   private List<UpgradePathBase>? TryFetchUpgradesFromServer(){var fetchTransaction = SentrySdk.StartTransaction(“fetch_upgrades”, […]

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

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 […]

;