Sentry は、アプリで起きた例外を、スタックトレースと周りの情報つきで集めて通知するサービスです。 アプリに SDK を入れ、プロジェクトごとの DSN(送り先の URL)を渡して init するだけで、捕まえていない例外が送られます。

# Python(pip install sentry-sdk)
import sentry_sdk
sentry_sdk.init(
    dsn="https://<公開キー>@o<組織ID>.ingest.sentry.io/<プロジェクトID>",
    environment="production",
    release="myapp@1.4.2",
    send_default_pii=False,
    traces_sample_rate=0.1,
)

SDK を手元の擬似サーバー(Sentry の受け口をまねた小さな HTTP サーバー)に向けて、実際に送られたものを調べました。

確かめたこと 結果
送り先 POST /api/42/envelope/(DSN の末尾がプロジェクト ID)
送る形式 1行目がヘッダー、2行目が項目のヘッダー、3行目が本体の JSON という「エンベロープ」
Python の例外1件 gzip で 1,324 バイト(展開すると 3,086 バイト)
一緒に送られたもの ソースコードの前後5行、ローカル変数、ホスト名、入っているパッケージの一覧
password という名前のローカル変数 "[Filtered]" に置き換わった
send_default_pii=False 利用者の IP は送られない。set_user で入れたメールアドレスは送られた
sample_rate=0.5 で 200件 送られたのは 94件。106件は捨てた件数として client_report で報告

