

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 NDJSON 端点发送日志（ND-JSON 日志）
ndjson 端点

ND-JSON 日志端点 (`/ingest/bulk`) 接受 [NDJSON（换行符分隔 JSON](https://github.com/ndjson/ndjson-spec)）格式的日志。每行只包含一个 JSON 值，由换行符分隔。

如果您使用的是不记名令牌身份验证，请先完成中的设置步骤，[设置不记名令牌身份验证](CWL_HTTP_Endpoints_BearerTokenAuth.md)然后再继续。

## 请求格式


每行发送一个 JSON 值，以 `\n` (LF) 或 `\r\n` (CRLF) 分隔。空行会被静默忽略。

```
{"timestamp":1771007942000,"message":"event one","level":"INFO"}
{"timestamp":1771007943000,"message":"event two","level":"ERROR"}
{"timestamp":1771007944000,"message":"event three","level":"DEBUG"}
```

`application/json`和`application/x-ndjson`都被接受为内容类型。

## 接受的 JSON 值类型


根据 NDJSON 规范 (RFC 8259)，每行都接受任何有效的 JSON 值。

**JSON 对象（最常见）：**

```
{"timestamp":1771007942000,"message":"User logged in","service":"auth"}
{"timestamp":1771007943000,"error":"Connection timeout","service":"api"}
```

**JSON 数组（扁平化为单个事件）：**

```
[{"timestamp":1000,"message":"a"},{"timestamp":2000,"message":"b"}]
```

此单行生成 2 个事件。每个数组元素都变成一个单独的日志事件。

**原始值：**

```
"a plain string log message"
42
true
null
```

每个基元都变成自己的事件，并带有服务器的当前时间戳。

**混合类型：**

```
{"timestamp":1771007942000,"message":"structured event"}
"unstructured string message"
42
{"timestamp":1771007943000,"error":"something failed"}
```

所有 4 行都被接受为有效事件。


| 行内容 | 行为 | 
| --- | --- | 
| JSON 对象 | 已接受，如果存在则提取时间戳 | 
| JSON 数组 | 扁平化 — 每个元素都变成一个单独的事件 | 
| 空数组 [] | 已接受，生成 0 个事件 | 
| json 字符串 | 已接受为活动消息 | 
| JSON 编号 | 已接受为活动消息 | 
| json 布尔值 | 已接受为活动消息 | 
| JSON 空 | 已接受为活动消息 | 
| JSON 无效 | 已跳过（已计数，处理仍在继续） | 
| 空行 | 已忽略（未计为已跳过） | 

## 时间戳字段


该`"timestamp"`字段以纪元毫秒（不是秒）为单位。


| 格式 | 示例 | 解释为 | 
| --- | --- | --- | 
| 数字（毫秒） | "timestamp":1771007942000 | 1771007942000 ms | 
| 缺失 | （没有时间戳字段） | 服务器当前时间 | 
| 非数字 | "timestamp":"invalid" | 服务器当前时间 | 
| 非对象线 | "hello", 42, true | 服务器当前时间 | 

## 无效的行


无效 JSON 的行会被静默跳过并计数。下一行继续处理。

```
{"message":"valid event"}
this is not valid json
{"message":"another valid event"}
```

结果：摄取 2 个事件，跳过 1 个事件。返回 `HTTP 200`。

如果所有行都无效，则返回`HTTP 400``"All events were invalid"`。

## 示例请求


```
curl -X POST "https://logs.<region>.amazonaws.com/ingest/bulk?logGroup=MyLogGroup&logStream=MyStream" \
  -H "Authorization: Bearer ACWL<token>" \
  -H "Content-Type: application/x-ndjson" \
  -d '{"timestamp":1771007942000,"message":"User logged in","level":"INFO"}
{"timestamp":1771007943000,"message":"Query took 42ms","level":"DEBUG"}
{"timestamp":1771007944000,"error":"Connection refused","level":"ERROR"}'
```

## 响应


**成功（接受所有活动）：**

```
HTTP 200 OK
{}
```

**部分成功（某些事件被拒绝）：**

```
{
  "partialSuccess": {
    "rejectedLogRecords": 5,
    "errorMessage": "{\"tooOldLogEventCount\": 3, \"tooNewLogEventCount\": 1, \"expiredLogEventCount\": 1}"
  }
}
```

该`rejectedLogRecords`字段是被拒绝的事件的总数。该`errorMessage`字段包含按拒绝原因划分的 JSON 编码细分：
+ `tooOldLogEventCount`— 时间戳早于保留期的事件
+ `tooNewLogEventCount`— 将来时间戳过远的事件
+ `expiredLogEventCount`— 在处理过程中过期的事件

## 最佳实践


### 对事件进行批处理


为了提高性能和效率：
+ 尽可能在单个请求中批量处理多个事件
+ 建议的批处理大小：每个请求 10—100 个事件
+ 最大请求大小：1 MB

### 错误处理


在应用程序中实现正确的错误处理。常见的 HTTP 状态码：
+ `200 OK`— 成功提取日志
+ `400 Bad Request`— 请求格式或参数无效
+ `401 Unauthorized`— 不记名令牌无效或已过期
+ `403 Forbidden`— 权限不足
+ `404 Not Found`— 日志组或直播不存在
+ `429 Too Many Requests`— 超出速率限制
+ `500 Internal Server Error`— 服务错误（使用指数退避重试）

## 限制

+ 最大事件大小：每个事件 256 KB
+ 最大请求大小：1 MB
+ 每个请求的最大事件数：10,000
+ 日志组名称必须遵循 CloudWatch 日志命名约定
+ 如果使用不记名令牌身份验证，则必须在日志组上启用持有者令牌身份验证。