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

# 日志

两个 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/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`, `prefix`, `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/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 组织名称和连接图已就绪                                                          |
| `🗓️ … 自动更新计划：下次检查时间为 …`                            | 已启用计划中的数据集刷新                                                             |
| `📦 服务状态缓存已预热`                                      | 服务状态页面已有数据                                                               |
| `🛰️ 已启用 Sentry 后端监控`                               | `SENTRY_DSN_BACKEND` 已设置                                                 |
| `🚀 后端服务器已就绪，地址为 http://localhost:11966`            | API 正在接收流量                                                               |
| `🚀 静态文件服务器已就绪，地址为 http://localhost:18966`          | SPA 正在提供服务                                                               |
| `❌ 在数据库成功加载之前，MaxMind API 会返回 503`                  | **问题** ——参见 [MaxMind 设置](/developer/zh/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 被限速") | .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/configuration/error-monitoring.md) ——如何 `warn` 和 `错误` 日志行到达 Sentry
* [安全选项](/developer/zh/configuration/security-options.md) ——位于以下内容背后的事件 `IP 被限流` 警告
* [环境变量](/developer/zh/reference/environment-variables.md) ——完整列表
* [后端](/developer/zh/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/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.
