> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/zh-tw/configuration/error-monitoring.md).

# 錯誤監控（Sentry）

前端與後端皆可選擇整合 Sentry，包含可避免廣告阻擋的隧道。

MyIP 附帶可選的 [Sentry](https://sentry.io/) 在應用程式的兩個部分都提供監測功能。完全由環境變數控制。

{% hint style="success" %}
**如果你不設定這些變數，部署行為就會完全像從未使用過 Sentry 的版本。** 前端套件中不包含任何 Sentry 程式碼， `@sentry/node` 從不會被後端匯入，且 tunnel 路由也不會掛載。沒有任何東西會被送到任何地方。
{% endhint %}

| 變數                         | 一半      | 在讀取時                        |
| -------------------------- | ------- | --------------------------- |
| `VITE_SENTRY_DSN_FRONTEND` | 前端 + 後端 | **建置時間** 套件在建置時，tunnel 在執行時 |
| `SENTRY_DSN_BACKEND`       | 後端      | 執行時                         |
| `SENTRY_ENVIRONMENT`       | 後端      | 執行時（以及 source map 的建置時間）    |
| `SENTRY_ORG`               | 建置工具    | 建置時間                        |
| `SENTRY_PROJECT_FRONTEND`  | 建置工具    | 建置時間                        |
| `SENTRY_AUTH_TOKEN`        | 建置工具    | 建置時間                        |

兩個部分彼此獨立。只啟用後端監控是一個完全正常的設定，而且對 Docker 使用者來說是最簡單的。

## 各部分如何搭配

```
瀏覽器（Vue SPA）
   │  錯誤、追蹤、重播
   ▼
POST /api/monitoring   ← 第一方 tunnel，同源
   │  （後端會驗證封包的 DSN，然後轉發）
   ▼
Sentry  ◀── 直接連線 ── Express 後端（錯誤、追蹤、warn+ 日誌）
```

## 後端 — `SENTRY_DSN_BACKEND`

設定 DSN 並重新啟動。整個設定就是這樣。

{% code title=".env" %}

```bash
SENTRY_DSN_BACKEND="https://<key>@oNNNNN.ingest.sentry.io/<project-id>"
```

{% endcode %}

會啟用什麼：

* **未捕捉的錯誤與 5xx 回應** 來自任何 `/api/*` 路由，透過 Sentry 的 Express 錯誤處理器。
* **效能追蹤** 以 100% 採樣率——每個路由的延遲、吞吐量與錯誤率。
* **日誌轉送。** 共用的 pino 記錄器會鏡射 `warn` 及以上到 Sentry Logs； `錯誤` 及以上還會額外變成可分組、可告警的 Issue。因此 `logger.error({ err }, '…')` 在整個過程中的呼叫 `api/` 是刻意發出的訊號，不只是日誌行。見 [記錄](/developer/zh-tw/configuration/logging.md).
* **Cron 監控** 用於排程的資料集工作（MaxMind 自動更新、CAIDA 重新整理、服務狀態輪詢）。監控是在第一次 check-in 時建立的——不需要在 Sentry UI 中預先建立。

SDK 透過以下方式啟動： `node --import ./sentry-instrument.js`，這會在 Express 載入之前註冊 loader hooks。 `dev`, `start`，而 pm2 start 指令已經帶上了這個旗標，所以不需要加任何東西。

{% hint style="info" %}
啟動時會印出 `🛰️ 已啟用 Sentry 後端監控` 當 DSN 被讀取到時。沒有這一行就表示沒有看到 DSN。
{% endhint %}

## 前端 — `VITE_SENTRY_DSN_FRONTEND`

這是一個 **建置時間** 變數。Vite 會把它內嵌為常數，而 Sentry 模組的動態 import 是以該常數為條件。沒有它，dead-code elimination 會移除該分支，而 SDK chunk 甚至不會被產生。

```bash
VITE_SENTRY_DSN_FRONTEND="https://<key>@oNNNNN.ingest.sentry.io/<project-id>"
pnpm run build
```

會啟用什麼：

* 未捕捉的例外與 `console.error()` 呼叫，按訊息分組。
* 路由層級的效能追蹤，採樣率 10%，並包含 Web Vitals。
* 僅在發生錯誤時才會記錄的 Session Replay——沒有錯誤觸發就不會記錄任何內容。

{% hint style="warning" %}
**同一個值也必須在執行時存在。** 後端會讀取 `VITE_SENTRY_DSN_FRONTEND` 以決定是否掛載 `/api/monitoring` 以及知道它被允許轉送的是哪個 DSN。雖然在建置時有帶入，但如果忘了把它傳給執行中的程序，瀏覽器 SDK 就會把資料 POST 到一個 `404`.
{% endhint %}

### 重播與隱私

頁面文字是刻意 **不** 在重播中被遮蔽的：這個應用程式的整個 UI 就是訪客自己的網路資訊，而那正是除錯所需的上下文。輸入的文字仍會被遮蔽。在公開的 IPCheck.ing 實例中，這點已在隱私政策中揭露——如果你為自己的使用者開啟前端監控，也請同樣揭露。

兩個部分都以 `sendDefaultPii: false`，因此訪客 IP 和標頭不會由 SDK 自動附加。看起來像憑證的查詢參數（`key`, `api_key`, `token`, `secret`, `password`, `驗證`）會在任何內容送出前，從 breadcrumbs、spans 和 request contexts 中移除——上游 URL 會帶著你的 API 金鑰，而 Sentry 會在多個地方記錄 URL。

## 這個 `/api/monitoring` tunnel

廣告封鎖器與隱私擴充功能會阻擋對 `*.ingest.sentry.io`。對於熟悉網路的使用者族群來說，這會佔很大一部分訪客，並且會悄悄刪掉大多數錯誤資料。

因此瀏覽器 SDK 不會直接與 Sentry 溝通。它會將其 envelopes 以 POST 傳送到 `/api/monitoring` ，在你自己的來源上，然後由後端轉送它們。

這個路由如何運作：

* **僅在以下情況掛載： `VITE_SENTRY_DSN_FRONTEND` 已設定時掛載隧道路由** 在執行時。否則，該路徑只是一個普通的 `404`.
* **不是開放轉送器。** envelope header 會帶著瀏覽器 SDK 所設定的 DSN。如果它與 `VITE_SENTRY_DSN_FRONTEND`完全不相符，請求就會以 `403`遭拒。沒有這個檢查，任何人都可以利用你的伺服器向任意的 Sentry 帳號送出資料。
* **它自己的速率限制**：每個 IP 每 20 分鐘 600 個請求，而且它 **不受全域 `/api` 限制器**。與應用程式配額共用的遙測資料，是報告悄悄失效的原因——一次 `429` ，瀏覽器 SDK 就會在接下來的一分鐘內丟棄每個事件。
* **訪客 IP 標記**：一旦 envelope 離開 relay，Sentry 就只會看到你的伺服器位址。後端會在轉送前，將訪客的真實 IP（來自 `CF-Connecting-IP`，若存在且有效）寫入事件項目。
* **失敗是柔性的**：relay 錯誤會回應 `502` 並記錄一則 `warn`。它絕不會中斷頁面。

## `SENTRY_ENVIRONMENT`

為後端事件加上標記，讓你可以在 Sentry UI 中篩選正式環境與開發環境。

* 未設定代表 `production`.
* Set `SENTRY_ENVIRONMENT="development"` 在開發機上。這也會停用 cron check-in，所以你闔上筆電時不會因為「錯過」警報而被叫醒。
* 前端會根據 Vite 建置模式自動加上標記——不需要設定。

{% hint style="info" %}
「為什麼 Sentry 裡沒有資料？」通常問題更常是 Sentry UI 中的環境篩選器，而不是設定壞掉。先檢查它，再檢查你的設定。
{% endhint %}

## Source maps — `SENTRY_ORG` / `SENTRY_PROJECT_FRONTEND` / `SENTRY_AUTH_TOKEN`

沒有 source maps 時，前端堆疊追蹤只會指向壓縮後 bundle 的偏移位置。建置程序可以把它們上傳到 Sentry，讓追蹤能對應回真實的來源檔案。

{% code title=".env" %}

```bash
SENTRY_ORG="your-org-slug"
SENTRY_PROJECT_FRONTEND="your-frontend-project-slug"
SENTRY_AUTH_TOKEN="sntrys_..."
```

{% endcode %}

上傳只會在 **兩個** 條件成立時執行：

1. `SENTRY_AUTH_TOKEN` 已設定，且
2. `SENTRY_ENVIRONMENT` 是 `production` （或未設定，表示 production）。

因此開發與測試建置既不會產生也不會上傳 maps。

{% hint style="danger" %}
`SENTRY_AUTH_TOKEN` 是真正的祕密，而且僅供建置時使用。它絕不會被內嵌到 bundle，也永遠不會到達瀏覽器。請把它排除在映像檔、版本庫之外，並將權限範圍限制在 source-map 上傳。
{% endhint %}

Maps 會以隱藏 source maps 的形式產生、上傳，然後從 `dist/` 刪除——訪客無法下載它們。

## Docker

後端監控很容易；前端監控不容易，而其中原因值得理解。

{% tabs %}
{% tab title="僅後端（推薦）" %}

```bash
docker run -d -p 18966:18966 \\
  -e SENTRY_DSN_BACKEND="https://<key>@oNNNNN.ingest.sentry.io/<id>" \\
  -e SENTRY_ENVIRONMENT="production" \\
  --name myip \\
  jason5ng32/myip:latest
```

在執行時讀取。可與官方預建映像檔搭配使用，無需重新建置。
{% endtab %}

{% tab title="前端（需要自訂建置）" %}
`VITE_SENTRY_DSN_FRONTEND` 由 `pnpm run build` **在** 映像建置過程中消耗。將它以 `docker run -e` 傳入，因此無法把 Sentry 放進已經建置好的 bundle。

官方映像檔在建置時沒有任何 DSN，因此其前端永遠不會使用 Sentry。若要啟用前端監控，你必須自己建置映像檔，並讓建置階段看得到該值——例如加入一組 `ARG` / `ENV` 對 `Dockerfile` 之前 `RUN pnpm run build`.

然後在執行時也傳入相同的 DSN，這樣 tunnel 路由才會掛載：

```bash
docker run -d -p 18966:18966 \\
  -e VITE_SENTRY_DSN_FRONTEND="https://<key>@oNNNNN.ingest.sentry.io/<id>" \\
  --name myip \\
  your-image:latest
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
`.env` 被排除在 Docker build context 之外，因此單純的 `docker build` 絕對不會意外從中取得 DSN。
{% endhint %}

## 驗證你的設定

* **後端**：請查看 `🛰️ 已啟用 Sentry 後端監控` 在啟動日誌中。
* **Tunnel**: `POST /api/monitoring` 不應回傳 `404`。A `404` 表示執行時看不到 `VITE_SENTRY_DSN_FRONTEND`.
* **前端 bundle**：如果你是在沒有 DSN 的情況下建置，Sentry chunk 就不會存在於 `dist/assets/` 任何 Content-Type。
* **沒有資料送達**：依序檢查環境篩選器、專案選擇器，以及 Sentry UI 中的時間範圍。

## 相關頁面

* [記錄](/developer/zh-tw/configuration/logging.md) ——餵給 Sentry Logs 和 Issues 的 pino 等級
* [安全性選項](/developer/zh-tw/configuration/security-options.md) —— 為什麼 tunnel 不受全域限制器影響
* [環境變數](/developer/zh-tw/reference/environment-variables.md) — 完整清單
* [使用 Docker 部署](/developer/zh-tw/getting-started/deploy-with-docker.md) —— 建置與執行時基礎


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/zh-tw/configuration/error-monitoring.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