確認環境:Python 3.11.15 と sentry-sdk 2.72.0、Node.js 22.22.2 と @sentry/node 11.7.0・@sentry/cli 3.8.0・esbuild 0.28.2 を Ubuntu 24.04 で動かし、送り先は Python で書いた擬似サーバーにしました。Java(sentry 8.60.0)と Spring Boot の設定は Sentry の公式ドキュメントで確かめています(確認日 2026年10月13日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Sentryの導入|Python・Java・JavaScriptの設定」

DSN とは

DSN は「どのプロジェクトに送るか」を表す URL です。 Sentry の管理画面の「Settings → Projects → (プロジェクト) → Client Keys (DSN)」にあります。

https://abc123publickey@o123456.ingest.sentry.io/42
└scheme┘ └─公開キー──┘ └──────ホスト──────┘ └プロジェクトID
部分 送るときの使われ方(手元で確かめたもの)
公開キー Python は X-Sentry-Auth: Sentry sentry_key=abc123publickey, sentry_version=7, ... ヘッダー、Node は URL の ?sentry_key=abc123publickey
プロジェクト ID 送り先のパス /api/42/envelope/

DSN の公開キーは秘密の値ではありません。 ブラウザの JavaScript にも入る前提の値で、イベントを送ることしかできません。ただし、知っていれば誰でもイベントを送れるので、環境変数で渡し、Git に入れない運用が一般的です。Python と Node の SDK は、dsn を書かなければ環境変数 SENTRY_DSN を読みます。DSN を空にすると、何も送りません(テストや手元の開発で使う)。

Python

pip install --upgrade sentry-sdk
import os
import sentry_sdk

def before_send(event, hint):
    # 送る前に中身を直す。None を返すと送らない
    if "exc_info" in hint:
        exc_type, exc, tb = hint["exc_info"]
        if isinstance(exc, KeyboardInterrupt):
            return None
    if "user" in event:
        event["user"].pop("email", None)
    return event

sentry_sdk.init(
    dsn=os.environ.get("SENTRY_DSN"),
    environment=os.environ.get("APP_ENV", "development"),
    release=os.environ.get("APP_VERSION"),        # 例:myapp@1.4.2 や Git のコミット
    send_default_pii=False,
    sample_rate=1.0,                              # エラーを送る割合
    traces_sample_rate=0.1,                       # 性能の計測(トレース)を送る割合
    before_send=before_send,
)

# 自分で送る
try:
    1 / 0
except ZeroDivisionError as e:
    sentry_sdk.capture_exception(e)
sentry_sdk.capture_message("処理を開始しました", level="info")

Django・Flask・FastAPI・Celery などは、パッケージが入っていれば SDK が自動で連携を有効にします。手元の例では、argv・atexit・dedupe・excepthook・logging・modules・stdlib・threading が有効でした(イベントの sdk.integrations)。logging の連携が有効なので、logging.error() もイベントとして送られます。

実際に送られた中身

ZeroDivisionError を capture_exception で送ったときのエンベロープです(gzip を展開したもの)。

POST /api/42/envelope/
Content-Type: application/x-sentry-envelope
Content-Encoding: gzip
User-Agent: sentry.python/2.72.0
X-Sentry-Auth: Sentry sentry_key=abc123publickey, sentry_version=7, sentry_client=sentry.python/2.72.0

{"event_id":"f13a044d38ca4780a1aacb9ce0387e84","sent_at":"2026-10-13T04:37:19.641803Z","trace":{"trace_id":"d807303b...","environment":"staging","release":"myapp@1.4.2","public_key":"abc123publickey"}}
{"type":"event","content_type":"application/json","length":2797}
{"level":"error","platform":"python","environment":"staging","release":"myapp@1.4.2","server_name":"vm","exception":{...},"modules":{...},"contexts":{...},...}

例外が起きた行の情報(スタックフレーム)です。

{
  "filename": "app1.py",
  "function": "divide",
  "lineno": 12,
  "pre_context": ["    traces_sample_rate=0.0,", ")", "", "def divide(a, b):", "    password = \"hunter2\""],
  "context_line": "    return a / b",
  "post_context": ["", "try:", "    divide(1, 0)", "except ZeroDivisionError as e:", "    event_id = sentry_sdk.capture_exception(e)"],
  "vars": {"a": "1", "b": "0", "password": "[Filtered]"},
  "in_app": true
}
項目 中身 止める設定
pre_context・context_line・post_context ソースコードの前後の行 include_source_context=False
vars ローカル変数の値(password・token・secret などの名前は [Filtered]) include_local_variables=False
server_name ホスト名 server_name="..." で上書き
modules 入っているパッケージと版 default_integrations の調整
contexts.runtime CPython 3.11.15 ―

ローカル変数は、名前で判定して伏せています。 password は [Filtered] になりましたが、a と b はそのまま送られました。名前が customer_mail のような変数は伏せられません。SDK のソース(scrubber.py)では、password・passwd・secret・api_key・auth・token・session・cookie・authorization などが伏せる名前の一覧(DEFAULT_DENYLIST)に入っています。

個人情報を送らない設定

send_default_pii で変わるもの

send_default_pii は「SDK が自動で集める個人情報」を送るかどうかです。自分で入れたものは止まりません。 手元の WSGI アプリ(Cookie・Authorization・X-Api-Key つきのリクエスト)で比べた結果です。

項目 False(既定) True
利用者の IP(REMOTE_ADDR・user.ip_address) 送らない 203.0.113.7
Cookie ヘッダー [Filtered] [Filtered]
Authorization ヘッダー [Filtered] [Filtered]
X-Api-Key ヘッダー 空にした k-123
URL のクエリ(token=abc&page=2) そのまま送った そのまま送った
set_user({"email": ...}) で入れたメール 送った 送った

URL のクエリに入れたトークンや、set_user に入れたメールアドレスは、send_default_pii=False でも送られます。 送りたくないものは、入れない・before_send で消す、のどちらかです。手元で、上の before_send(X-Api-Key とメールを消す)を足すと、どちらもイベントから消えました。

def before_send(event, hint):
    req = event.get("request", {})
    req.get("headers", {}).pop("X-Api-Key", None)
    req.pop("query_string", None)                 # クエリを送らない
    if "user" in event:
        event["user"] = {"id": event["user"].get("id")}   # ID だけ残す
    return event
設定 何をするか
send_default_pii=False IP・リクエストの本文など、自動で集める個人情報を送らない
before_send 送る直前のイベントを直す・捨てる(エラーのイベント)
before_send_transaction 性能の計測(トランザクション)を直す・捨てる
before_breadcrumb パンくず(例外の前の操作やログの記録)を直す・捨てる
include_local_variables=False ローカル変数を送らない
include_source_context=False ソースコードの行を送らない
event_scrubber 伏せる名前の一覧を足す(EventScrubber(denylist=[...]))
サーバー側の Data Scrubbing Sentry のプロジェクト設定で、受け取ったあとに伏せる

Python のドキュメントでは、send_default_pii は将来 data_collection(集める情報を種類ごとに決める設定)に置き換える予定で、両方を書くと send_default_pii は無視されると説明されています。

JavaScript(Node.js)

npm install @sentry/node
// instrument.js:アプリより先に読み込む
const Sentry = require('@sentry/node');

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.APP_ENV || 'development',
  release: process.env.APP_VERSION,          // 未指定なら SENTRY_RELEASE を読む
  sampleRate: 1.0,
  tracesSampleRate: 0.1,
  beforeSend(event) {
    if (event.user) delete event.user.email;
    return event;
  },
});
node --import ./instrument.js app.js       # 公式ドキュメントの読み込み方(ESM なら instrument.mjs)
// app.js
const Sentry = require('@sentry/node');
try {
  JSON.parse('{"id":1}').items.length;
} catch (e) {
  Sentry.captureException(e);
}

