> 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/logging.md).

# 記錄

日誌等級、供日誌彙整器使用的 JSON 輸出，以及每個請求的 HTTP 日誌。

兩個 Node 程序——後端 API 與靜態檔案伺服器——都寫入同一個共用 [pino](https://getpino.io/) 記錄器。由三個環境變數控制；三者皆為可選。

| 變數           | 值                                | 預設     |
| ------------ | -------------------------------- | ------ |
| `LOG_LEVEL`  | `debug` / `info` / `warn` / `錯誤` | `info` |
| `LOG_FORMAT` | `json`，或其他任何值                    | pretty |
| `LOG_HTTP`   | `"true"`                         | 取用     |

所有內容都會輸出到 stdout。沒有內建日誌檔——那是你的程序管理器（pm2、systemd、Docker）的責任。

## `LOG_LEVEL`

設定會被寫入的最低嚴重等級。低於它的內容會在格式化前就被丟棄，所以安靜等級的成本確實很低。

* `debug` — 全部都會記錄，包括冗長的資料集更新閒聊。當 MaxMind 或 CAIDA 下載出狀況時很有用。
* `info` — 預設。啟動行、資料集載入、排程工作計畫。
* `warn` — 僅限降級：被限流的 IP、上游部分失敗、逾時。
* `錯誤` — 僅處理器失敗。

{% hint style="info" %}
`LOG_LEVEL` 也會控制哪些內容會送達 Sentry。Sentry 橋接器安裝在記錄器內，因此被等級抑制的行永遠不會變成 Sentry 日誌或問題。請參見 [錯誤監控](/developer/zh-tw/configuration/error-monitoring.md).
{% endhint %}

## `LOG_FORMAT`

### 美化格式（預設）

留空 `LOG_FORMAT` ，輸出就會經過 `pino-pretty`：有顏色、每個事件一行、帶有 UTC 偏移量的主機本地時間戳， `pid` 以及 `hostname` 會被省略。

```
[2026-07-14 10:23:45.221 +0800] INFO: 🚀 後端伺服器已在 http://localhost:11966 就緒
```

這就是你想要用在 `pnpm dev` 以及閱讀 `pm2 logs` 或 `docker logs` 時用肉眼查看的格式。

### JSON

```bash
LOG_FORMAT="json"
```

輸出會變成每行一個原始 JSON 物件——也就是 pino 的原生格式——沒有顏色，也沒有 ANSI 跳脫序列：

```json
{"level":30,"time":1752459825221,"msg":"🚀 後端伺服器已在 http://localhost:11966 就緒"}
{"level":40,"time":1752460013887,"ip":"203.0.113.45","msg":"IP 已限流"}
{"level":50,"time":1752460101044,"err":{"type":"Error","message":"上游回應 429"},"ip":"1.1.1.1","msg":"ipinfo-io 處理器失敗"}
```

欄位說明：

* `level` 是數值： `20` debug, `30` info, `40` warn, `50` error。
* `time` 是 Unix 時間戳毫秒數。
* `msg` 是人類可讀的訊息。
* 其他任何鍵都是呼叫端附加的結構化內容—— `ip`, `asn`, `前綴`, `err`，依此類推。

只要不是由人來閱讀日誌，就使用 JSON。美化模式中的 ANSI 顏色碼會讓多數解析器混淆。

## `LOG_HTTP`

```bash
LOG_HTTP="true"
```

會為 `/api/*` 路由開啟逐請求記錄。預設關閉，以保持程序管理器日誌易讀。

```
INFO: GET /api/ipinfo?ip=1.1.1.1 → 200
WARN: GET /api/report/abc → 404
```

值得了解的細節：

* 每個請求都會記錄方法、URL、狀態碼與回應時間。
* 等級會對應到結果： `5xx` 或拋出錯誤 → `錯誤`, `4xx` → `warn`，其他一切 → `info`.
* 中介軟體掛載在 **之前** 限流器之後，因此 `429` 回應也會被記錄。請參見 [安全性選項](/developer/zh-tw/configuration/security-options.md).
* 無論此旗標如何，處理器層級的失敗都會被記錄—— `LOG_HTTP` 只會增加成功請求，不會增加錯誤。

{% hint style="warning" %}
請求 URL 包含查詢參數，包括訪客查詢的 IP 位址。在公開實例上，這些屬於個人資料。將 `LOG_HTTP` 其開啟以供除錯，然後再關閉——或確保你的保留政策涵蓋它。
{% endhint %}

## 閱讀健康啟動

啟動行以前置表情符號開頭，讓你一眼就能掃描開機過程。

| 行                                                   | 意義                                                                           |
| --------------------------------------------------- | ---------------------------------------------------------------------------- |
| `📝 已啟用 HTTP 請求記錄（LOG_HTTP=true）`                   | `LOG_HTTP` 已啟用                                                               |
| `🛡️ 已啟用限流器 — 每 N 個請求……`                            | `SECURITY_RATE_LIMIT` 已設定                                                    |
| `🐢 已啟用速度限制器 — 在 N 個請求後減速`                          | `SECURITY_DELAY_AFTER` 已設定                                                   |
| `📥 找不到 MaxMind 資料庫；正在嘗試初始下載……`                     | 首次啟動，正在取得 GeoLite2                                                           |
| `📦 MaxMind 資料庫已載入（…）`                              | 地理位置功能已就緒                                                                    |
| `📦 CAIDA as2org 已載入（…）` / `📦 CAIDA as-rel 已載入（…）` | ASN 組織名稱與連線圖已就緒                                                              |
| `🗓️ … 自動更新計畫：下次檢查時間為 …`                            | 已啟用排程資料集重新整理                                                                 |
| `📦 服務狀態快取已預熱`                                      | service-status 頁面已有資料                                                        |
| `🛰️ 已啟用 Sentry 後端監控`                               | `SENTRY_DSN_BACKEND` 已設定                                                     |
| `🚀 後端伺服器已在 http://localhost:11966 準備就緒`            | API 正在接受流量                                                                   |
| `🚀 靜態檔案伺服器已在 http://localhost:18966 準備就緒`          | SPA 正在提供服務                                                                   |
| `❌ 在資料庫成功載入之前，MaxMind API 會回傳 503`                  | **問題** ——請參見 [MaxMind 設定](/developer/zh-tw/getting-started/maxmind-setup.md) |

兩者 `🚀` 行顯示 `localhost` 因為這就是程序在其自己的主機或容器內綁定的位址。這不是對你公開 URL 的提示。

## 傳送 JSON 日誌

Set `LOG_FORMAT="json"` 並讓你的平台收集 stdout。應用程式中其他任何部分都不需要變更。

{% tabs %}
{% tab title="Docker" %}

```bash
docker run -d -p 18966:18966 \\
  -e LOG_FORMAT="json" \\
  -e LOG_LEVEL="info" \
  --log-driver=json-file \\
  --name myip \\
  jason5ng32/myip:latest
```

之後，任何 Docker 日誌驅動程式或側車收集器（Vector、Fluent Bit、Promtail、Datadog agent）都能把這些行抓走。每一行本來就是有效的 JSON，因此不需要多行或正規表示式解析。
{% endtab %}

{% tab title="pm2" %}
{% code title=".env" %}

```bash
LOG_FORMAT="json"
LOG_LEVEL="info"
```

{% endcode %}

pm2 會把 stdout 寫到自己的日誌檔；把你的收集器指向那些路徑（`pm2 info <name>` 會顯示它們）。

{% hint style="warning" %}
pm2 會在程序第一次啟動時快照環境變數。 `pm2 restart` 會重播舊的快照。變更 `.env`之後，執行 `pm2 delete <name> && pm2 start ecosystem.config.cjs && pm2 save`.
{% endhint %}
{% endtab %}

{% tab title="臨時 / jq" %}

```bash
# 僅限錯誤，最新在前
docker logs myip 2>&1 | jq -c 'select(.level >= 50)'

# 哪些 IP 被限流
docker logs myip 2>&1 | jq -r 'select(.msg == "IP rate-limited") | .ip' | sort | uniq -c

# 將 JSON 串流重新美化以供人類閱讀
docker logs myip 2>&1 | npx pino-pretty
```

{% endtab %}
{% endtabs %}

合理的生產環境基準： `LOG_FORMAT="json"`, `LOG_LEVEL="info"`, `LOG_HTTP` 預設關閉。需要時再加上 `LOG_HTTP="true"` 以便暫時取得每個請求的可見性。

## 相關頁面

* [錯誤監控](/developer/zh-tw/configuration/error-monitoring.md) — 如何 `warn` 以及 `錯誤` 日誌行送達 Sentry
* [安全性選項](/developer/zh-tw/configuration/security-options.md) — 其背後的事件 `IP 已限流` 警告
* [環境變數](/developer/zh-tw/reference/environment-variables.md) — 完整清單
* [後端](/developer/zh-tw/architecture/backend.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/logging.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.
