# 环境日志查询与错误排查

使用 Hosted Service CLI 按环境和时间查询运行、迁移日志，通过请求标识追踪错误，并区分业务失败与日志查询失败。

Hosted Service 的日志查询面向一个 Project 下的一个 Environment。先确认发布版本和部署状态，再查询失败请求所在时间段的日志。`/healthz` 成功、部署成功或工作流完成，都不能替代真实业务请求验证。

## 查询范围与日志来源

每次查询必须指定 `workspaceId`、`projectId`、`environmentId`、`startTime` 和 `endTime`。其中 `environmentId` 是后端项目的环境 ID，取自环境列表或详情；不是 App Runtime ID，也不是 Deployment ID。

查询覆盖所选环境在时间窗口内可解析的运行实例和数据库迁移执行记录，包括该窗口内的历史部署，不限于当前最新 Deployment。多个环境共用 Slot 时，结果仍按环境隔离。不能省略环境参数来查询整个项目，也不能自行指定主机、容器或执行身份扩大查询范围。

平台根据环境运行记录确定查询范围，再从日志采集与检索服务读取正文；业务数据库不是日志正文查询入口。在使用 SLS 的平台环境中，正文来自 SLS；本命令不提供 ARMS 指标或全平台链路查询。Runtime 方法调用使用独立的 [Runtime 日志与调用链路入口](/features/runtime-logs/)，按 `applicationRuntimeId` 查询。开发者使用当前登录身份查询，无需配置云日志凭据。

这个入口不包含所有平台服务的内部日志，也不等同于发布构建日志。构建失败先看 Release Operation，迁移失败结合 Migration Operation 和 Attempt，业务运行失败再查环境日志。请求在到达业务进程前被网关拒绝时，目标环境可能没有对应日志。

## 先确认环境和时间

先从当前工作区和项目记录取得真实 ID，再查看环境：

```bash
baijimu hosted-service env list \
  --workspace-id "$WORKSPACE_ID" \
  --project-id "$PROJECT_ID" \
  --json
```

以下命令中的大写变量均需替换为本次实际值，不能照抄其他工作区或历史请求的 ID。

时间使用 RFC3339，必须带时区并精确到整秒；`endTime` 必须晚于 `startTime`。例如 `2026-01-15T10:00:00+08:00` 与 `2026-01-15T02:00:00Z` 表示同一时刻。先选择覆盖故障发生时间的短窗口，再按需分段扩大。

CLI 的精确参数以本机帮助为准：

```bash
baijimu hosted-service debug --help
baijimu hosted-service debug logs-search --help
baijimu hosted-service debug logs-trace --help
```

## 搜索运行和迁移日志

第一次查询先只使用环境和时间，避免关键词或级别过滤掉需要的记录：

```bash
baijimu hosted-service debug logs-search \
  --workspace-id "$WORKSPACE_ID" \
  --project-id "$PROJECT_ID" \
  --environment-id "$ENVIRONMENT_ID" \
  --start-time "$START_TIME" \
  --end-time "$END_TIME" \
  --limit 20 \
  --json
```

确认有日志后，可添加 `--keyword "$KEYWORD"` 搜索文本，或使用 `--level "$LEVEL"` 按日志实际记录的级别过滤。未记录级别的日志不会匹配级别过滤；纯文本中的关键词也不保证存在同名结构化字段。

`limit` 控制一次检索的记录数量，不表示全量导出。时间跨度和数量上限由目标平台配置决定；超过限制时缩短时间窗口或降低 `limit`，不要把某个环境的上限当作所有环境的固定值。

## 按请求或 Trace 标识追踪

从失败请求、应用响应或已有日志取得真实的请求标识后，使用同一个环境和时间窗口：

```bash
baijimu hosted-service debug logs-trace \
  --workspace-id "$WORKSPACE_ID" \
  --project-id "$PROJECT_ID" \
  --environment-id "$ENVIRONMENT_ID" \
  --start-time "$START_TIME" \
  --end-time "$END_TIME" \
  --request-id "$REQUEST_ID" \
  --limit 20 \
  --json
```

也可用 `--trace-id "$TRACE_ID"` 替代 `--request-id`；至少提供一个。两个都提供时，查询要求同时匹配，不是二选一。

该命令只返回所选环境内匹配的日志，不自动扩大到其他服务或环境。应用必须实际记录可检索的 `requestId` 或 `traceId`；若标识只出现在消息正文中，可以先用 `logs-search --keyword` 定位。不要把前端应用 ID、工作流实例 ID 或 Deployment ID 当作请求标识。

## 如何读取结果

成功结果使用 [CModel 错误模型](/integration/cmodel-error-model/)：`errorCode` 为字符串 `"0"`，日志列表在 `data.entries` 中。成功空结果示例：