手元で TypeError を送ると、3つのエンベロープが送られました。

順番 項目の種類 中身
1 session アプリの起動(リリースの健全性の集計用)
2 event 例外。platform: node、environment・release、ソースコードの前後の行、contexts に runtime・app・os・device・culture・cloud_resource
3 session 終了したセッション
POST /api/42/envelope/?sentry_version=7&sentry_key=abc123publickey&sentry_client=sentry.javascript.node%2F11.7.0
user-agent: sentry.javascript.node/11.7.0
Transfer-Encoding: chunked

Node の SDK は、ローカル変数を既定では送りません(includeLocalVariables の既定は false)。 Python と既定が違います。beforeSend でメールを消すと、user は {"id":"u-1001"} だけになりました。Node SDK のドキュメントでは、sendDefaultPii は非推奨で、dataCollection で集める情報を決める方式に変わっていると説明されています。

Java・Spring Boot

Java は Sentry の公式ドキュメント(sentry 8.60.0)で確かめた書き方です。

// build.gradle.kts(Spring Boot を使わない場合)
dependencies {
    implementation("io.sentry:sentry:8.60.0")
}
import io.sentry.Sentry;

public class Main {
    public static void main(String[] args) {
        Sentry.init(options -> {
            options.setDsn(System.getenv("SENTRY_DSN"));
            options.setEnvironment("production");
            options.setRelease("myapp@1.4.2");
            options.setTracesSampleRate(0.1);
            options.setBeforeSend((event, hint) -> {
                if (event.getUser() != null) event.getUser().setEmail(null);
                return event;
            });
        });

        try {
            throw new IllegalStateException("order not found: 1234");
        } catch (Exception e) {
            Sentry.captureException(e);
        }
    }
}
Spring Boot の版 依存(Gradle)
4 implementation 'io.sentry:sentry-spring-boot-4:8.60.0'
3 implementation 'io.sentry:sentry-spring-boot-starter-jakarta:8.60.0'
2 implementation 'io.sentry:sentry-spring-boot-starter:8.60.0'
# application.properties
sentry.dsn=${SENTRY_DSN}
sentry.environment=production
sentry.traces-sample-rate=0.1

