- 技術 💻
Sentryの導入|Python・Java・JavaScriptの設定
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期連続の黒字決算。