```json
{
  "contractVersion": "1.0.0",
  "errorCode": "0",
  "data": {
    "entries": [],
    "complete": true
  }
}
```

日志条目的主要字段：

| 字段                          | 含义                                                      |
| --------------------------- | ------------------------------------------------------- |
| `timestamp`                 | Unix 秒时间戳，用于和失败请求时间对齐。                                  |
| `projectId`、`environmentId` | 该条日志所属项目和环境。                                            |
| `message`、`source`、`level`  | 日志正文、输出来源及可用时的级别。                                       |
| `execution`                 | 执行来源；`runtimeProcess` 表示运行进程，`migrationAttempt` 表示迁移尝试。 |
| `traceId`、`requestId`       | 可用时的关联标识，可能为 `null`。                                    |
| `contentComplete`           | 该条正文是否完整；为 `false` 时不能把截断内容当成完整错误信息。                    |

`execution.deploymentId` 是 Hosted Deployment 身份，`execution.runtimeDeploymentId` 是物理运行身份；迁移条目还包含 `attemptId`。这些字段用于解释结果，不是公共查询的输入选择器。

`data.complete` 表示本次查询及返回正文的完整性；即使为 `true`，结果仍受 `limit` 限制，不代表已经导出整个时间窗口的所有日志。需要更多记录时，按时间拆分查询并核对内容。

### 空列表不等于没有故障

成功空列表表示当前条件下没有可返回的匹配日志。依次检查：

1. 工作区、项目、环境是否选对，时区是否一致。
2. 失败请求是否实际到达业务进程，日志是否已写出并完成采集。
3. 移除关键词、级别和请求标识过滤后是否有记录。
4. 目标时间是否仍在平台日志保留范围内。
5. 历史运行是否具有能归属到该环境的可查询日志。

查询不会因为历史覆盖情况未知而先行拒绝整个时间窗口，也不会自动补采缺失的历史日志。如果查询返回错误，必须按查询失败处理，不能显示为“暂无日志”。

## 区分业务错误和日志查询错误

有效 CModel 响应使用 HTTP `200` 传输，业务成败由 `errorCode` 决定。`errorCode != "0"` 即为失败；不能把 HTTP `200` 当成业务成功，也不能仅凭错误文案猜测是数据库密码问题。CModel 之外的 HTTP 401、500、超时或非 JSON 响应，应先区分发生在哪个请求边界。

| 现象或公开错误码                               | 排查动作                                                  |
| -------------------------------------- | ----------------------------------------------------- |
| 业务请求返回非零 `errorCode`，日志查询成功            | 根据业务错误码和同次请求日志定位业务处理、鉴权或依赖失败。                         |
| `UNAUTHORIZED`                         | 检查用于日志查询的 CLI 登录身份是否有效；与业务 Endpoint 的服务 token 分开处理。   |
| `FORBIDDEN`、`HOSTED_SERVICE_FORBIDDEN` | 核对当前身份的工作区、项目权限及环境归属；重新登录不能代替授权。                      |
| `HOSTED_SERVICE_NOT_FOUND`             | 从环境列表重新确认资源身份，不复用已删除资源的 ID。                           |
| `INVALID_LOG_QUERY`                    | 检查整秒时间、先后顺序、窗口大小、limit 和过滤参数；运行记录过多时缩小窗口。             |
| `LOG_QUERY_UNAVAILABLE`                | 日志查询能力或范围解析不可用；保留查询参数和公开错误信息交由平台维护者定位。                |
| `LOG_PROVIDER_ERROR`                   | 日志检索依赖返回错误；由平台维护者检查日志服务状态，不据此修改业务数据库密码。               |
| `LOG_SCOPE_UNSUPPORTED`                | 当前查询流程不再因历史覆盖未知拒绝查询；仍收到此码时保留证据，由平台维护者核对已部署版本和请求链路。    |
| 业务入口返回 `GATEWAY2_INTERNAL_ERROR`       | 仅凭这个通用错误码不能定位根因。对齐方法、时间和请求标识查目标环境日志；没有对应业务日志时提交平台侧排查。 |

客户端是否自动重试应遵循失败响应中可用的 `data.retryable`，不要依据 HTTP `200`、错误文案或通用错误码无限重试。涉及平台应用会话时，继续查看 [安全与故障排查](/development/bundle-development/platform-application-development/security-and-troubleshooting/)。

## 提交排查证据

保留故障发生时间及其时区、工作区/项目/环境 ID、项目版本、Deployment、公开错误码、可公开的请求标识，以及脱敏后的查询命令和结果。模块调用另附 service 和方法名；平台应用另附应用版本与安装身份。

分别记录“业务请求失败”和“日志查询失败”，说明复现步骤及查询是否返回空列表。不要提交完整 Token、Cookie、数据库连接串、密码或包含个人数据的完整请求体。