Spring Boot では、コントローラーで捕まえていない例外が自動で送られます。@ControllerAdvice で例外を処理して 500 を返す場合の扱いは、関連記事「Spring Boot例外処理|@ControllerAdvice完全版」で扱っています。Logback と組み合わせると log.error() も送れます(sentry-logback)。

environment と release

設定 使い方 既定値
environment production・staging・development で分けて、画面で絞り込む Python は production
release どの版で起きたか・どの版で直ったかを追う。ソースマップとの対応にも使う Python は Git などから自動で決めようとする。Node は SENTRY_RELEASE
dist 同じ release の中のビルドの区別(モバイルアプリなど) なし

release は、デプロイする版とそろえます。 例は myapp@1.4.2 や Git のコミットハッシュです。release を付けると、「この版で初めて起きたエラー」「直したはずの版でまた起きた(回帰)」が分かります。手元のエンベロープでも、1行目のヘッダーの trace に environment と release が入っていました。

サンプリング(sample_rate・traces_sample_rate)

設定 対象 既定値(Python)
sample_rate エラー 1.0(全部送る)
traces_sample_rate 性能の計測(トランザクション・スパン) なし(計測しない)
traces_sampler 計測を送る割合を関数で決める なし

エラーは全部送り、性能の計測は割合を下げるのが一般的です。 手元で 200件ずつ送った結果です。

設定 送られた件数 捨てた件数(client_report の報告)
sample_rate=0.5 でメッセージ 200件 94件 sample_rate で 106件
traces_sample_rate=0.25 でトランザクション 200件 48件 sample_rate で 152件

SDK は、捨てた件数を client_report という項目で Sentry に報告します。 実際の中身です。

{"discarded_events":[{"reason":"sample_rate","category":"error","quantity":106}]}

一度に大量に送ると、SDK の送信待ちの列(Python の transport_queue_size、既定 100)があふれて捨てられます。手元で、エラーとトランザクションを合わせて 400件を一気に送ったときは、エラー 53件が queue_overflow として捨てられました。

def traces_sampler(ctx):
    name = ctx.get("transaction_context", {}).get("name", "")
    if name.startswith("/health"):
        return 0          # ヘルスチェックは送らない
    if name.startswith("/checkout"):
        return 0.5        # 大事な画面は多めに
    return 0.05

sentry_sdk.init(dsn="...", traces_sampler=traces_sampler)

ソースマップ(JavaScript)

圧縮した JavaScript のエラーを元のソースの行で見るには、ソースマップを Sentry に上げます。 今の方式は「Debug ID」で、ビルドしたファイルとソースマップに同じ ID を書き込んで対応させます。手元で esbuild の出力に sentry-cli sourcemaps inject を動かした結果です。

npx esbuild src/app.js --bundle --minify --sourcemap --platform=node --outdir=dist
npx sentry-cli sourcemaps inject dist
Source Map Debug ID Injection Report
  Modified: The following source files have been modified to have debug ids
    e8e4e293-a0bc-51e7-b5f8-db50e9f93631 - dist/app.js
  Modified: The following sourcemap files have been modified to have debug ids
    e8e4e293-a0bc-51e7-b5f8-db50e9f93631 - dist/app.js.map
ファイル 書き込まれたもの
dist/app.js の先頭 e._sentryDebugIds[n]="e8e4e293-..." を登録する1行のコード
dist/app.js の末尾 //# debugId=e8e4e293-a0bc-51e7-b5f8-db50e9f93631
dist/app.js.map "debugId": "e8e4e293-a0bc-51e7-b5f8-db50e9f93631"

そのあと、CI で次のように上げます(組織・プロジェクト・トークンが要ります)。

export SENTRY_AUTH_TOKEN=...      # CI の秘密の変数に入れる
npx sentry-cli sourcemaps upload --org my-org --project my-project --release "$APP_VERSION" dist

ソースマップは、公開サーバーに置かないのが一般的です。 置くと、元のソースコードを誰でも読めます。上げたあとに dist から .map を消してからデプロイします。Vite・webpack・Next.js には、ビルドと同時に inject と upload を行うプラグイン(@sentry/vite-plugin など)があります。

