こんにちは!開発の現場で「なんだかエラーが全然上がってこないな…でもユーザーからは不具合の報告が来るぞ?」と、冷や汗をかいた経験はありませんか?
もしかしたらそれ、あなたのコードのバグではなく、ユーザーのブラウザにある「アドブロック(広告ブロッカー)拡張機能」にSentryのエラー送信がサイレントに消し去られているのが原因かもしれません。
オブザーバビリティ(可観測性)の世界において、見えないエラーは存在しないも同値です。今回は、アドブロックの魔の手からエラーログを守り抜き、トラッキング精度を100%に近づけるための秘技「Sentryトンネリング(Tunneling)」について、基礎から実装まで優しく、そして徹底的に解説していきますね。
これをマスターすれば、あなたのプロダクトのエラー検知率は劇的に改善し、ユーザーが直面する見えないバグに怯える夜から解放されますよ!
—
1. なぜエラーが消えるのか?アドブロックの仕組みとSentryの宿命
まずは敵を知ることから始めましょう。Sentryは非常に優秀なエラー追跡ツールです。フロントエンド(ブラウザ)にJavaScriptのSDKを組み込むだけで、ユーザーの環境で起きたバグをリアルタイムでキャッチしてくれます。
通常、Sentry SDKはブラウザから直接、以下のようなSentry公式のインフラへエラーデータを送信します。
- `https://o123456.ingest.sentry.io/api/…`
しかし、世の中の多くのユーザー(特にITリテラシーの高いエンジニアやゲーマーなど、バグを踏みやすい層!)は、uBlock OriginやAdBlockといった広告ブロッカーを導入しています。これらの拡張機能は、リクエストのURLに `sentry.io` や `ingest.sentry.io` といった文字列が含まれていると、「どうせサードパーティのトラッキングやろ!」と勝手に判断し、通信を丸ごとブロック(通信の遮断)してしまうのです。
結果として、一番検知したい重要顧客のエラーログが綺麗にロスト(消失)します。「トラッキング精度が実は70%しかなかった」なんてことも珍しくありません。
—
2. 救世主「Sentryトンネリング」とは何か?
この問題を鮮やかに解決するのが「トンネリング(Tunneling)」です。
概念はとてもシンプルです。ブラウザから直接Sentryのサーバーへリクエストを送るのをやめ、いったん「自社ドメイン(例:`your-app.com/api/sentry`)」を介してリクエストを中継(プロキシ)するのです。
[ ユーザーのブラウザ ]
│
▼ (自社ドメインへ送信。アドブロックは怪しまない)
[ あなたのサーバー / リバースプロキシ ]
│
▼ (サーバー間通信なのでブロックされない)
[ Sentry公式サーバー ]
アドブロック拡張機能は、リクエスト先のドメインが自社のものであればブロックしません。そして、あなたのサーバー(またはNext.jsなどのAPIルート、Cloudflare Workersなど)で受け取ったリクエストを、Sentryの公式サーバーへこっそり転送してあげるわけです。
これでアドブロックを完全にバイパスし、トラッキング精度を限りなく100%に近づけることができます。
—
3. 実践!Next.js環境でのトンネリング実装ステップ
それでは、現代的なWeb開発でよく使われる Next.js を例に、具体的な実装手順を見ていきましょう。他のフレームワーク(ExpressやNuxt、あるいはNginxなどのWebサーバー)でも考え方は全く同じです。
ステップ1: Sentryのフロントエンド設定を変更する
まずは、ブラウザ側(クライアントサイド)のSentry初期化設定(`sentry.client.config.ts` など)を書き換えます。ここで `tunnel` オプションを追加するのがポイントです。
// sentry.client.config.ts
import as Sentry from “@sentry/nextjs”;
Sentry.init({
dsn: “https://example_dsn@o0.ingest.sentry.io/0”,
// ★ここが魔法のキースニペット!
// 自社ドメイン内のエンドポイントを指定します
tunnel: “/api/sentry-tunnel”,
// その他の設定…
tracesSampleRate: 1.0,
});
これだけで、Sentry SDKはエラーが発生した際に `https://your-domain.com/api/sentry-tunnel` へ向けてデータを投げるようになります。
ステップ2: トンネル用APIルートを作成する
次に、ブラウザから受け取ったリクエストをSentryに横流しするサーバー側の受け皿を作ります。Next.jsのApp Routerであれば、`app/api/sentry-tunnel/route.ts` を作成します。
ここには、セキュリティとプライバシーを守るための超重要なエンジニアリング上の注意点があります。丁寧にコメントを書いたので読んでみてください。
// app/api/sentry-tunnel/route.ts
import { NextRequest, NextResponse } from “next/server”;
// 1. 転送先として許可するSentryのホスト(Sentryのプロジェクトのホスト名に合わせて変更してください)
const SENTRY_HOST = “o0.ingest.sentry.io”;
// 2. あなたのSentryプロジェクトID
const SENTRY_PROJECT_ID = “0”;
export async function POST(req: NextRequest) {
try {
// ブラウザから送られてきたリクエストボディ(エンベロープデータ)を生のテキストとして取得
const envelope = await req.text();
// プライバシー保護の要:
// 送信されてきたデータの1行目(ヘッダー部分)をパースし、
// DSN(Data Source Name)が含まれているか、不正な宛先になっていないかを検証します。
const lines = envelope.split(“\n”);
const headerJson = JSON.parse(lines[0]);
// ヘッダーのDSNからホストとプロジェクトIDを抽出して厳密にチェック
// (オープンプロキシとして悪用されるのを防ぐセキュリティ対策です)
const dsn = new URL(headerJson.dsn);
if (dsn.hostname !== SENTRY_HOST) {
return NextResponse.json({ error: “Invalid Sentry hostname” }, { status: 400 });
}
// Sentry公式のエンドポイントを組み立てる
const sentryIngestUrl = `https://${SENTRY_HOST}/api/${SENTRY_PROJECT_ID}/envelope/`;
// サーバーサイドからSentry公式へリクエストを転送(フェッチ)
const sentryResponse = await fetch(sentryIngestUrl, {
method: “POST”,
body: envelope,
});
// Sentryからのレスポンスをそのままブラウザ(SDK)に返す
const responseBody = await sentryResponse.text();
return new NextResponse(responseBody, {
status: sentryResponse.status,
headers: {
“Content-Type”: “application/json”,
},
});
} catch (error) {
console.error(“Sentry tunnel error:”, error);
return NextResponse.json({ error: “Internal Error” }, { status: 500 });
}
}
🔒 ここがプロのこだわり:オープンプロキシ対策
トンネリングを実装する際、「誰から送られてきたデータでも無条件でSentryに転送するコード」を書いてしまうと、悪意ある第三者にあなたのサーバーを「スパムや別サービスへの踏み台(オープンプロキシ)」として悪用される危険性があります。
上記コードのように、宛先ホストが確実に自社のSentryプロジェクトを指しているか厳格にバリデーション(検証)するのが、現場で信頼されるエンジニアの作法です。
—
4. 精度高い「HelloWorld」動作確認:アドブロックを突破せよ!
コードが書けたら、実際に正しくトンネリングが機能しているかテストしてみましょう。ここが一番ワクワクする瞬間です!
1. 広告ブロッカーを有効化する
お使いのブラウザ(ChromeやBraveなど)で、uBlock Originなどのアドブロック拡張機能を有効にします。できれば、サードパーティスクリプトを厳しくブロックするモードにしておいてください。
2. 意図的にエラーを発生させるコンポーネントを作る
テスト用のボタンなどを配置し、クリックしたらわざとエラーを投げるコードを書きます。
export default function TestPage() {
const triggerError = () => {
throw new Error(“Sentry Tunneling Test Error!”);
};
return (
);
}
3. ブラウザの開発者ツール(Networkタブ)で確認する
ページを開き、ブラウザの「開発者ツール(F12)」を開いて「Network(ネットワーク)」タブを選択します。その状態で「エラーを爆誕させる」ボタンをポチッと押してください。
ここで、以下の通信が発生していることを確認します:
1. `https://your-domain.com/api/sentry-tunnel` に対して `POST` リクエストが飛んでいる(アドブロックにブロックされていない!)
2. そのAPI内部から、裏側でSentryのサーバーへデータが転送され、ステータスコード `200 OK` が返ってきている。
4. Sentryダッシュボードを確認する
ブラウザを閉じ、Sentryのダッシュボード(Issues画面)をリロードしてみてください。
見事に “Sentry Tunneling Test Error!” というエラーが、アドブロックが有効な環境下にもかかわらず、美しく着弾しているはずです!
—
まとめ:見えないエラーをなくし、プロダクトの品格を高めよう
お疲れ様でした!今回はSentryの「トンネリング」機能を使って、アドブロックによるエラーロストを防ぎ、トラッキング精度を100%に近づける裏技を解説しました。
- アドブロックは `sentry.io` への通信を容赦なく消し去る
- 自社ドメイン(`/api/sentry-tunnel` 等)を経由させることでブロックを回避できる
- オープンプロキシ化を防ぐため、サーバー側で宛先ホストのバリデーションを忘れないこと
これを導入するだけで、今まで闇に葬られていたユーザーの環境依存バグや、特殊な拡張機能を入れたパワーユーザーからの悲鳴を確実にキャッチできるようになります。
「これをマスターすれば、毎日の作業が劇的に楽になりますよ」——エラーに怯えることなく、自信を持ってデプロイできる静かな安心感を、ぜひあなたの現場にも取り入れてみてください。
あなたのプロダクトのオブザーバビリティが、今日からさらに最高のものになることを応援しています!