送られていないときの確かめ方

確かめること 方法
SDK の動き Python は init(debug=True)、Node は debug: true で送信のログを出す
すぐ終わるスクリプト 終わる前に sentry_sdk.flush()・await Sentry.flush(2000)
DSN が空 SENTRY_DSN が入っているか。空なら何も送らない
サンプリング sample_rate が 0 になっていないか、before_send が None を返していないか
ネットワーク *.ingest.sentry.io への HTTPS がプロキシ・ファイアウォールで止まっていないか
割り当て Sentry の Stats 画面で、受け取ったが捨てた(上限・フィルター)件数を見る

よくある質問

Q. DSN をフロントエンドの JavaScript に書いてもよいですか? A. Sentry の DSN はブラウザに入れる前提の値です。送ることしかできません。迷惑なイベントを送られた場合に備えて、Sentry 側の「Allowed Domains」やレート制限を設定します。

Q. 同じエラーが大量に来て、通知があふれます。 A. Sentry は同じ種類のエラーを1つの Issue にまとめます。通知はアラートのルールで「初めて起きたとき」「1時間に100回を超えたとき」などに絞れます。SDK 側では before_send で、無視してよい例外(切断・キャンセル)を捨てられます。

Q. ログ(logging・console)とどう使い分けますか? A. ログは「何が起きたかの記録」、Sentry は「直すべきエラーの一覧と通知」です。ログの出し方は、関連記事「ログレベルの使い分け|ERROR・WARN・INFO・DEBUGの判断基準とログ設計」で扱っています。

まとめ

  • DSN の末尾がプロジェクト ID。SDK は /api/<ID>/envelope/ に「エンベロープ」で送る
  • Python は既定で ソースコードの前後の行とローカル変数 を送る。password などの名前だけ伏せる
  • send_default_pii=False でも、クエリ文字列と set_user のメールは送られた。before_send で消す
  • エラーは sample_rate=1.0、性能の計測は traces_sample_rate を下げる。捨てた件数は client_report で分かる
  • environment と release を付け、release はデプロイの版とそろえる
  • ソースマップは sentry-cli sourcemaps inject → upload。公開サーバーには置かない

全体の監視の考え方は関連記事「監視設計の項目一覧|死活・リソース・ログ監視のしきい値例とテンプレート」、トレースの仕組みは「OpenTelemetry入門|Pythonで始めるトレース・メトリクス実装」で扱っています。

参考・出典

確認日はいずれも 2026年10月13日です。

  • Sentry Docs「Python」:https://docs.sentry.io/platforms/python/
  • Sentry Docs「Python Options」:https://docs.sentry.io/platforms/python/configuration/options/
  • Sentry Docs「Python Data Collected」:https://docs.sentry.io/platforms/python/data-management/data-collected/
  • Sentry Docs「Python Scrubbing Sensitive Data」:https://docs.sentry.io/platforms/python/data-management/sensitive-data/
  • Sentry Docs「Node.js」:https://docs.sentry.io/platforms/javascript/guides/node/
  • Sentry Docs「Node.js Options」:https://docs.sentry.io/platforms/javascript/guides/node/configuration/options/
  • Sentry Docs「Java」:https://docs.sentry.io/platforms/java/
  • Sentry Docs「Spring Boot」:https://docs.sentry.io/platforms/java/guides/spring-boot/
  • Sentry Docs「Source Maps(Uploading with Sentry CLI)」:https://docs.sentry.io/platforms/javascript/sourcemaps/uploading/cli/
  • Sentry Developer Docs「Envelopes」:https://develop.sentry.dev/sdk/data-model/envelopes/
  • sentry-python のソース(scrubber.py):https://github.com/getsentry/sentry-python

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Sentryの導入|Python・Java・JavaScriptの設定」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?