> ## Documentation Index
> Fetch the complete documentation index at: https://docs.logbrew.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Định dạng phản hồi API và ví dụ phản hồi JSON

> Đọc phản hồi API của LogBrew cho danh sách telemetry, trang cursor, sự kiện trực tiếp, thao tác thay đổi, trạng thái thành công và lỗi.

Trang này đưa ra một ví dụ cho mỗi nhóm phản hồi của
[Telemetry API](/vi/reference/telemetry-api). Mọi giá trị đều là dữ liệu giả lập.
Để xem mã lỗi và cách khắc phục, đọc [Lỗi API](/vi/reference/api-errors).

## Đọc phản hồi

Đọc mọi phản hồi theo thứ tự sau:

1. Đọc trạng thái HTTP.
2. Kiểm tra body có đúng cấu trúc mà route quy định.
3. Kiểm tra mỗi `project_id` nằm trong phạm vi dự án đã yêu cầu.
4. Giữ nguyên các giá trị enum chuẩn và các định danh.
5. Chỉ làm theo `next_action` khi client hỗ trợ `code` và `target` của nó.
6. Coi `null`, trường bị lược bỏ và danh sách trống là ba trạng thái khác nhau.

Phản hồi `200 OK` có thể chứa danh sách trống. Danh sách log trống nghĩa là
không có log nào khớp với yêu cầu. Điều đó không có nghĩa là vấn đề, trace hay
hành động cũng trống. Không ghép các tín hiệu chỉ vì dấu thời gian của chúng
gần nhau. Chỉ chuyển sang một trace khi phản hồi chứa đúng `trace_id` của trace
đó.

`404` và danh sách trống là hai kết quả khác nhau. Route danh sách trả về `[]`
khi không có bản ghi nào khớp. Route chi tiết trả về `404` với `code: not_found`
khi không tìm thấy bản ghi nào đọc được. Cả hai kết quả đều không chứng minh
rằng việc gửi dữ liệu đã thất bại.

## Cần gửi gì

Phản hồi chỉ hữu ích khi telemetry bạn gửi đủ tốt. Gửi các giá trị sau trong
mọi envelope hoặc khi thiết lập SDK:

* `release` và `environment`.
* Tên ổn định cho dịch vụ, hành động và chỉ số.
* Ngữ cảnh trace khi log, span, hành động và vấn đề thuộc cùng một yêu cầu.
* Các giá trị mức độ nghiêm trọng chuẩn: `info`, `warning`, `error` và
  `critical`.
* Các thuộc tính giúp gỡ lỗi, không chứa thông tin bí mật hay dữ liệu cá nhân không cần
  thiết.

Xem [Tích hợp SDK](/vi/guides/sdk-ingestion) và
[Kiểm soát dữ liệu ghi nhận](/vi/guides/safe-capture).

## Phản hồi khi gửi dữ liệu

Các SDK công khai tự đọc phản hồi của `POST /v1/events`. Mã ứng dụng không cần
xử lý phản hồi này.

### Phản hồi batch của SDK

Một batch SDK thành công trả về `200 OK` cùng số lượng được chấp nhận cho từng
luồng:

```json theme={null}
{
  "issues": 1,
  "logs": 2,
  "trace_spans": 3,
  "actions": 1,
  "metrics": 1,
  "already_accepted": 0,
  "context_updated": true,
  "next": "review accepted telemetry in logs, issues, traces, actions, metrics, or live feed",
  "next_action": {
    "code": "review_ingested_telemetry",
    "target": "telemetry_reads"
  }
}
```

| Trường | Ý nghĩa |
| - | - |
| `issues`, `logs`, `trace_spans`, `actions`, `metrics` | Các sự kiện trong batch này mà LogBrew đã chấp nhận. |
| `already_accepted` | Các sự kiện có ID mà LogBrew đã chấp nhận trước đó. LogBrew không lưu lại chúng lần nữa. |
| `context_updated` | `true` khi batch đã cập nhật ngữ cảnh bản phát hành hoặc môi trường. |

Các số lượng chỉ tính cho batch này. Khi gửi lại một batch mà LogBrew đã chấp
nhận, phản hồi trả về `0` cho từng luồng và số sự kiện trong
`already_accepted`. Giữ nguyên ID sự kiện gốc khi thử lại.

### Phản hồi envelope gốc

`POST /api/telemetry/ingest` trả về `200 OK` cùng số mục được chấp nhận cho
từng luồng:

```json theme={null}
{
  "issues": 0,
  "logs": 1,
  "trace_spans": 0,
  "actions": 1,
  "already_accepted": 0,
  "next": "review accepted telemetry in logs, issues, traces, actions, or live feed",
  "next_action": {
    "code": "review_ingested_telemetry",
    "target": "telemetry_reads"
  }
}
```

Phản hồi gốc không có trường `metrics` hay `context_updated`. Không tự thêm
các trường này. `already_accepted` đếm các mục có `id` mà LogBrew đã chấp nhận
trước đó cho dự án. Xem [Gửi trực tiếp envelope gốc](/vi/guides/sdk-ingestion#required-envelope-fields).

### Lỗi khi gửi dữ liệu

`401` với `code: ingest_key_invalid` nghĩa là bearer token gửi dữ liệu đã bị
thu hồi, đã hết hạn hoặc không hợp lệ cho dự án. Với `POST /v1/events`, yêu cầu
thiếu bearer token hoặc dùng bearer token không phải khóa gửi dữ liệu sẽ nhận
`401` với `code: unauthorized`. Dùng bearer token gửi dữ liệu hiện tại thuộc
phạm vi dự án. Không thử lại bằng bearer token của tài khoản.

Một batch SDK bị từ chối trả về `422` với `code: validation_failed`:

```json theme={null}
{
  "error": "SDK event ids must be unique within a batch",
  "code": "validation_failed",
  "next": "send release/environment context plus issue, log, span, action, or metric events from a current LogBrew SDK",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

Các giá trị `error` khác gồm `SDK event batch requires at least one event` và
`SDK event type is not supported by this ingest route`. Kiểm tra phiên bản SDK
và cấu hình truyền tải. Không gửi batch trống. Không đổi loại sự kiện hay ID
chỉ để batch vượt qua bước kiểm tra hợp lệ.

Yêu cầu dùng phương thức khác `POST` trả về `405` với
`code: method_not_allowed`. Body JSON không đọc được trả về `code: invalid_json`.

## Định dạng phản hồi danh sách telemetry

Theo mặc định, route danh sách trả về một mảng JSON trần. Danh sách trống
thành công là `[]`.

Với `pagination=cursor`, route trả về một envelope. Khóa collection khớp với
loại tín hiệu:

| Route | Khóa collection |
| - | - |
| `/api/logs` | `logs` |
| `/api/telemetry/issues` | `issues` |
| `/api/telemetry/issues/{issue_id}/events` | `events`, kèm `issue_id` ở cấp cao nhất |
| `/api/telemetry/actions` | `actions` |
| `/api/telemetry/metrics` | `metrics` |
| `/api/telemetry/releases` | `releases` |
| `/api/telemetry/traces` | `traces`, kèm `naming_quality` ở cấp cao nhất |

`next_cursor` là một object chứa các trường để đọc tiếp, hoặc `null` ở trang
cuối. Các dòng được sắp xếp từ mới nhất đến cũ nhất. Xem [phân trang bằng cursor](/vi/reference/telemetry-api-filters#cursor-pagination).

### <span id="log-response">Phản hồi log</span>

Một trang cursor của log với `limit=1`:

```json theme={null}
{
  "logs": [
    {
      "id": "150d1288-bec2-49ec-a036-3f7ac55f1b2d",
      "project_id": "123e4567-e89b-12d3-a456-426614174000",
      "level": "warning",
      "severity": "warning",
      "triage": {
        "effective_severity": "warning",
        "ignored": false,
        "rule_applied": false
      },
      "source": "runtime",
      "message": "checkout retry scheduled",
      "attributes": { "route": "/checkout" },
      "occurred_at": "2026-06-01T12:00:00Z",
      "environment": "production",
      "release": "api@1.2.3",
      "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
      "span_id": "00f067aa0ba902b7",
      "service_name": "checkout-api",
      "sdk_name": "@logbrew/node",
      "sdk_version": "0.1.8",
      "next_action": {
        "code": "inspect_trace",
        "target": "trace_summary"
      }
    }
  ],
  "next_cursor": {
    "time": "2026-06-01T12:00:00Z",
    "id": "150d1288-bec2-49ec-a036-3f7ac55f1b2d"
  }
}
```

Log có `level` để tương thích và `severity` để hiển thị. Cả hai đều chứa giá trị
chuẩn. `triage` chứa kết quả của quy tắc mức độ nghiêm trọng. Xem
[phản hồi quy tắc mức độ nghiêm trọng](#severity-rule-responses).

`trace_id` và `span_id` là `null` khi log không có liên kết trace. Khi đó,
`next_action` là `inspect_related_logs` với target `telemetry_logs`. Log, vấn đề
và hành động dùng chung 2 cặp `next_action` này.

`GET /api/logs/{log_id}` trả về một log với cùng cấu trúc.

### <span id="issue-response">Phản hồi vấn đề</span>

`GET /api/telemetry/issues/{issue_id}` trả về một vấn đề đã gộp nhóm. Route danh
sách trả về các object giống hệt. Ví dụ này dùng phiên bản phản hồi mặc định 1:

```json theme={null}
{
  "id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "fingerprint": "payment-error",
  "severity": "error",
  "triage": {
    "effective_severity": "error",
    "ignored": false,
    "rule_applied": false
  },
  "title": "PaymentError",
  "message": "payment provider timed out",
  "stack_trace": null,
  "attributes": {},
  "environment": "production",
  "release": "checkout@1.2.3",
  "service_name": "checkout-api",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "next_action": {
    "code": "inspect_trace",
    "target": "trace_summary"
  },
  "status": "unresolved",
  "occurrence_count": 2,
  "first_seen_at": "2026-07-13T07:00:00Z",
  "last_seen_at": "2026-07-13T08:00:00Z"
}
```

Ở phiên bản 1, `status` là `unresolved`, `resolved` hoặc `ignored`. Với vấn đề
đã lưu trữ, `triage.ignored` là `true`. Về các cặp `next_action` và các lượt
đọc tiếp theo, xem
[Điều tra một vấn đề](/vi/guides/investigate-an-issue).

`first_seen_at` và `last_seen_at` là thời điểm của lần xảy ra đầu tiên và gần
nhất. Hai giá trị này không đổi khi trạng thái thay đổi.

Một số trường chỉ xuất hiện khi LogBrew có dữ liệu:

| Trường | Khi nào xuất hiện |
| - | - |
| `span_id` | Vấn đề có liên kết span. Nếu không, trường này bị lược bỏ. |
| `diagnostics` | Lần xảy ra gần nhất có loại ngoại lệ hoặc breadcrumb. Xem [lịch sử lần xảy ra của vấn đề](#issue-occurrence-history). |
| `symbolication` | Chỉ có ở `GET /api/telemetry/issues/{issue_id}`, khi vấn đề có định danh artifact (tệp bản dựng) của bản phát hành. Xem [Source map JavaScript](/vi/guides/source-maps). |

`symbolication.status` là `resolved`, `invalid_metadata`,
`artifact_not_found`, `source_not_resolved` hoặc `unavailable`. Route danh
sách, thao tác đổi trạng thái và thao tác đổi quy tắc không trả về
`symbolication`.

Với `response_version=2`, vấn đề có cùng các trường, kèm các thay đổi sau:

| Trường | Giá trị ở phiên bản 2 |
| - | - |
| `status` | `unresolved`, `resolved` hoặc `archived`. Phiên bản 1 hiển thị `archived` thành `ignored`. |
| `priority` | `high`, `medium` hoặc `low`. |
| `priority_source` | `manual` khi một người đã đặt mức ưu tiên. `derived` khi mức ưu tiên theo mức độ nghiêm trọng hiệu lực. |

```json theme={null}
{
  "id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
  "status": "archived",
  "severity": "error",
  "priority": "low",
  "priority_source": "manual"
}
```

Ví dụ này chỉ hiển thị một số trường. Mức ưu tiên suy ra là `high` cho `error`
và `critical`, `medium` cho `warning`, và `low` cho `info`. Mức ưu tiên này dựa
trên `triage.effective_severity`, nên quy tắc mức độ nghiêm trọng của vấn đề có
thể thay đổi nó.

Với `response_version=3`, vấn đề có mọi trường của phiên bản 2 và thêm
`assignee`. `assignee` là `null` khi vấn đề chưa có người phụ trách:

```json theme={null}
{
  "id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
  "status": "unresolved",
  "priority": "high",
  "priority_source": "derived",
  "assignee": {
    "user_id": "5d6e7f80-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
    "name": "Ada Example",
    "email": "ada@example.com"
  }
}
```

| Trường | Ý nghĩa |
| - | - |
| `assignee.user_id` | ID người dùng của người phụ trách. Gửi giá trị này làm `assignee` trong bộ lọc hoặc thao tác thay đổi. |
| `assignee.name` | Tên người phụ trách, hoặc `null` khi tài khoản chưa có tên. |
| `assignee.email` | Địa chỉ email của người phụ trách. |

Vấn đề không hiển thị người phụ trách khi thành viên được giao không còn đọc
được dự án.

Với `response_version=4`, `assignee` có thêm `type`. Người phụ trách `user` có
`user_id`, `name` và `email`, giống phiên bản 3. Người phụ trách `team` có
`team_id`, `slug` và `name`. Phiên bản 3 hiển thị nhóm phụ trách là `null`.
CLI yêu cầu phiên bản 4:

```json theme={null}
{
  "assignee": {
    "type": "team",
    "team_id": "7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    "slug": "payments",
    "name": "Payments"
  }
}
```

Mọi `response_version` khác trả về `422` với `code: validation_failed`. Một
trang cursor dùng cùng phiên bản cho mọi vấn đề trong `issues`.

### <span id="assignee-list-response">Phản hồi danh sách người phụ trách</span>

`GET /api/telemetry/issues/assignees?project_id=<project_id>` trả về mọi tài
khoản có thể được giao vấn đề trong dự án:

```json theme={null}
{
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "assignees": [
    {
      "user_id": "5d6e7f80-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
      "name": "Ada Example",
      "email": "ada@example.com"
    },
    {
      "user_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
      "name": null,
      "email": "sam@example.com"
    }
  ]
}
```

Thêm `response_version=2` để nhận thêm `teams`: mọi nhóm trong tổ chức của dự
án, kèm `team_id`, `slug` và `name`.

Nếu tài khoản không đọc được dự án, route trả về `404` với
`code: not_found`.

### <span id="action-response">Phản hồi hành động</span>

```json theme={null}
{
  "id": "d8ee3a6f-3918-440b-96cb-14166419399a",
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "checkout_failed",
  "distinct_id": "user_123",
  "session_id": "session_456",
  "occurred_at": "2026-06-01T12:00:00Z",
  "properties": { "surface": "checkout" },
  "environment": "production",
  "release": "checkout@1.2.3",
  "service_name": "checkout-api",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "next_action": {
    "code": "inspect_trace",
    "target": "trace_summary"
  }
}
```

`distinct_id` theo dõi một đối tượng thực hiện hoặc một phiên. Coi `distinct_id`
và `session_id` là ID opaque (không diễn giải nội dung). `session_id` và
`trace_id` là `null` khi chưa ghi nhận. `span_id` bị lược bỏ khi chưa ghi nhận.
Hành động không có mức độ nghiêm trọng. Xem [Ghi nhận sự kiện sản phẩm](/vi/guides/product-events).

### Phản hồi chỉ số

```json theme={null}
{
  "id": "6f1c2d3e-4a5b-4c6d-8e7f-901234567890",
  "event_id": "metric-1",
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "http.server.duration",
  "kind": "histogram",
  "value": 12.5,
  "unit": "ms",
  "temporality": "delta",
  "attributes": {},
  "occurred_at": "2026-07-13T08:00:00Z",
  "environment": "production",
  "release": "checkout@1.2.3",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "service_name": "checkout-api",
  "sdk_name": "@logbrew/node",
  "sdk_version": "0.1.8"
}
```

Mỗi mục là một mẫu. Không dùng số mẫu làm số sự kiện hay số người dùng.
`unit`, `temporality`, `trace_id` và `span_id` là `null` khi chưa ghi nhận.
Giá trị `null` không phải là 0.

### Phản hồi bản phát hành

```json theme={null}
{
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "release": "api@1.2.3",
  "environment": "production",
  "service_name": "checkout-api",
  "issue_count": 3,
  "log_count": 824,
  "trace_span_count": 421,
  "action_count": 19,
  "metric_count": 87,
  "first_seen_at": "2026-06-01T12:00:00Z",
  "last_seen_at": "2026-06-01T12:15:00Z",
  "trace_health": {
    "status": "errors_observed",
    "trace_count": 42,
    "error_trace_count": 3,
    "error_rate_basis_points": 714
  },
  "next_action": {
    "code": "inspect_release_issues",
    "target": "telemetry_issues"
  }
}
```

Mỗi dòng ứng với một dự án, bản phát hành, môi trường và dịch vụ. Các số lượng
của dòng chỉ mô tả riêng dòng đó.

`trace_health.status` là `unknown` khi dòng không có trace, hoặc là
`no_errors_observed` hay `errors_observed`. `error_rate_basis_points` là tỷ lệ
trace có span lỗi, từ `0` đến `10000`. Đây không phải tỷ lệ lỗi của mọi yêu
cầu.

`next_action` trỏ đến loại tín hiệu đầu tiên có dữ liệu, theo thứ tự sau:

| `code` | `target` |
| - | - |
| `inspect_release_issues` | `telemetry_issues` |
| `inspect_release_traces` | `trace_explorer` |
| `inspect_release_logs` | `telemetry_logs` |
| `inspect_release_actions` | `telemetry_actions` |
| `inspect_release_metrics` | `telemetry_metrics` |
| `review_release_telemetry` | `telemetry_reads` |

Xem [Bản phát hành](/vi/concepts/releases).

### Phản hồi khám phá trace

`GET /api/telemetry/traces?pagination=cursor` trả về một dòng cho mỗi trace,
kèm biên nhận `naming_quality` cho trang được trả về:

```json theme={null}
{
  "traces": [
    {
      "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
      "project_ids": ["123e4567-e89b-12d3-a456-426614174000"],
      "root_span_name": "POST /checkout",
      "root_service_name": "checkout-api",
      "root_operation": "http.server",
      "span_count": 3,
      "error_span_count": 1,
      "service_count": 1,
      "started_at": "2026-06-01T12:00:00Z",
      "duration_ms": 45,
      "services": ["checkout-api"],
      "releases": ["checkout@1.2.3"],
      "environments": ["production"],
      "next_action": {
        "code": "inspect_trace",
        "target": "trace_summary"
      }
    }
  ],
  "next_cursor": null,
  "naming_quality": {
    "evaluated_traces": 1,
    "meaningful_name_traces": 1,
    "generic_name_traces": 0,
    "unmatched_route_traces": 0,
    "generic_operation_traces": 0,
    "truncated": false,
    "next_action": null
  }
}
```

`naming_quality` chỉ áp dụng cho trang được trả về. Đây không phải điểm số cho
toàn tài khoản. `truncated: true` nghĩa là còn trang khác. Khi trang có tên
chung chung, route không khớp hoặc thao tác chung chung, `next_action` là
`improve_trace_naming` với target `sdk_configuration`. Nếu không có
`pagination=cursor`, route trả về một mảng trace trần và không có
`naming_quality`.

`next_cursor` chứa `time` và `trace_id`. Gửi chúng dưới dạng `cursor_time` và
`cursor_trace_id`.

`GET /api/telemetry/traces/{trace_id}` trả về các span của một trace.
`GET /api/telemetry/traces/{trace_id}/summary` trả về span gốc, các span lỗi,
dịch vụ, thời lượng và đường đi chậm nhất, không kèm thuộc tính thô của span.
`404` ở bản tóm tắt nghĩa là không có trace nào khớp với toàn bộ phạm vi. Không
bỏ bộ lọc để thử lại. Xem [phản hồi span và bản tóm tắt trace](#trace-spans-and-summary-responses).

### Danh sách trống và bản ghi không tồn tại

Lượt đọc danh sách có thể không có kết quả khớp. Lượt đọc chi tiết tuân theo quy
ước khác:

| Yêu cầu | Thành công | Không có bản ghi đọc được |
| - | - | - |
| `GET /api/logs/{log_id}` | `200` với một [log](#log-response) | `404` với `code: not_found` |
| `GET /api/telemetry/issues/{issue_id}` | `200` với một [vấn đề](#issue-response) | `404` với `code: not_found` |
| `GET /api/telemetry/issues/{issue_id}/events` | `200` với các lần xảy ra | `404` với `code: not_found` ở trang đầu tiên |
| `GET /api/telemetry/traces/{trace_id}` | `200` với các span | `200` với `[]` |
| `GET /api/telemetry/traces/{trace_id}/summary` | `200` với một bản tóm tắt | `404` với `code: not_found` |

Log không tồn tại trả về `404` sau:

```json theme={null}
{
  "error": "log not found",
  "code": "not_found",
  "next": "check the resource id or filters and retry",
  "next_action": {
    "code": "check_resource",
    "target": "resource"
  }
}
```

Vấn đề không tồn tại dùng `"error": "issue not found"`. Bản tóm tắt trace không
tồn tại dùng `"error": "trace not found"`. ID không xác định và ID mà tài khoản
không đọc được đều trả về cùng một phản hồi.

Danh sách với một `project_id` mà tài khoản không đọc được trả về `200` với danh
sách trống. Kiểm tra ID dự án trước khi báo rằng không có dữ liệu.

### Lựa chọn dự án bị từ chối

Danh sách log, vấn đề, hành động, chỉ số, bản phát hành và trace nhận một dự án
qua `project_id`, hoặc từ 2 đến 50 dự án qua `project_ids`. Danh mục thuộc tính
log nhận cùng các tham số chọn này. Lịch sử lần xảy ra của vấn đề không nhận
chúng.

Yêu cầu có cả `project_id` lẫn `project_ids` trả về `422`:

```json theme={null}
{
  "error": "project_id and project_ids are mutually exclusive",
  "code": "validation_failed",
  "next": "use project_id for one project, project_ids=uuid,uuid for two to fifty projects, or omit both for all readable projects",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

`project_ids` có UUID không hợp lệ, có ID lặp lại, hoặc có ít hơn 2 hay nhiều
hơn 50 ID cũng trả về `422` với `code: validation_failed`.

Nếu tài khoản không đọc được một dự án trong tập `project_ids`, toàn bộ yêu cầu
trả về `404`. Yêu cầu không trả về các dự án còn lại thành kết quả một phần:

```json theme={null}
{
  "error": "project selection not found",
  "code": "not_found",
  "next": "refresh readable projects and retry with only project IDs you can read",
  "next_action": {
    "code": "check_resource",
    "target": "resource"
  }
}
```

Hiển thị lỗi, không hiển thị danh sách trống hay số đếm bằng 0. Đọc lại danh
sách dự án. Không âm thầm bỏ một dự án, và không thử lại trên tất cả dự án.
Thông tin xác thực được ủy quyền, chẳng hạn một kết nối MCP, trả về `403` với
`code: forbidden` cho dự án nằm ngoài phạm vi kết nối đó. Xem
[phạm vi dự án](/vi/reference/telemetry-api-filters#project-scope).

### <span id="cursor-errors">Lỗi cursor</span>

Log, vấn đề, hành động, chỉ số và lần xảy ra của vấn đề dùng `cursor_time` và
`cursor_id`. Cursor bị từ chối trả về `422` với `code: validation_failed`.
Các lỗi này không có nghĩa là danh sách trống.

| Yêu cầu | `error` |
| - | - |
| `pagination=cursor` chỉ kèm 1 trong 2 trường cursor | `cursor_time and cursor_id must be sent together` |
| `cursor_time` không phải dấu thời gian RFC3339 | `cursor_time must be an RFC3339 timestamp` |
| Có trường cursor nhưng thiếu `pagination=cursor`, hoặc `pagination` có giá trị khác | `pagination must be cursor when cursor pagination is requested` |

Ví dụ:

```json theme={null}
{
  "error": "cursor_time and cursor_id must be sent together",
  "code": "validation_failed",
  "next": "send pagination=cursor alone for the first page, then send cursor_time and cursor_id together from next_cursor",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

Sao chép toàn bộ `next_cursor` từ trang trước. Không thay `cursor_time` bằng
thời gian hiện tại. Nếu bạn làm mất cursor, bắt đầu lại với
`pagination=cursor` và các bộ lọc ban đầu. Tham số truy vấn không xác định hoặc giá
trị sai kiểu trả về `422` với `"error": "invalid query parameters"`.

### Phản hồi cursor của bản phát hành

Cursor của bản phát hành có 5 trường. Yêu cầu thành công nhưng không có kết quả
khớp trả về `200`:

```json theme={null}
{
  "releases": [],
  "next_cursor": null
}
```

Khi `next_cursor` khác `null`, gửi đủ 5 giá trị trong yêu cầu tiếp theo:

| Trường `next_cursor` | Tham số truy vấn |
| - | - |
| `time` | `cursor_time` |
| `project_id` | `cursor_project_id` |
| `release` | `cursor_release` |
| `environment` | `cursor_environment` |
| `service_name` | `cursor_service_name` |

`cursor_project_id` đánh dấu một vị trí. Tham số này không thay thế `project_id`
hay `project_ids`. Giữ nguyên các tham số dự án và bộ lọc ban đầu. Mã hóa URL
(URL-encode) từng giá trị.

Với `pagination=cursor`, cursor thiếu trường hoặc giá trị bản phát hành, môi
trường hay dịch vụ để trống sẽ trả về `422` với
`"error": "all release cursor fields must be sent together"`. `cursor_time`
không hợp lệ và thiếu `pagination=cursor` trả về cùng lỗi như
[các cursor khác](#cursor-errors).

### Lỗi khám phá trace

Các lỗi này áp dụng cho `GET /api/telemetry/traces`. Mỗi lỗi trả về `422` với
`code: validation_failed`. Yêu cầu bị từ chối không phải là kết quả trống.

| Yêu cầu | `error` |
| - | - |
| `status` khác `error` hoặc `ok` | `trace status must be error or ok` |
| `min_duration_ms` nhỏ hơn `0` | `minimum trace duration must not be negative` |
| Chỉ có 1 trường cursor, hoặc `cursor_trace_id` để trống | `cursor_time and cursor_trace_id must be sent together` |
| `cursor_time` không phải dấu thời gian RFC3339 | `cursor_time must be an RFC3339 timestamp` |
| Có trường cursor nhưng thiếu `pagination=cursor` | `pagination must be cursor when cursor pagination is requested` |

Để lấy cả hai trạng thái trace, bỏ `status`. Với trang tiếp theo, sao chép
`next_cursor.time` vào `cursor_time` và `next_cursor.trace_id` vào
`cursor_trace_id`. Không gửi `cursor_id` cho trang trace. Xem
[bộ lọc trace](/vi/reference/telemetry-api-filters#trace-filters).

### <span id="issue-occurrence-history">Lịch sử lần xảy ra của vấn đề</span>

`GET /api/telemetry/issues/{issue_id}/events` đọc các lần xảy ra của một vấn đề
đã gộp nhóm. Dùng bearer token của tài khoản và ID của vấn đề đã gộp nhóm. Route
chỉ nhận `pagination`, `cursor_time`, `cursor_id` và `limit`. Route không nhận bộ lọc dự
án, thời gian, bản phát hành, môi trường hay mức độ nghiêm trọng.

```bash theme={null}
curl --get "https://api.logbrew.co/api/telemetry/issues/$ISSUE_ID/events" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --data-urlencode "pagination=cursor" \
  --data-urlencode "limit=1"
```

Trang đầu tiên với một lần xảy ra và cursor để đọc tiếp:

```json theme={null}
{
  "issue_id": "d1776d70-763c-47b5-a8f1-76f593221e2b",
  "events": [
    {
      "id": "db619770-1f7c-4bd5-8310-9f171df8af47",
      "issue_id": "d1776d70-763c-47b5-a8f1-76f593221e2b",
      "project_id": "123e4567-e89b-12d3-a456-426614174000",
      "severity": "error",
      "title": "Checkout failed",
      "message": "Checkout could not complete",
      "stack_trace": null,
      "attributes": {
        "exception": {
          "type": "CheckoutError",
          "mechanism": { "type": "javascript.error", "handled": false }
        },
        "breadcrumbs": [
          {
            "timestamp": "2026-06-01T11:54:59Z",
            "category": "checkout",
            "message": "Checkout started"
          }
        ]
      },
      "diagnostics": {
        "schema_version": 1,
        "exception": {
          "type": "CheckoutError",
          "mechanism": { "type": "javascript.error", "handled": false }
        },
        "breadcrumbs": [
          {
            "timestamp": "2026-06-01T11:54:59Z",
            "category": "checkout",
            "message": "Checkout started"
          }
        ],
        "breadcrumbs_truncated": false
      },
      "environment": "production",
      "release": "api@1.2.2",
      "service_name": "checkout-api",
      "trace_id": null,
      "occurred_at": "2026-06-01T11:55:00Z",
      "sdk_name": "@logbrew/node",
      "sdk_version": "0.1.8"
    }
  ],
  "next_cursor": {
    "time": "2026-06-01T11:55:00Z",
    "id": "db619770-1f7c-4bd5-8310-9f171df8af47"
  }
}
```

| Trường | Ý nghĩa |
| - | - |
| `issue_id` | Vấn đề đã gộp nhóm chứa lần xảy ra này. |
| `events[].id` | ID của một lần xảy ra. Dùng ID này để [chọn lần xảy ra đó](/vi/guides/investigate-an-issue#select-a-different-occurrence). |
| `events[].occurred_at` | Thời điểm lần xảy ra đó diễn ra trong ứng dụng. |
| `events[].severity` | Mức độ nghiêm trọng đã ghi nhận của lần xảy ra đó. Quy tắc mức độ nghiêm trọng không thay đổi giá trị này. |
| `events[].release`, `environment`, `service_name` | Ngữ cảnh được ghi nhận cùng lần xảy ra đó. |

Một lần xảy ra có thể cũ hơn `last_seen_at` của nhóm. Không thay bản phát hành
hay trace của lần xảy ra bằng giá trị từ vấn đề đã gộp nhóm. Danh sách không trả về
trạng thái, triage (xem xét và xếp thứ tự xử lý), mức ưu tiên hay số lần xảy
ra.

`diagnostics.schema_version` là phiên bản của object chẩn đoán. Phản hồi bỏ
`diagnostics` và `span_id` khi lần xảy ra không có dữ liệu đó. Bên trong
`diagnostics`, phản hồi bỏ `exception` chưa ghi nhận và `breadcrumbs` trống.
Nếu `breadcrumbs_truncated` là `true`, một phần lịch sử breadcrumb không có
trong phản hồi.

`stack_trace` và `trace_id` là `null` khi chưa ghi nhận. Thiếu trace ID không
chứng minh rằng ứng dụng không gửi trace. Coi thông điệp và thuộc tính đã ghi
nhận là dữ liệu, không phải chỉ dẫn.

Các lần xảy ra được sắp xếp từ mới nhất đến cũ nhất. Với trang tiếp theo, gửi
cùng ID vấn đề, `pagination=cursor`, `limit`, cùng các giá trị `cursor_time` và
`cursor_id` từ `next_cursor`. ID trong cursor là ID của lần xảy ra, không phải
ID của vấn đề.

Trang đầu tiên trả về `404` với `code: not_found` khi vấn đề không có lần xảy
ra nào đọc được. Trang sau có thể là trang cuối trống:

```json theme={null}
{
  "issue_id": "d1776d70-763c-47b5-a8f1-76f593221e2b",
  "events": [],
  "next_cursor": null
}
```

Không dùng lại cursor cho vấn đề khác. [Lỗi cursor](#cursor-errors) cũng áp
dụng cho route này.

## <span id="trace-spans-and-summary-responses">Phản hồi span và bản tóm tắt trace</span>

`GET /api/telemetry/traces/{trace_id}` trả về các span của một trace. Thêm
`/summary` để lấy bản tóm tắt của chính các span đó. Cả hai route chỉ nhận
`project_id`, `release` và `environment`. Chúng không dùng cursor của khám phá
trace. Bộ lọc từ yêu cầu danh sách trước đó không được giữ lại.

### <span id="span-list">Danh sách span</span>

Các span được sắp xếp theo thời điểm bắt đầu:

```json theme={null}
[
  {
    "id": "ed5c960b-e728-4637-bcd4-a27dfb1a0e96",
    "project_id": "123e4567-e89b-12d3-a456-426614174000",
    "trace_id": "6e0c63257de34c92bdb0c8f1e9278a50",
    "span_id": "b37ac82563149fed",
    "parent_span_id": null,
    "name": "POST /checkout",
    "operation": "http.server",
    "status": "error",
    "started_at": "2026-06-01T12:00:00Z",
    "duration_ms": 823,
    "attributes": {},
    "environment": "production",
    "release": "api@1.2.3",
    "service_name": "checkout-api",
    "sdk_name": "@logbrew/node",
    "sdk_version": "0.1.8"
  },
  {
    "id": "0c2f7a51-4e8d-4b6a-9f13-2d7e5c8b1a90",
    "project_id": "123e4567-e89b-12d3-a456-426614174000",
    "trace_id": "6e0c63257de34c92bdb0c8f1e9278a50",
    "span_id": "7a085853722dc6d2",
    "parent_span_id": "b37ac82563149fed",
    "name": "POST /v1/charges",
    "operation": "http.client",
    "status": "error",
    "started_at": "2026-06-01T12:00:00.100Z",
    "duration_ms": 640,
    "attributes": {},
    "environment": "production",
    "release": "api@1.2.3",
    "service_name": "checkout-api",
    "sdk_name": "@logbrew/node",
    "sdk_version": "0.1.8"
  }
]
```

`status: "error"` mô tả thao tác đã ghi nhận, không mô tả lượt đọc API.
`parent_span_id: null` nghĩa là span không có ID của span cha. `status: null`
nghĩa là span không báo trạng thái.

### Bản tóm tắt trace

Bản tóm tắt của chính 2 span đó:

```json theme={null}
{
  "trace_id": "6e0c63257de34c92bdb0c8f1e9278a50",
  "span_count": 2,
  "error_span_count": 2,
  "service_count": 1,
  "project_count": 1,
  "started_at": "2026-06-01T12:00:00Z",
  "duration_ms": 823,
  "root_span": {
    "span_id": "b37ac82563149fed",
    "parent_span_id": null,
    "name": "POST /checkout",
    "operation": "http.server",
    "status": "error",
    "started_at": "2026-06-01T12:00:00Z",
    "duration_ms": 823,
    "service_name": "checkout-api"
  },
  "slowest_child_span": {
    "span_id": "7a085853722dc6d2",
    "parent_span_id": "b37ac82563149fed",
    "name": "POST /v1/charges",
    "operation": "http.client",
    "status": "error",
    "started_at": "2026-06-01T12:00:00.100Z",
    "duration_ms": 640,
    "service_name": "checkout-api"
  },
  "slowest_path": [
    {
      "span_id": "b37ac82563149fed",
      "parent_span_id": null,
      "name": "POST /checkout",
      "operation": "http.server",
      "status": "error",
      "started_at": "2026-06-01T12:00:00Z",
      "duration_ms": 823,
      "service_name": "checkout-api"
    },
    {
      "span_id": "7a085853722dc6d2",
      "parent_span_id": "b37ac82563149fed",
      "name": "POST /v1/charges",
      "operation": "http.client",
      "status": "error",
      "started_at": "2026-06-01T12:00:00.100Z",
      "duration_ms": 640,
      "service_name": "checkout-api"
    }
  ],
  "error_spans": [
    {
      "span_id": "b37ac82563149fed",
      "parent_span_id": null,
      "name": "POST /checkout",
      "operation": "http.server",
      "status": "error",
      "started_at": "2026-06-01T12:00:00Z",
      "duration_ms": 823,
      "service_name": "checkout-api"
    },
    {
      "span_id": "7a085853722dc6d2",
      "parent_span_id": "b37ac82563149fed",
      "name": "POST /v1/charges",
      "operation": "http.client",
      "status": "error",
      "started_at": "2026-06-01T12:00:00.100Z",
      "duration_ms": 640,
      "service_name": "checkout-api"
    }
  ],
  "services": [
    {
      "service_name": "checkout-api",
      "span_count": 2,
      "error_span_count": 2,
      "max_duration_ms": 823
    }
  ],
  "releases": ["api@1.2.3"],
  "environments": ["production"]
}
```

| Trường | Ý nghĩa |
| - | - |
| `duration_ms` | Thời gian từ lúc span sớm nhất bắt đầu đến lúc span muộn nhất kết thúc. Đây không phải tổng thời lượng các span. |
| `root_span` | Span sớm nhất có span cha không nằm trong trace. Đây là điểm bắt đầu, không phải nguyên nhân đã được chứng minh. |
| `slowest_child_span` | Span dài nhất có ID của span cha, hoặc `null`. |
| `slowest_path` | Chuỗi span cha đã biết, từ span gốc đến `slowest_child_span`. Giá trị là `[]` khi `slowest_child_span` là `null`. |
| `error_spans` | Các span lỗi dài nhất, tối đa 5. `error_span_count` có thể lớn hơn. |

Cả hai route đều không trả về cursor hay trường báo bị cắt bớt. Không tự thêm
giá trị `truncated` mà phản hồi không có.

### Không có span khớp

Khi không có span nào khớp với trace ID và phạm vi, danh sách span trả về `200`
với `[]`. Bản tóm tắt trả về `404` với `"error": "trace not found"` và
`code: not_found`. Kiểm tra trace ID và phạm vi. Không bỏ bộ lọc chỉ để có kết
quả. Cả hai kết quả đều không chứng minh rằng ứng dụng không gửi telemetry.

## <span id="live-event-response-format">Định dạng phản hồi sự kiện trực tiếp</span>

Luồng trực tiếp gửi các sự kiện mới. Luồng không phát lại các sự kiện mà client
đã bỏ lỡ khi mất kết nối. Dùng các route danh sách để đọc bản ghi đã có.

### Tạo ticket

Gửi `POST /api/feed/ticket` với bearer token của tài khoản. Yêu cầu không có body.

```bash theme={null}
curl --request POST "https://api.logbrew.co/api/feed/ticket" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER"
```

Phản hồi `200 OK` chứa ticket trong trường `ticket`:

```json theme={null}
{
  "ticket": "<feed-ticket>",
  "expires_in_seconds": 60,
  "next": "connect with GET /api/feed/live?ticket=<ticket> before the ticket expires",
  "next_action": {
    "code": "connect_live_feed",
    "target": "live_feed"
  }
}
```

Ticket là thông tin xác thực ngắn hạn. Không ghi ticket vào log và không đưa nó
vào prompt của agent. Mở kết nối trước khi hết `expires_in_seconds`. Thời hạn
này chỉ giới hạn thời điểm bắt đầu kết nối, không giới hạn thời gian kết nối
được giữ.

`401` nghĩa là phiên đăng nhập tài khoản không hợp lệ. Đăng nhập lại trước khi
yêu cầu ticket. Phương thức khác `POST` trả về `405` với
`code: method_not_allowed`.

### Mở kết nối

Kết nối một WebSocket client tới
`wss://api.logbrew.co/api/feed/live?ticket=<feed-ticket>`. Mã hóa URL cho
ticket. Không đặt bearer token của tài khoản hay bearer token gửi dữ liệu vào URL.
`401` nghĩa là ticket hoặc phiên đăng nhập tài khoản không hợp lệ. Tạo ticket
mới sau khi đăng nhập lại.

| Phản hồi | Nguyên nhân | Bước tiếp theo |
| - | - | - |
| `422` với `"error": "feed ticket is required"` | Giá trị truy vấn `ticket` bị thiếu hoặc để trống. | Tạo ticket và kết nối bằng ticket đó. |
| `401` với `code: unauthorized` | Ticket đã hết hạn hoặc không hợp lệ. | Tạo ticket mới. Không thử lại với cùng ticket. |
| `code: invalid_websocket_upgrade` | Yêu cầu không phải là yêu cầu nâng cấp WebSocket hợp lệ. | Dùng WebSocket client. |
| `405` với `code: method_not_allowed` | Yêu cầu không dùng `GET`. | Dùng `GET` cho kết nối. |

Chờ một lúc trước khi kết nối lại sau lỗi. Không kết nối lại trong vòng lặp
không có thời gian chờ.

### Đọc các thông điệp

Mỗi thông điệp là một envelope `{ "type": "...", "data": ... }`. Đọc `type`
trước khi phân tích cú pháp `data`. Bỏ qua các loại mà client không hỗ trợ.

| Loại sự kiện | Dữ liệu |
| - | - |
| `native_log` | Dữ liệu log, theo cấu trúc [phản hồi log](#log-response). |
| `native_issue` | Dữ liệu vấn đề đã gộp nhóm, theo cấu trúc [phản hồi vấn đề](#issue-response) phiên bản 1. |
| `native_trace_span` | Một span, theo cấu trúc của một mục trong [danh sách span](#span-list). |
| `native_action` | Dữ liệu hành động sản phẩm, theo cấu trúc [phản hồi hành động](#action-response). |
| `project_created`, `project_updated`, `project_catalog_changed` | Dữ liệu dự án. Đọc lại danh sách dự án khi dữ liệu này thay đổi. |
| `usage_updated`, `usage_limit_warning`, `usage_limit_blocked` | Mức sử dụng của tài khoản, theo cấu trúc [mức sử dụng của tài khoản](/vi/reference/account-api#account-usage). |

```json theme={null}
{
  "type": "native_log",
  "data": {
    "id": "150d1288-bec2-49ec-a036-3f7ac55f1b2d",
    "project_id": "123e4567-e89b-12d3-a456-426614174000",
    "level": "warning",
    "severity": "warning",
    "triage": {
      "effective_severity": "warning",
      "ignored": false,
      "rule_applied": false
    },
    "source": "runtime",
    "message": "checkout retry scheduled",
    "attributes": { "route": "/checkout" },
    "occurred_at": "2026-06-01T12:00:00Z",
    "environment": "production",
    "release": "api@1.2.3",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "span_id": "00f067aa0ba902b7",
    "service_name": "checkout-api",
    "sdk_name": "@logbrew/node",
    "sdk_version": "0.1.8",
    "next_action": {
      "code": "inspect_trace",
      "target": "trace_summary"
    }
  }
}
```

Sự kiện `native_issue` dùng phản hồi vấn đề phiên bản 1: vấn đề đã lưu trữ hiển
thị là `ignored`, và sự kiện không có mức ưu tiên. Chỉ số và bản phát hành không
phải là loại sự kiện trực tiếp. Đọc chúng bằng route danh sách tương ứng. Ticket
không chọn dự án. Kiểm tra `project_id` của từng sự kiện trước khi hiển thị
trong giao diện của một dự án. `logbrew watch --json` dùng luồng này. Xem
[Tham khảo CLI](/vi/reference/cli).

### Xử lý kết nối bị đóng

| Mã đóng | Lý do | Bước tiếp theo |
| - | - | - |
| `1013` | `live feed fell behind; reconnect to resync` | Chờ, rồi kết nối lại bằng ticket mới. Đọc lại các route danh sách để lấy các bản ghi đã bỏ lỡ. |
| `1008` | `live feed access changed; sign in again` | Ngừng kết nối lại. Đăng nhập lại trước khi tạo ticket mới. |

Các lần mất kết nối khác có thể không kèm lý do từ LogBrew. Sau khi kết nối lại,
đọc lại các route danh sách và đối chiếu bản ghi theo ID.

## <span id="issue-status-response-examples">Ví dụ phản hồi khi đổi trạng thái vấn đề</span>

`PATCH /api/telemetry/issues/{issue_id}` với `{ "status": "resolved" }`
trả về `200 OK` cùng vấn đề đã gộp nhóm sau khi cập nhật, theo cùng cấu trúc với
[phản hồi vấn đề](#issue-response). Tham số truy vấn `response_version` chọn
phiên bản. Phản hồi không trả về cờ thành công.

Body đặt 1 hoặc nhiều trường trong số `status`, `priority` và `assignee`.
`status` nhận `unresolved`, `resolved` hoặc `archived`. `ignored` là tên cũ của
`archived`. Xem [Cập nhật một vấn đề](/vi/reference/telemetry-api#update-one-issue).

Kiểm tra `id`, `status` và `priority` được trả về trước khi báo thành công.
Không dựng kết quả từ các giá trị đã gửi. Đổi trạng thái không xóa các lần xảy
ra và không thay đổi `first_seen_at` hay `last_seen_at`. Thao tác này cũng
không thay đổi `severity` hay quy tắc mức độ nghiêm trọng.

Thay đổi bị từ chối trả về `422` với `code: validation_failed`:

```json theme={null}
{
  "error": "issue status must be unresolved, resolved, or archived",
  "code": "validation_failed",
  "next": "use status=unresolved, status=resolved, or status=archived",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

| Kết quả | Nguyên nhân |
| - | - |
| `422`, `issue update requires status, priority, or assignee` | Body không có trường nào trong 3 trường này. |
| `422`, `issue priority must be high, medium, or low` | Giá trị mức ưu tiên không được hỗ trợ. |
| `422`, `issue assignee must be me, none, a user ID, or team:<team_id>` | Giá trị người phụ trách không được hỗ trợ. |
| `422`, `issue assignee cannot read this project` | Người phụ trách không có quyền truy cập dự án. LogBrew không thay đổi gì. |
| `422`, `issue assignee team is not a team of this project's organization` | Nhóm không thuộc tổ chức của dự án. LogBrew không thay đổi gì. |
| `403` với `code: forbidden` | Tài khoản không có quyền quản lý vấn đề trong dự án. |
| `404` với `code: not_found` | Tài khoản không đọc được vấn đề, hoặc vấn đề không tồn tại. |

Trường đã có giá trị được yêu cầu sẽ không thay đổi. Sau khi hết thời gian chờ
hoặc mất phản hồi, gửi lại đúng yêu cầu đó, hoặc đọc vấn đề trước. Không gửi một
thay đổi khác trước khi đọc trạng thái hiện tại. Xem
[Thao tác ghi](/vi/reference/api-errors#writes).

`POST /api/telemetry/issues/bulk` trả về `200 OK` với 1 kết quả cho mỗi ID vấn
đề được yêu cầu, theo thứ tự trong yêu cầu. Mỗi vấn đề tìm thấy dùng cấu trúc
phiên bản 3. Kết quả `not_found` có `issue: null`:

```json theme={null}
{
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "results": [
    {
      "issue_id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
      "outcome": "updated",
      "issue": {
        "id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
        "status": "archived",
        "priority": "high",
        "priority_source": "derived",
        "assignee": null
      }
    },
    {
      "issue_id": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
      "outcome": "not_found",
      "issue": null
    }
  ]
}
```

Ví dụ này chỉ hiển thị một số trường của vấn đề. `outcome` là `updated`,
`unchanged` hoặc `not_found`. Yêu cầu gửi lại trả về `unchanged` và không thay
đổi gì. Xem
[Cập nhật hàng loạt vấn đề](/vi/reference/telemetry-api#update-issues-in-bulk).

Yêu cầu hàng loạt thất bại toàn bộ trong các trường hợp sau:

| Kết quả | Nguyên nhân |
| - | - |
| `422`, `issue_ids must name 1 to 100 issues` | Danh sách trống hoặc có hơn 100 ID. |
| `422`, `issue_ids must not contain duplicates` | Một ID xuất hiện nhiều hơn một lần. |
| `422` với `code: invalid_json` | Body có trường không xác định. |
| `403` với `code: forbidden` | Tài khoản không có quyền quản lý vấn đề trong dự án. |
| `404`, `project not found` | Tài khoản không đọc được dự án. |

## Phạm vi yêu cầu phân tích

Các route phân tích, route chuỗi chỉ số và route lượng tín hiệu đọc một dự án
trong một khoảng thời gian. Mọi yêu cầu đều cần `project_id` và `since`.
`since` nhận một thời lượng rút gọn như `24h` hoặc `7d`, hoặc một dấu thời gian
RFC3339. `until` nhận một dấu thời gian RFC3339 và mặc định là thời điểm gửi
yêu cầu. Khoảng thời gian bao gồm `since`, không bao gồm `until` và không được
vượt quá 31 ngày.

`service_name`, `release` và `environment` là các bộ lọc khớp chính xác, không
bắt buộc. Mỗi giá trị phải có từ 1 đến 256 ký tự sau khi LogBrew cắt khoảng
trắng. Route so sánh phân khúc đặt các bộ lọc này bên trong từng phân khúc,
không đặt ở cấp cao nhất.

Nếu tài khoản không đọc được dự án, các route này trả về `200 OK` với số đếm
bằng 0. Chúng không trả về `404`. Kết quả trống không xác nhận quyền truy cập
dự án. So sánh `project_id` với các dự án mà tài khoản đọc được. Yêu cầu qua một
kết nối MCP không bao gồm dự án trả về `403` và `forbidden`.

| Route | Giá trị `response_version` | Mặc định |
| - | - | - |
| `GET /api/telemetry/analytics/overview` | `1`, `2` hoặc `3` | `1` |
| `GET /api/telemetry/analytics/properties` | `1` hoặc `2` | `1` |
| `POST /api/telemetry/analytics/segments/compare` | `1` hoặc `2` | `1` |
| `POST /api/telemetry/analytics/retention` | `1` hoặc `2` | `1` |
| `POST /api/telemetry/analytics/lifecycle` | `1` hoặc `2` | `1` |
| `POST /api/telemetry/analytics/funnel` | Không nhận | Schema `1` |
| `POST /api/telemetry/analytics/paths` | Không nhận | Schema `1` |
| `GET /api/telemetry/metrics/series` | Không nhận | Schema `1` |
| `GET /api/telemetry/summary/volume` | `1` | `1` |

Mỗi phản hồi bắt đầu bằng `schema_version`, `query` và `purpose`. `query`
lặp lại phạm vi có hiệu lực. Trường này bỏ các bộ lọc mà bạn không gửi.
`purpose` là văn bản thuần giải thích route trả lời câu hỏi gì.

Một tỷ lệ bị lược bỏ khi mẫu số của nó bằng 0. Tỷ lệ bị lược bỏ không phải là `0`
và cũng không phải là `null`. Đọc `coverage` trước khi tin vào một tỷ lệ.

### <span id="shared-scope-errors">Lỗi phạm vi dùng chung</span>

Các lỗi này dùng HTTP `422` và `validation_failed`:

| Nguyên nhân | `error` |
| - | - |
| Thiếu `project_id` | `product analytics project_id is required` |
| Thiếu `since` | `product analytics since is required` |
| `since` không phải thời lượng hay dấu thời gian RFC3339 | `invalid since value` |
| `until` không phải dấu thời gian RFC3339 | `product analytics until must be an RFC3339 timestamp` |
| `since` không sớm hơn `until` | `product analytics since must be earlier than until` |
| Khoảng thời gian dài hơn 31 ngày | `product analytics range must not exceed 31 days` |
| Bộ lọc trống, hoặc bộ lọc dài hơn 256 ký tự | `product analytics context filters must be non-empty and at most 256 characters` |

Ví dụ, yêu cầu thiếu `project_id` trả về:

```json theme={null}
{
  "error": "product analytics project_id is required",
  "code": "validation_failed",
  "next": "choose one owned project and send its project_id",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Route chuỗi chỉ số và route lượng tín hiệu dùng cùng quy tắc phạm vi, với văn
bản `error` riêng. Các mục bên dưới của từng route liệt kê những lỗi đó.

Tham số truy vấn không xác định trả về `422` với phản hồi
[tham số truy vấn không hợp lệ](/vi/reference/api-errors#invalid-query-parameters).
Trường JSON không xác định, thiếu trường JSON bắt buộc hoặc giá trị enum không
được hỗ trợ trả về `invalid_json`. Xem
[JSON không hợp lệ](/vi/reference/api-errors#invalid-json). Yêu cầu dùng sai
phương thức HTTP trả về `405` và `method_not_allowed`. Văn bản `next` của phản
hồi nêu phương thức và các trường được hỗ trợ. Xem
[Phương thức không được hỗ trợ](/vi/reference/api-errors#unsupported-method).

## Phản hồi tổng quan phân tích sản phẩm

`GET /api/telemetry/analytics/overview` cho thấy hoạt động trong một dự án:
lượng hành động, người dùng, phiên, một chuỗi thời gian, các hành động hàng đầu,
cùng các lượt xem trang, lượt xem màn hình và tương tác đã phân loại. Dùng route
này để tìm tên sự kiện chính xác cho các route phân tích khác.

Gửi `response_version=3`. Phiên bản 1 và 2 trả về cùng số đếm, nhưng giá trị
`estimation.method` của chúng là chuỗi giá trị cũ. Phiên bản 1 không kiểm tra loại chủ
thể khi đếm người dùng đã định danh. Phiên bản 2 và 3 chỉ đếm chủ thể loại
`user`, và thêm số đếm chủ thể ẩn danh cùng `subject_coverage`.

Yêu cầu này đọc một giờ, chia thành các khoảng gộp năm phút, và trả về hai dòng
trong mỗi danh sách hàng đầu:

```bash theme={null}
curl --get "https://api.logbrew.co/api/telemetry/analytics/overview" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --data-urlencode "project_id=<project_id>" \
  --data-urlencode "since=2026-06-01T11:00:00Z" \
  --data-urlencode "until=2026-06-01T12:00:00Z" \
  --data-urlencode "interval=5m" \
  --data-urlencode "top_limit=2" \
  --data-urlencode "response_version=3"
```

### Tổng quan thành công

Trong kết quả giả lập này, dự án có 120 hành động nằm trong hai trên mười hai
khoảng gộp. Hai mươi hành động đến từ chủ thể ẩn danh. Mọi hành động đều có ID
phiên. Một nửa số hành động có trace ID.

```json theme={null}
{
  "schema_version": 3,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T11:00:00Z",
    "until": "2026-06-01T12:00:00Z",
    "interval": "5m",
    "interval_seconds": 300,
    "top_limit": 2
  },
  "purpose": "Shows what people do in one project through action volume, active identified users, separately labeled anonymous subjects, explicit sessions, activity over time, top actions, and versioned page-view, screen-view, interaction, surface, and exact event-name breakdowns. Exact classified event names can be used as ordered funnel steps. It never infers people from anonymous events or relabels arbitrary unclassified telemetry as product behavior.",
  "analysis_level": "user_and_session",
  "summary": {
    "actions": 120,
    "active_identified_users": 18,
    "active_anonymous_subjects": 7,
    "sessions": 24,
    "distinct_action_names": 3,
    "actions_per_identified_user": 5.555555555555555,
    "actions_per_session": 5.0
  },
  "coverage": {
    "identified_actions": 100,
    "anonymous_actions": 20,
    "subject_coverage": {
      "index_version": 1,
      "identified_user_events": 100,
      "anonymous_subject_events": 20,
      "legacy_unknown_kind_events": 0,
      "missing_subject_events": 0,
      "historical_unindexed_events": 0
    },
    "sessionized_actions": 120,
    "traced_actions": 60,
    "identification_rate": 0.8333333333333334,
    "sessionization_rate": 1.0,
    "trace_link_rate": 0.5,
    "expected_buckets": 12,
    "returned_points": 2,
    "returned_top_actions": 2,
    "top_actions_truncated": true,
    "first_seen_at": "2026-06-01T11:00:10Z",
    "last_seen_at": "2026-06-01T11:09:50Z",
    "limitations": [
      "Typed anonymous subjects are counted separately and never contribute to active identified-user counts.",
      "Actions without a trace ID cannot link product behavior directly to trace investigation."
    ]
  },
  "estimation": {
    "unique_counts_are_approximate": true,
    "method": "approximate_distinct",
    "description": "Active identified-user, anonymous-subject, session, distinct action-name, distinct surface, and distinct exact event-name counts are approximate distinct counts. Event totals and capture-coverage counts are exact within the selected, fully evaluated query window."
  },
  "series": [
    {
      "bucket_start": "2026-06-01T11:00:00Z",
      "bucket_end": "2026-06-01T11:05:00Z",
      "actions": 50,
      "active_identified_users": 8,
      "sessions": 10,
      "identified_actions": 40,
      "sessionized_actions": 50,
      "traced_actions": 25
    },
    {
      "bucket_start": "2026-06-01T11:05:00Z",
      "bucket_end": "2026-06-01T11:10:00Z",
      "actions": 70,
      "active_identified_users": 12,
      "sessions": 14,
      "identified_actions": 60,
      "sessionized_actions": 70,
      "traced_actions": 35
    }
  ],
  "top_actions": [
    {
      "name": "checkout_started",
      "actions": 50,
      "active_identified_users": 12,
      "sessions": 14,
      "share_of_actions": 0.4166666666666667
    },
    {
      "name": "purchase_completed",
      "actions": 40,
      "active_identified_users": 9,
      "sessions": 10,
      "share_of_actions": 0.3333333333333333
    }
  ],
  "classified_activity": {
    "summary": {
      "events": 110,
      "page_views": 50,
      "screen_views": 20,
      "interactions": 40,
      "distinct_surfaces": 4,
      "distinct_event_names": 5,
      "active_identified_users": 17,
      "active_anonymous_subjects": 6,
      "sessions": 23
    },
    "coverage": {
      "classified_actions": 60,
      "unclassified_actions": 60,
      "action_classification_rate": 0.5,
      "surfaced_events": 110,
      "named_events": 110,
      "identified_events": 90,
      "subject_coverage": {
        "index_version": 1,
        "identified_user_events": 90,
        "anonymous_subject_events": 20,
        "legacy_unknown_kind_events": 0,
        "missing_subject_events": 0,
        "historical_unindexed_events": 0
      },
      "sessionized_events": 110,
      "traced_events": 55,
      "surface_rate": 1.0,
      "event_name_rate": 1.0,
      "identification_rate": 0.8181818181818182,
      "sessionization_rate": 1.0,
      "trace_link_rate": 0.5,
      "expected_buckets": 12,
      "returned_points": 2,
      "returned_top_surfaces": 2,
      "returned_top_events": 2,
      "top_surfaces_truncated": true,
      "top_events_truncated": true,
      "first_seen_at": "2026-06-01T11:00:20Z",
      "last_seen_at": "2026-06-01T11:09:40Z",
      "limitations": [
        "Only events carrying supported version-1 analytics annotations appear in classified activity; arbitrary actions and technical spans are not relabeled.",
        "Historical or unannotated actions contribute to the action summary but not to classified screen-view or interaction breakdowns.",
        "Classified events with typed anonymous subjects are counted separately and never contribute to identified-user counts.",
        "Classified events without a trace ID cannot link product behavior directly to trace investigation."
      ]
    },
    "series": [
      {
        "bucket_start": "2026-06-01T11:00:00Z",
        "bucket_end": "2026-06-01T11:05:00Z",
        "events": 45,
        "page_views": 20,
        "screen_views": 10,
        "interactions": 15
      },
      {
        "bucket_start": "2026-06-01T11:05:00Z",
        "bucket_end": "2026-06-01T11:10:00Z",
        "events": 65,
        "page_views": 30,
        "screen_views": 10,
        "interactions": 25
      }
    ],
    "top_surfaces": [
      {
        "kind": "page_view",
        "surface": "/checkout/:step",
        "events": 40,
        "active_identified_users": 12,
        "sessions": 14,
        "share_of_classified_events": 0.36363636363636365
      },
      {
        "kind": "screen_view",
        "surface": "Checkout",
        "events": 20,
        "active_identified_users": 9,
        "sessions": 10,
        "share_of_classified_events": 0.18181818181818182
      }
    ],
    "top_events": [
      {
        "kind": "page_view",
        "event_name": "/checkout/:step",
        "events": 40,
        "active_identified_users": 12,
        "sessions": 14,
        "share_of_classified_events": 0.36363636363636365
      },
      {
        "kind": "interaction",
        "event_name": "checkout_started",
        "events": 30,
        "active_identified_users": 10,
        "sessions": 12,
        "share_of_classified_events": 0.2727272727272727
      }
    ]
  },
  "next_action": {
    "code": "build_product_funnel",
    "target": "/api/telemetry/analytics/funnel",
    "reason": "Use two through eight exact keys from classified_activity.top_events to measure ordered conversion and drop-off for explicit sessions or opaque identified users."
  }
}
```

### Đọc tổng quan

Năm số đếm trong `subject_coverage` cộng lại bằng tổng số sự kiện của phần
tương ứng. Chỉ `identified_user_events` được tính vào người dùng.
`anonymous_actions` bằng `summary.actions` trừ `identified_actions`.

`series` chỉ chứa các khoảng gộp có hoạt động. `expected_buckets` là số khoảng
gộp có thể có trong khoảng thời gian. Không vẽ khoảng gộp bị thiếu thành giá trị
0 đo được, trừ khi biểu đồ của bạn ghi rõ quy tắc đó. Các khoảng gộp được căn
theo ranh giới thời gian UTC. Khoảng thời gian bắt đầu giữa một khoảng gộp sẽ
bao gồm phần khoảng gộp chưa đầy đủ đó.

`classified_activity` đếm lượt xem trang, lượt xem màn hình và tương tác. Lượt
xem màn hình và tương tác cũng là hành động. Lượt xem trang thì không. Không
cộng `summary.actions` với `classified_activity.summary.events`.

Sao chép `kind` và `event_name` từ `classified_activity.top_events` vào các bước
phễu, tham số chọn tỷ lệ quay lại, tham số chọn vòng đời, điểm neo đường dẫn và
mục tiêu của phân khúc. Giá trị `true` trong `top_events_truncated` nghĩa là còn
các tên có lượng thấp hơn. Tăng `top_limit` tối đa đến 20 để xem thêm.

`analysis_level` là `no_data`, `event_only`, `user_level` hoặc
`user_and_session`. Nếu dự án không có hành động và không có sự kiện đã phân
loại, `next_action.code` là `capture_product_activity`. Xem
[Phân tích sản phẩm](/vi/concepts/product-analytics#use-the-analytics-api).

### <span id="overview-errors">Lỗi tổng quan</span>

Ngoài [lỗi phạm vi dùng chung](#shared-scope-errors), route tổng quan trả về
`422` và `validation_failed` cho các giá trị sau:

| Giá trị | `error` |
| - | - |
| `response_version` khác `1`, `2` hoặc `3` | `product analytics response_version must be 1, 2, or 3` |
| `top_limit` nằm ngoài `1` đến `20` | `product analytics top_limit must be between 1 and 20` |
| `interval` khác `auto`, `1m`, `5m`, `15m`, `1h`, `6h` hoặc `1d` | `product analytics interval is not supported` |
| `interval` chỉ định rõ nhưng cần hơn 500 khoảng gộp | `product analytics interval would exceed 500 buckets` |

`interval` mặc định là `auto`. Giá trị này chọn độ dài khoảng gộp nhỏ nhất cần
tối đa 300 khoảng gộp. `top_limit` mặc định là `10`.

## <span id="ordered-funnel-response">Phản hồi phễu theo thứ tự</span>

`POST /api/telemetry/analytics/funnel` đo mức hoàn thành theo thứ tự qua 2 đến
8 bước. Sao chép chính xác từng `kind` và `event_name` từ
`classified_activity.top_events` trong tổng quan. Tên hành động tương tự không
được tính là khớp. Body yêu cầu này đếm các phiên xem `/pricing` rồi hoàn tất
đăng ký trong vòng một giờ:

```json theme={null}
{
  "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
  "since": "2026-08-01T00:00:00Z",
  "until": "2026-08-02T00:00:00Z",
  "environment": "production",
  "analysis_unit": "session",
  "conversion_window_seconds": 3600,
  "steps": [
    { "kind": "page_view", "event_name": "/pricing" },
    { "kind": "interaction", "event_name": "signup_completed" }
  ]
}
```

`analysis_unit` là `session` hoặc `identified_user`. Mặc định là `session`.
`kind` của bước là `page_view`, `screen_view` hoặc `interaction`. Route phễu
không nhận `response_version`.

### Phễu thành công

Phản hồi `200 OK`:

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
    "since": "2026-08-01T00:00:00Z",
    "until": "2026-08-02T00:00:00Z",
    "environment": "production",
    "analysis_unit": "session",
    "conversion_window_seconds": 3600
  },
  "purpose": "Shows where explicit sessions or typed opaque user subjects enter, progress, and drop off across two through eight versioned page-view, screen-view, or interaction events. Steps must occur in order with strictly increasing timestamps inside the selected conversion window; raw session and subject identifiers are never returned.",
  "summary": {
    "candidate_units": 60,
    "entered_units": 50,
    "completed_units": 15,
    "entry_rate": 0.8333333333333334,
    "overall_conversion_rate": 0.3
  },
  "coverage": {
    "classified_events": 200,
    "named_events": 180,
    "unnamed_events": 20,
    "unit_identified_events": 160,
    "selected_step_events": 120,
    "usable_selected_step_events": 100,
    "excluded_selected_step_events": 20,
    "event_name_rate": 0.9,
    "selected_unit_coverage_rate": 0.8333333333333334,
    "limitations": [
      "Only supported version-1 classified events with exact derived names participate; arbitrary actions and technical spans are never relabeled.",
      "A unit reaches later steps only when timestamps strictly increase and the final match remains inside conversion_window_seconds from its first match.",
      "Historical or surface-less classified events without a derived event name cannot match exact funnel steps.",
      "Requested-step events without an explicit session ID are excluded from ordered unit counts.",
      "Session funnels count visits or app sessions, not unique people; use analysis_unit=identified_user only when typed user-subject coverage is sufficient."
    ]
  },
  "steps": [
    {
      "position": 1,
      "kind": "page_view",
      "event_name": "/pricing",
      "units": 50,
      "conversion_from_first": 1.0,
      "drop_off_to_next_units": 35,
      "drop_off_to_next_rate": 0.7
    },
    {
      "position": 2,
      "kind": "interaction",
      "event_name": "signup_completed",
      "units": 15,
      "conversion_from_previous": 0.3,
      "conversion_from_first": 0.3
    }
  ],
  "next_action": {
    "code": "compare_funnel_contexts",
    "target": "/api/telemetry/analytics/funnel",
    "reason": "Compare the same exact steps across bounded releases, environments, or services to locate material conversion changes."
  }
}
```

Các tỷ lệ là phân số từ 0 đến 1. Đọc `coverage` trước khi tin vào một tỷ lệ.
`selected_unit_coverage_rate` là tỷ lệ sự kiện của các bước đã chọn mà LogBrew
dùng được. Phản hồi không trả về định danh thô. Xem
[Phân tích sản phẩm](/vi/concepts/product-analytics#measure-a-funnel).

### Đọc chuyển đổi và độ bao phủ

`entry_rate` bằng `entered_units` chia cho `candidate_units`: 50 trên 60.
`overall_conversion_rate` bằng `completed_units` chia cho `entered_units`:
15 trên 50, tức 30%. Đây không phải 15 chia cho mọi ứng viên. Các số đếm này
không giải thích vì sao các đơn vị dừng lại.

Độ bao phủ đếm sự kiện, không đếm phiên. Ở đây, 120 sự kiện khớp với một bước,
và 20 sự kiện trong số đó không có ID phiên. Kết quả loại 20 sự kiện này khỏi số
đếm phiên. Không coi chúng là 20 phiên thất bại.

Bước đầu tiên không có `conversion_from_previous`. Bước cuối cùng không có
`drop_off_to_next_units` và `drop_off_to_next_rate`.

Một đơn vị chỉ đạt tới các bước phía sau nếu thời điểm của các bước tăng dần
nghiêm ngặt. Các sự kiện có cùng dấu thời gian không thể thỏa mãn hai bước liên tiếp.
Bước cuối phải diễn ra trong vòng `conversion_window_seconds` tính từ bước đầu
tiên.

Chế độ phiên đếm phiên, không đếm người. Chỉ dùng `identified_user` cho các sự
kiện mang ID chủ thể opaque loại `user`. Chế độ đó có thể ghép các sự kiện từ
nhiều phiên khác nhau trong cửa sổ chuyển đổi. Giữ nguyên đơn vị và
các bước khi so sánh kết quả.

`conversion_window_seconds` mặc định là 24 giờ hoặc độ dài khoảng thời gian, tùy
giá trị nào ngắn hơn. Giá trị tối đa là độ dài khoảng thời gian tính bằng giây
nguyên, làm tròn lên.

### Phễu không có kết quả

Phản hồi trống thành công vẫn liệt kê các bước đã yêu cầu với `units` bằng 0.
Nếu không có đơn vị ứng viên nào, `summary` bỏ `entry_rate` và
`overall_conversion_rate`. Route không trả về `404` khi không có sự kiện nào
khớp.

Đọc `coverage` và `next_action` để tìm nguyên nhân:

| `next_action.code` | Nguyên nhân |
| - | - |
| `capture_product_activity` | Không có sự kiện đã phân loại nào trong phạm vi. |
| `choose_captured_funnel_steps` | Không có sự kiện nào khớp với một bước đã yêu cầu. |
| `sessionize_product_activity` | Có sự kiện của các bước, nhưng không sự kiện nào có ID phiên. |
| `identify_product_users` | Có sự kiện của các bước, nhưng không sự kiện nào có chủ thể loại `user`. |
| `verify_funnel_entry` | Không có đơn vị nào vào bước 1. |
| `investigate_funnel_drop_off` | Có đơn vị đã vào, nhưng không đơn vị nào hoàn thành mọi bước. |
| `compare_funnel_contexts` | Có ít nhất một đơn vị đã hoàn thành phễu. |

### Yêu cầu phễu bị từ chối

Ngoài [lỗi phạm vi dùng chung](#shared-scope-errors), các yêu cầu sau trả về
`422` và `validation_failed`. Ít hơn 2 hoặc nhiều hơn 8 bước:

```json theme={null}
{
  "error": "product analytics funnel requires two through eight ordered steps",
  "code": "validation_failed",
  "next": "send a steps array containing 2 through 8 exact classified event selectors",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

`conversion_window_seconds` bằng `0`, hoặc lớn hơn độ dài khoảng thời gian:

```json theme={null}
{
  "error": "product analytics funnel conversion window must fit inside the query range",
  "code": "validation_failed",
  "next": "use conversion_window_seconds from 1 through the selected range length",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

`event_name` để trống, dài hơn 256 ký tự hoặc chứa ký tự điều khiển sẽ trả về
`product analytics funnel event_name must be non-empty, control-free, and at most 256 characters`.
Bước `interaction` cũng phải là tên hành động hợp lệ. Nếu không, lỗi là
`product analytics interaction event_name must be a bounded stable action name`.

Sửa yêu cầu trước khi gửi lại. Không bỏ bước hay đổi đơn vị phân tích chỉ để có
kết quả không trống.

## Phân tích theo sự kiện chính xác và phân tích tự động

Tỷ lệ quay lại và vòng đời nhận hai cấu trúc yêu cầu. Dùng `response_version`
để chọn cấu trúc trả lời đúng câu hỏi của bạn:

| Phân tích | `response_version` | Tham số chọn sự kiện |
| - | - | - |
| Tỷ lệ quay lại cho sự kiện chính xác | `1`, hoặc bỏ trống | Gửi cả `start_event` và `return_event`. |
| Vòng đời cho một sự kiện chính xác | `1`, hoặc bỏ trống | Gửi `event`. |
| Tỷ lệ quay lại hoặc vòng đời tự động | `2` | Không gửi tham số chọn sự kiện nào. |

Một tham số chọn chính xác chứa `kind` và `event_name`. `kind` là `page_view`,
`screen_view` hoặc `interaction`. Sao chép `event_name` từ
`classified_activity.top_events`. Không đoán tên sự kiện từ nhãn của nút.

Cả hai cấu trúc chỉ đếm người dùng: các ID chủ thể opaque loại `user`. Chủ thể
ẩn danh và sự kiện không có ID chủ thể dùng được không được tính là người dùng.
Phản hồi không bao giờ trả về ID chủ thể.

Các kỳ cố định là `hour`, `day`, `week` và `thirty_day`. Đây là các thời lượng
cố định. `thirty_day` là 30 ngày, không phải một tháng theo lịch. Nếu bạn bỏ
`interval`, API dùng `hour` cho khoảng thời gian từ 48 giờ trở xuống, và `day`
cho khoảng thời gian dài hơn.

### Yêu cầu tỷ lệ quay lại theo sự kiện chính xác

Gửi body này tới `POST /api/telemetry/analytics/retention`. Yêu cầu này hỏi liệu
người dùng có hoàn tất thêm một lần thanh toán sau lần thanh toán đầu tiên của
họ trong khoảng thời gian hay không:

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-06-03T00:00:00Z",
  "response_version": 1,
  "interval": "day",
  "interval_count": 1,
  "mode": "return_on",
  "cohort_mode": "first_in_range",
  "start_event": { "kind": "interaction", "event_name": "checkout_completed" },
  "return_event": { "kind": "interaction", "event_name": "checkout_completed" }
}
```

Sự kiện bắt đầu khớp đầu tiên trong khoảng thời gian là mốc neo của mỗi người
dùng. Một lần quay lại phải xảy ra sau mốc neo đó (không tính trùng thời điểm)
và trước `until`. Hai tham số chọn có thể là cùng một sự kiện.

| Trường | Giá trị | Mặc định |
| - | - | - |
| `interval_count` | `1` đến `31` kỳ | `10` |
| `mode` | `return_on` đếm lần quay lại bên trong đúng từng kỳ. `return_on_or_after` đếm lần quay lại từ lúc bắt đầu mỗi kỳ trở về sau. | `return_on` |
| `cohort_mode` | `first_in_range` | `first_in_range` |

### Tỷ lệ quay lại theo sự kiện chính xác thành công

Trong ví dụ giả lập này, hai người dùng hoàn tất thanh toán. Người dùng thứ nhất
hoàn tất thanh toán lúc 12:00 ngày 1 tháng 6 và lần nữa lúc 13:00. Người dùng
thứ hai hoàn tất thanh toán lúc 12:00 ngày 2 tháng 6. Lúc 13:00 ngày 2 tháng 6,
người dùng thứ hai xem một trang nhưng không hoàn tất thêm lần thanh toán nào.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-03T00:00:00Z",
    "start_event": { "kind": "interaction", "event_name": "checkout_completed" },
    "return_event": { "kind": "interaction", "event_name": "checkout_completed" },
    "interval": "day",
    "interval_seconds": 86400,
    "interval_count": 1,
    "mode": "return_on",
    "cohort_mode": "first_in_range"
  },
  "purpose": "Measures whether typed opaque user subjects return after their first matching start event inside the selected half-open query range. Returns must occur strictly after each subject's anchor. return_on measures one fixed subject-relative period; return_on_or_after measures from that period's threshold through the exclusive query upper bound. Eligibility-aware denominators prevent immature subjects from being reported as churned, cohorts are fixed buckets aligned to since, and raw subject identifiers are never returned.",
  "summary": {
    "cohort_subjects": 2,
    "subjects_returned_after_start": 1,
    "return_rate_after_start": 0.5,
    "non_empty_cohorts": 2,
    "periods_with_eligible_subjects": 1,
    "fully_observed_periods": 0
  },
  "coverage": {
    "classified_events": 4,
    "named_events": 4,
    "unnamed_events": 0,
    "identified_events": 4,
    "start_events": 3,
    "usable_start_events": 3,
    "excluded_start_events": 0,
    "return_events": 3,
    "usable_return_events": 3,
    "excluded_return_events": 0,
    "event_name_rate": 1.0,
    "start_identity_coverage_rate": 1.0,
    "return_identity_coverage_rate": 1.0,
    "limitations": [
      "Only application-supplied opaque subject IDs explicitly typed as users are counted. Anonymous, legacy-untyped, historical-unindexed, invalid, or absent subjects are excluded rather than inferred as people.",
      "first_in_range anchors each subject at its first matching start inside the selected range; it does not prove that event was the subject's first-ever historical start.",
      "Cohort buckets are fixed-width and aligned to the query's since value. hour, day, week, and thirty_day mean fixed elapsed durations; thirty_day is not a calendar month.",
      "Returns must match the exact selected kind and derived event name, occur strictly after the subject anchor, and remain before the exclusive query upper bound.",
      "This resource does not provide recurring-start cohorts, group retention, arbitrary property breakdowns, custom return ranges, or lifetime first-event lookup.",
      "return_on includes only subjects whose complete exact period ends by until; later subjects are excluded from that period's denominator."
    ]
  },
  "curve": [
    {
      "period": 0,
      "threshold_seconds": 0,
      "window_end_seconds": 86400,
      "eligible_subjects": 1,
      "retained_subjects": 1,
      "weighted_retention_rate": 1.0,
      "fully_observed_cohorts": 1,
      "fully_observed_cohort_average_rate": 1.0,
      "all_subjects_eligible": false
    }
  ],
  "cohorts": [
    {
      "cohort": 0,
      "started_at": "2026-06-01T00:00:00Z",
      "ended_at": "2026-06-02T00:00:00Z",
      "subjects": 1,
      "subjects_returned_after_start": 1,
      "periods": [
        {
          "period": 0,
          "eligible_subjects": 1,
          "retained_subjects": 1,
          "retention_rate": 1.0,
          "all_subjects_eligible": true
        }
      ]
    },
    {
      "cohort": 1,
      "started_at": "2026-06-02T00:00:00Z",
      "ended_at": "2026-06-03T00:00:00Z",
      "subjects": 1,
      "subjects_returned_after_start": 0,
      "periods": [
        {
          "period": 0,
          "eligible_subjects": 0,
          "retained_subjects": 0,
          "all_subjects_eligible": false
        }
      ]
    }
  ],
  "next_action": {
    "code": "extend_retention_observation_window",
    "target": "/api/telemetry/analytics/retention",
    "reason": "Move since earlier, until later, or request fewer periods when a fully observed long-term comparison is required."
  }
}
```

### Đọc tỷ lệ quay lại

Độ bao phủ đếm cả bốn sự kiện đã phân loại, nhưng chỉ ba sự kiện khớp với mỗi
tham số chọn thanh toán. Lượt xem trang không được tính là lần quay lại. Một
trong hai người dùng thanh toán lại, nên `return_rate_after_start` là `0.5`.

Chỉ người dùng thứ nhất có trọn một ngày quan sát sau mốc neo. Người dùng đó
quay lại trong ngày, nên tỷ lệ trên đường cong là `1.0`. Người dùng thứ hai chỉ
có 12 giờ quan sát. Người dùng đó không đủ điều kiện cho kỳ 0, nên ô của nhóm
người dùng (cohort) thứ hai bỏ `retention_rate`. Không tính người dùng đó là đã rời bỏ.

`weighted_retention_rate` chia tổng số người dùng quay lại cho tổng số người dùng
đủ điều kiện. `fully_observed_cohort_average_rate` là trung bình cộng đơn giản
của tỷ lệ ở các nhóm người dùng mà mọi người dùng đều đủ điều kiện. Nhóm người
dùng là các khoảng gộp cố định bắt đầu từ `since`. `cohorts` chỉ chứa các nhóm
người dùng có người dùng.

Với `mode: "return_on_or_after"`, đường cong bỏ `window_end_seconds`.

### Tỷ lệ quay lại tự động

Gửi `response_version: 2` và không gửi `start_event` hay `return_event`. Mọi
lượt xem trang, lượt xem màn hình và tương tác được hỗ trợ đều được tính là lần
bắt đầu và lần quay lại. Phiên bản này chọn một tập sự kiện. Nó không chọn định
dạng ghi nhận của SDK.

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-06-03T00:00:00Z",
  "response_version": 2,
  "interval": "day",
  "interval_count": 1,
  "mode": "return_on",
  "cohort_mode": "first_in_range"
}
```

Phản hồi có cùng cấu trúc `summary`, `curve`, `cohorts` và `next_action` với
phản hồi theo sự kiện chính xác. Đoạn trích này hiển thị các trường thay đổi.
Trong ví dụ này, cùng hai người dùng đó có ba sự kiện và không có lượt xem
trang:

```json theme={null}
{
  "schema_version": 2,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-03T00:00:00Z",
    "activity_scope": "all_classified_activity",
    "interval": "day",
    "interval_seconds": 86400,
    "interval_count": 1,
    "mode": "return_on",
    "cohort_mode": "first_in_range"
  },
  "purpose": "Measures whether typed opaque user subjects perform any later supported classified product activity after their first such activity inside the selected half-open range. It does not choose or infer a top event. Returns must occur strictly after the anchor, anonymous and unidentified subjects remain excluded from user counts, eligibility-aware denominators prevent immature subjects from being reported as churned, and raw identifiers are never returned.",
  "coverage": {
    "classified_events": 3,
    "named_events": 3,
    "unnamed_events": 0,
    "identified_events": 3,
    "start_events": 3,
    "usable_start_events": 3,
    "excluded_start_events": 0,
    "return_events": 3,
    "usable_return_events": 3,
    "excluded_return_events": 0,
    "event_name_rate": 1.0,
    "start_identity_coverage_rate": 1.0,
    "return_identity_coverage_rate": 1.0,
    "limitations": [
      "Only application-supplied opaque subject IDs explicitly typed as users are counted. Anonymous, legacy-untyped, historical-unindexed, invalid, or absent subjects are excluded rather than inferred as people.",
      "first_in_range anchors each subject at its first supported classified activity in the range; it does not prove that activity was the subject's first-ever product activity.",
      "Cohort buckets are fixed-width and aligned to the query's since value. hour, day, week, and thirty_day mean fixed elapsed durations; thirty_day is not a calendar month.",
      "Returns are any supported classified activity strictly after the subject anchor and before the exclusive query upper bound; no event is ranked, selected, or inferred.",
      "This resource does not provide recurring-start cohorts, group retention, arbitrary property breakdowns, custom return ranges, or lifetime first-event lookup.",
      "return_on includes only subjects whose complete exact period ends by until; later subjects are excluded from that period's denominator."
    ]
  }
}
```

Ở chế độ tự động, `start_events` và `return_events` đều bằng
`classified_events`. Các số đếm này là sự kiện, không phải người dùng.

### Tỷ lệ quay lại khi không có người dùng đủ điều kiện

Kết quả thành công có thể không có người dùng nào trong nhóm người dùng. Đoạn
trích này cho thấy một kỳ đã yêu cầu nhưng không có nhóm người dùng nào:

```json theme={null}
{
  "schema_version": 2,
  "summary": {
    "cohort_subjects": 0,
    "subjects_returned_after_start": 0,
    "non_empty_cohorts": 0,
    "periods_with_eligible_subjects": 0,
    "fully_observed_periods": 0
  },
  "curve": [
    {
      "period": 0,
      "threshold_seconds": 0,
      "window_end_seconds": 86400,
      "eligible_subjects": 0,
      "retained_subjects": 0,
      "fully_observed_cohorts": 0,
      "all_subjects_eligible": false
    }
  ],
  "cohorts": []
}
```

Đọc `coverage` và `next_action`. Hai trường này phân biệt phạm vi không có sự
kiện đã phân loại (`capture_product_activity`) với sự kiện không có người dùng
(`identify_product_users` hoặc `identify_returning_users`). Tỷ lệ bị thiếu
không phải giá trị 0 đo được.

### Lỗi tỷ lệ quay lại

Ngoài [lỗi phạm vi dùng chung](#shared-scope-errors), các yêu cầu sau trả về
`422` và `validation_failed`:

| Nguyên nhân | `error` |
| - | - |
| Phiên bản 1 không có đủ hai tham số chọn, phiên bản 2 có tham số chọn, hoặc một phiên bản khác | `product analytics retention activity selection is contradictory` |
| `interval_count` nằm ngoài `1` đến `31` | `product analytics retention interval_count must be between 1 and 31` |
| Số khoảng gộp của nhóm người dùng nhân với `interval_count` lớn hơn 500 | `product analytics retention interval and interval_count would exceed 500 cohort matrix cells` |

Giới hạn số ô dựa trên khoảng thời gian và số kỳ, không dựa trên số người dùng.
Khoảng thời gian 30 ngày với `interval: "hour"` có 720 khoảng gộp nhóm người
dùng. Với `interval_count: 1`, tức là 720 ô, nhiều hơn 500:

```json theme={null}
{
  "error": "product analytics retention interval and interval_count would exceed 500 cohort matrix cells",
  "code": "validation_failed",
  "next": "choose a wider interval, a shorter time range, or fewer retention periods",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Để dùng tỷ lệ quay lại tự động, bỏ cả hai tham số chọn. Không thay đổi SDK để
sửa yêu cầu đọc này.

### Yêu cầu vòng đời theo sự kiện chính xác

Gửi body này tới `POST /api/telemetry/analytics/lifecycle`. Yêu cầu này phân
loại người dùng theo một sự kiện, không theo mọi hoạt động trong dự án:

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-06-03T00:00:00Z",
  "response_version": 1,
  "interval": "day",
  "history_period_count": 2,
  "event": { "kind": "interaction", "event_name": "checkout_completed" }
}
```

`history_period_count` đặt số kỳ đầy đủ trước `since` mà LogBrew đọc làm lịch
sử. Trường này nhận `2` đến `31`. Mặc định là `2`. Một người dùng có thể ở
trạng thái không hoạt động với sự kiện này trong khi vẫn làm các hoạt động khác.

### Vòng đời theo sự kiện chính xác thành công

Ví dụ giả lập này dùng hai ngày lịch sử và hai ngày phân tích. Các chữ cái chỉ
dùng để đánh dấu người dùng trong ví dụ. Phản hồi không trả về ID người dùng.

| Ngày, UTC | Người dùng hoàn tất thanh toán |
| - | - |
| Ngày 30 tháng 5, lịch sử | B |
| Ngày 31 tháng 5, lịch sử | A và D |
| Ngày 1 tháng 6, phân tích | A, B và C |
| Ngày 2 tháng 6, phân tích | A và B |

C cũng xem một trang vào ngày 2 tháng 6. Sự kiện đó không khớp với tham số chọn
thanh toán.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-03T00:00:00Z",
    "history_since": "2026-05-30T00:00:00Z",
    "event": { "kind": "interaction", "event_name": "checkout_completed" },
    "interval": "day",
    "interval_seconds": 86400,
    "history_period_count": 2,
    "expected_buckets": 2
  },
  "purpose": "Classifies typed opaque user subjects for one exact product event in each fixed analysis period. new_within_observed_history means active now with no earlier matching event inside the bounded history window; returning means active now and in the immediately previous period; resurrected means active now, inactive in the previous period, and active earlier in observed history; dormant means active in the previous period but not now. These states are disjoint, incomplete buckets are marked, and raw subject identifiers are never returned.",
  "summary": {
    "observed_subjects": 4,
    "analysis_active_subjects": 3,
    "history_only_subjects": 1,
    "returned_buckets": 2,
    "fully_observed_buckets": 2,
    "latest_fully_observed_period": 1,
    "buckets_with_resurrection": 1,
    "buckets_with_dormancy": 2
  },
  "coverage": {
    "analysis_classified_events": 6,
    "analysis_named_events": 6,
    "analysis_unnamed_events": 0,
    "analysis_identified_events": 6,
    "selected_events": 5,
    "usable_selected_events": 5,
    "usable_selected_sessionized_events": 5,
    "usable_selected_trace_linked_events": 5,
    "excluded_selected_events": 0,
    "history_selected_events": 3,
    "usable_history_selected_events": 3,
    "excluded_history_selected_events": 0,
    "event_name_rate": 1.0,
    "selected_identity_coverage_rate": 1.0,
    "selected_sessionization_rate": 1.0,
    "selected_trace_link_rate": 1.0,
    "history_identity_coverage_rate": 1.0,
    "limitations": [
      "Only application-supplied opaque subject IDs explicitly typed as users are counted. Anonymous, legacy-untyped, historical-unindexed, invalid, or absent subjects are excluded rather than inferred as people.",
      "new_within_observed_history means no earlier selected event between history_since and the current bucket. It does not prove that a subject is a lifetime-new user.",
      "Observed history contains exactly 2 complete fixed periods before since; activity before history_since is intentionally unknown.",
      "Buckets are fixed-width and aligned to since. hour, day, week, and thirty_day mean fixed elapsed durations; thirty_day is not a calendar month.",
      "Returning, resurrected, and dormant compare only the selected exact kind and derived event name. They do not infer intent, identity merges, or causality.",
      "This resource does not provide arbitrary property breakdowns, reusable cohorts, group lifecycle, lifetime first-event lookup, or per-subject lists."
    ]
  },
  "buckets": [
    {
      "period": 0,
      "started_at": "2026-06-01T00:00:00Z",
      "ended_at": "2026-06-02T00:00:00Z",
      "fully_observed": true,
      "active_subjects": 3,
      "new_within_observed_history_subjects": 1,
      "returning_subjects": 1,
      "resurrected_subjects": 1,
      "dormant_subjects": 1,
      "previous_active_subjects": 2,
      "new_share_of_active": 0.3333333333333333,
      "returning_share_of_active": 0.3333333333333333,
      "resurrected_share_of_active": 0.3333333333333333,
      "dormant_share_of_previous_active": 0.5,
      "net_active_change": 1
    },
    {
      "period": 1,
      "started_at": "2026-06-02T00:00:00Z",
      "ended_at": "2026-06-03T00:00:00Z",
      "fully_observed": true,
      "active_subjects": 2,
      "new_within_observed_history_subjects": 0,
      "returning_subjects": 2,
      "resurrected_subjects": 0,
      "dormant_subjects": 1,
      "previous_active_subjects": 3,
      "new_share_of_active": 0.0,
      "returning_share_of_active": 1.0,
      "resurrected_share_of_active": 0.0,
      "dormant_share_of_previous_active": 0.3333333333333333,
      "net_active_change": -1
    }
  ],
  "next_action": {
    "code": "investigate_lifecycle_loss",
    "target": "/api/telemetry/analytics/paths",
    "reason": "The latest complete bucket lost more prior active subjects than it added through new-within-observed-history and resurrected activity; compare bounded journeys around the selected event."
  }
}
```

### Đọc vòng đời

Ngày 1 tháng 6, A là quay lại, B là hoạt động trở lại, C là mới và D là không
hoạt động. Ngày 2 tháng 6, A và B là quay lại, còn C không hoạt động với sự
kiện thanh toán dù có lượt xem trang. Thay đổi ròng ngày 2 tháng 6 là
`2 - 3 = -1`.

Trong mỗi khoảng gộp, số người dùng mới, quay lại và hoạt động trở lại cộng lại
bằng `active_subjects`. `returning_subjects` cộng `dormant_subjects` bằng
`previous_active_subjects`. `net_active_change` bằng `active_subjects` trừ
`previous_active_subjects`.

Không cộng số người dùng hoạt động theo ngày để có số người dùng riêng biệt. Ở
đây, các số đếm theo ngày cộng lại bằng 5, nhưng
`analysis_active_subjects` là 3. Có bốn người dùng riêng biệt xuất hiện trong
lịch sử và giai đoạn phân tích.

`fully_observed` là `false` với khoảng gộp cuối kết thúc sau `until`. Số đếm
của khoảng gộp đó có thể thay đổi khi quan sát được trọn kỳ. `next_action` gợi
ý một hướng điều tra. Trường này không chỉ ra nguyên nhân.

### Vòng đời tự động

Gửi `response_version: 2` và không gửi tham số chọn `event`. Mọi lượt xem
trang, lượt xem màn hình và tương tác được hỗ trợ đều được tính là hoạt động:

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-06-03T00:00:00Z",
  "response_version": 2,
  "interval": "day",
  "history_period_count": 2
}
```

Phản hồi có cùng cấu trúc `summary`, `buckets` và `next_action` với phản hồi
theo sự kiện chính xác. Đoạn trích này hiển thị các trường thay đổi:

```json theme={null}
{
  "schema_version": 2,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-03T00:00:00Z",
    "history_since": "2026-05-30T00:00:00Z",
    "activity_scope": "all_classified_activity",
    "interval": "day",
    "interval_seconds": 86400,
    "history_period_count": 2,
    "expected_buckets": 2
  },
  "purpose": "Classifies typed opaque user subjects by any supported classified product activity in each fixed period. It does not choose or infer a top event. new_within_observed_history, returning, resurrected, and dormant remain disjoint; anonymous and unidentified subjects are excluded from user counts, incomplete buckets are marked, and raw identifiers are never returned."
}
```

Ở chế độ tự động, `coverage.selected_events` bằng
`coverage.analysis_classified_events`. Mục thứ năm trong `limitations` là
`Returning, resurrected, and dormant compare any supported classified product activity; no event is ranked, selected, or inferred.`

### Vòng đời khi không có người dùng

Nếu cả khoảng thời gian phân tích lẫn lịch sử đều không có người dùng dùng được,
`buckets` trống và `summary` bỏ `latest_fully_observed_period`:

```json theme={null}
{
  "schema_version": 2,
  "summary": {
    "observed_subjects": 0,
    "analysis_active_subjects": 0,
    "history_only_subjects": 0,
    "returned_buckets": 0,
    "fully_observed_buckets": 0,
    "buckets_with_resurrection": 0,
    "buckets_with_dormancy": 0
  },
  "buckets": []
}
```

Người dùng chỉ xuất hiện trong lịch sử vẫn có thể tạo ra các khoảng gộp có người
dùng không hoạt động khi khoảng thời gian phân tích không có hoạt động nào.

### Lỗi vòng đời

Ngoài [lỗi phạm vi dùng chung](#shared-scope-errors), các yêu cầu sau trả về
`422` và `validation_failed`:

| Nguyên nhân | `error` |
| - | - |
| Phiên bản 1 không có `event`, phiên bản 2 có `event`, hoặc một phiên bản khác | `product analytics lifecycle activity selection is contradictory` |
| `history_period_count` nằm ngoài `2` đến `31` | `product analytics lifecycle history_period_count must be between 2 and 31` |
| Tổng các kỳ lịch sử dài hơn 62 ngày | `product analytics lifecycle history must not exceed 62 days` |
| Hơn 100 khoảng gộp phân tích | `product analytics lifecycle interval would exceed 100 analysis buckets` |

Ví dụ, mười kỳ lịch sử `week` cần 70 ngày:

```json theme={null}
{
  "error": "product analytics lifecycle history must not exceed 62 days",
  "code": "validation_failed",
  "next": "use fewer history periods or a narrower fixed interval",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

### Đọc phạm vi phân tích đã chọn

Phản hồi theo sự kiện chính xác có `schema_version: 1`. `query` của chúng lặp
lại các tham số chọn và bỏ `activity_scope`. Phản hồi tự động có
`schema_version: 2` và `query.activity_scope: "all_classified_activity"`.
Chúng bỏ các tham số chọn. Một tham số chọn khác có thể làm kết quả thay đổi
dù hoạt động đã ghi nhận không đổi.

## Phản hồi chuỗi chỉ số

`GET /api/telemetry/metrics/series` đọc đúng một tên chỉ số trong một dự án.
Sao chép tên từ `GET /api/telemetry/metrics`. Yêu cầu này nhóm một bộ đếm delta
theo dịch vụ:

```bash theme={null}
curl --get "https://api.logbrew.co/api/telemetry/metrics/series" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --data-urlencode "project_id=<project_id>" \
  --data-urlencode "name=jobs.completed" \
  --data-urlencode "since=2026-06-01T12:00:00Z" \
  --data-urlencode "until=2026-06-01T12:15:00Z" \
  --data-urlencode "interval=5m" \
  --data-urlencode "group_by=service_name"
```

### Chuỗi chỉ số thành công

Phản hồi giả lập này chứa một chuỗi bộ đếm delta. Ba mẫu với giá trị `2`, `3`
và `5` nằm trong khoảng gộp đầu tiên. Hai mẫu với giá trị `1` và `4` nằm trong
khoảng gộp cuối cùng. Khoảng gộp ở giữa không có mẫu nào, nên phản hồi không có
điểm dữ liệu cho khoảng gộp đó.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "name": "jobs.completed",
    "since": "2026-06-01T12:00:00Z",
    "until": "2026-06-01T12:15:00Z",
    "interval": "5m",
    "interval_seconds": 300,
    "group_by": "service_name",
    "series_limit": 10
  },
  "purpose": "Shows how one metric changes over time without changing its meaning: gauges use sampled state, delta counters use change volume and rate, histograms use distributions, and cumulative streams stay raw when reset-safe change is ambiguous.",
  "coverage": {
    "samples": 5,
    "series": 1,
    "returned_series": 1,
    "points": 2,
    "expected_buckets_per_series": 3,
    "first_seen_at": "2026-06-01T12:00:10Z",
    "last_seen_at": "2026-06-01T12:14:50Z",
    "truncated": false
  },
  "series": [
    {
      "identity": {
        "kind": "counter",
        "unit": "{job}",
        "temporality": "delta",
        "group_by": "service_name",
        "group_value": "checkout-worker"
      },
      "status": "ready",
      "aggregation": {
        "code": "delta_sum",
        "description": "Primary value is the sum of recorded changes in each bucket; rate_per_second normalizes that change by bucket width."
      },
      "sample_count": 5,
      "points": [
        {
          "bucket_start": "2026-06-01T12:00:00Z",
          "bucket_end": "2026-06-01T12:05:00Z",
          "sample_count": 3,
          "value": 10.0,
          "last": 5.0,
          "min": 2.0,
          "max": 5.0,
          "average": 3.3333333333333335,
          "sum": 10.0,
          "rate_per_second": 0.03333333333333333,
          "trace_exemplars": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
        },
        {
          "bucket_start": "2026-06-01T12:10:00Z",
          "bucket_end": "2026-06-01T12:15:00Z",
          "sample_count": 2,
          "value": 5.0,
          "last": 4.0,
          "min": 1.0,
          "max": 4.0,
          "average": 2.5,
          "sum": 5.0,
          "rate_per_second": 0.016666666666666666,
          "trace_exemplars": []
        }
      ]
    }
  ],
  "next_action": {
    "code": "inspect_metric_change",
    "target": "trace_summary",
    "reason": "Open a trace exemplar from an unusual bucket to connect the metric change to spans, errors, logs, and release context."
  }
}
```

### Đọc chuỗi chỉ số

Điểm dữ liệu đầu tiên ghi nhận 10 công việc đã hoàn thành, không phải 10 mẫu.
`rate_per_second` chia mức thay đổi đó cho khoảng gộp 300 giây. `last` là mức
thay đổi được ghi nhận cuối cùng, không phải tổng. Xem
[ý nghĩa của phép tổng hợp chỉ số](/vi/concepts/telemetry#read-the-metric-value).

Loại và temporality của một chuỗi quyết định `aggregation.code` của chuỗi đó và
các giá trị thống kê trong mỗi điểm dữ liệu. Điểm dữ liệu bỏ giá trị thống kê
không áp dụng. Giá trị thống kê bị thiếu không phải là 0.

| Loại và temporality | `status` | `aggregation.code` | `value` | Các giá trị thống kê khác |
| - | - | - | - | - |
| `gauge`, `instant` | `ready` | `gauge_last` | Mẫu cuối cùng | `last`, `min`, `max`, `average` |
| `counter`, `delta` | `ready` | `delta_sum` | Tổng các mức thay đổi | `last`, `min`, `max`, `average`, `sum`, `rate_per_second` |
| `histogram`, `delta` | `ready` | `distribution_p95` | p95 ước tính | `min`, `max`, `average`, `sum`, `p50`, `p95`, `p99` |
| Loại bất kỳ, `cumulative` | `limited` | `raw_cumulative_last` | Mẫu thô cuối cùng | `last`, `min`, `max` |
| Mọi cặp khác | `limited` | `raw_last` | Mẫu thô cuối cùng | `last`, `min`, `max` |

`limited` là phản hồi thành công, không phải lỗi. Trạng thái này thêm
`aggregation.limitation` để giải thích vì sao LogBrew chỉ hiển thị giá trị thô.
`ready` không chứng minh dữ liệu đã được ghi nhận đầy đủ.

Đọc `coverage` trước khi vẽ biểu đồ:

* `samples` đếm mẫu của mọi chuỗi khớp, kể cả các chuỗi mà phản hồi không trả
  về.
* `series` đếm số chuỗi khớp. `returned_series` và `points` đếm dữ liệu được
  trả về.
* `truncated` là `true` khi `series_limit` đã loại các chuỗi có lượng thấp hơn.
* `expected_buckets_per_series` là số khoảng gộp có thể có trong khoảng thời
  gian.

Không thêm điểm dữ liệu cho khoảng gộp không có mẫu. Không chèn giá trị 0 hay
sao chép giá trị trước đó. Mỗi điểm dữ liệu trả về tối đa 3 `trace_exemplars`.
Một trace exemplar liên kết một mẫu với một trace. Nó không giải thích mọi mẫu
trong khoảng gộp. Nếu không điểm dữ liệu nào có trace exemplar,
`next_action.target` là `metric_samples`.

### Phạm vi và lỗi của chuỗi chỉ số

`project_id`, `name` và `since` là bắt buộc. `name` có tối đa 200 ký tự.
`interval` là `auto`, `1m`, `5m`, `15m`, `1h`, `6h` hoặc `1d`. Mặc định là
`auto`, giá trị này chọn độ dài khoảng gộp nhỏ nhất cần tối đa 300 khoảng gộp.
Độ dài khoảng gộp chỉ định rõ không được cần quá 500 khoảng gộp.

`group_by` là `none`, `service_name`, `release` hoặc `environment`. Mặc định là
`none`. Khi không nhóm, các loại, đơn vị và temporality khác nhau vẫn nằm trong
các chuỗi riêng. `series_limit` nhận `1` đến `20`. Mặc định là `10`.

Kết quả trống trả về `200` với `series: []` và `samples` bằng 0. Object
`coverage` bỏ `first_seen_at` và `last_seen_at`. Điều này không chứng minh
rằng ứng dụng chưa từng gửi chỉ số đó. Kiểm tra dự án, tên chỉ số và khoảng thời
gian.

Thiếu `name` trả về `422`:

```json theme={null}
{
  "error": "metric series name is required",
  "code": "validation_failed",
  "next": "send the exact metric name returned by /api/telemetry/metrics",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Khoảng gộp một phút trên bảy ngày trả về `422`:

```json theme={null}
{
  "error": "metric series interval would exceed 500 buckets",
  "code": "validation_failed",
  "next": "use interval=auto or select a wider interval",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Các lỗi `422` khác là `metric series group_by is not supported`,
`metric series interval is not supported` và
`metric series_limit must be between 1 and 20`.

## Phản hồi phân tích đường dẫn

`POST /api/telemetry/analytics/paths` tìm các sự kiện có tên xảy ra trước hoặc
sau một sự kiện đã chọn trong cùng phiên. Sự kiện đã chọn là điểm neo. Sao chép
`kind` và `event_name` của nó từ `classified_activity.top_events`. Route trả về
`schema_version: 1`. Route không nhận `response_version` hay `analysis_unit`.

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T11:00:00Z",
  "until": "2026-06-01T12:00:00Z",
  "direction": "following",
  "anchor": { "kind": "page_view", "event_name": "/checkout" },
  "depth": 2,
  "collapse_repeated": true,
  "path_limit": 2
}
```

`direction` và `anchor` là bắt buộc.

### Đường dẫn thành công

Trong kết quả giả lập này, bốn phiên chứa điểm neo. Hai đường dẫn được trả về
đại diện cho ba trong số các phiên đó. Một đường dẫn xếp hạng thấp hơn không
được trả về.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T11:00:00Z",
    "until": "2026-06-01T12:00:00Z",
    "direction": "following",
    "anchor": { "kind": "page_view", "event_name": "/checkout" },
    "depth": 2,
    "collapse_repeated": true,
    "path_limit": 2
  },
  "purpose": "Shows the highest-volume named product-event sequences immediately before or after one exact version-1 page view, screen view, or interaction inside explicit sessions. Following paths use the earliest matching anchor in each session; preceding paths use the latest. Optional exact property predicates classify only the anchor, while surrounding events preserve the real session journey. Results aggregate exact bounded sequences and never return raw session or subject identifiers.",
  "summary": {
    "anchored_sessions": 4,
    "represented_sessions": 3,
    "unrepresented_sessions": 1,
    "returned_paths": 2,
    "paths_truncated": true
  },
  "coverage": {
    "classified_events": 12,
    "named_events": 12,
    "unnamed_events": 0,
    "sessionized_events": 10,
    "unsessionized_events": 2,
    "anchor_events": 5,
    "usable_anchor_events": 4,
    "excluded_anchor_events": 1,
    "traced_anchor_events": 1,
    "event_name_rate": 1.0,
    "sessionization_rate": 0.8333333333333334,
    "anchor_session_coverage_rate": 0.8,
    "anchor_trace_link_rate": 0.2,
    "ordered_event_cap_per_session": 1024,
    "limitations": [
      "Paths include only supported version-1 classified events with exact derived names; arbitrary actions, technical spans, and raw identity values are excluded.",
      "Paths stay inside application-supplied session boundaries and the selected half-open time range; activity beyond either boundary is not inferred.",
      "Each session retains at most 1024 direction-nearest named events before anchoring, so exceptionally noisy sessions can be omitted or truncated.",
      "Classified events without an explicit opaque session ID cannot participate in session paths.",
      "Trace exemplars prove only that a matching anchor carried the same trace ID. They do not prove root cause, and deeper investigation depends on retained spans for that trace.",
      "Some matching anchors lack trace IDs, so trace-linked path evidence covers only the reported traced_anchor_events population."
    ]
  },
  "paths": [
    {
      "rank": 1,
      "sessions": 2,
      "share_of_anchored_sessions": 0.5,
      "traced_sessions": 1,
      "trace_link_rate": 0.5,
      "trace_exemplars": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"],
      "nodes": [
        { "relative_position": 0, "kind": "page_view", "event_name": "/checkout" },
        { "relative_position": 1, "kind": "interaction", "event_name": "checkout.submitted" },
        { "relative_position": 2, "kind": "interaction", "event_name": "checkout.completed" }
      ]
    },
    {
      "rank": 2,
      "sessions": 1,
      "share_of_anchored_sessions": 0.25,
      "traced_sessions": 0,
      "trace_link_rate": 0.0,
      "trace_exemplars": [],
      "nodes": [
        { "relative_position": 0, "kind": "page_view", "event_name": "/checkout" },
        { "relative_position": 1, "kind": "interaction", "event_name": "checkout.failed" }
      ]
    }
  ],
  "next_action": {
    "code": "inspect_path_trace",
    "target": "/api/telemetry/traces/{trace_id}/investigation",
    "reason": "Open an exemplar from the material path to connect the product journey to retained spans, issues, logs, actions, metrics, and release context as evidence rather than a root-cause claim."
  }
}
```

### Đọc đường dẫn

`share_of_anchored_sessions` chia số phiên của một đường dẫn cho cả bốn phiên
có điểm neo. Tỷ lệ là 50% và 25%, không phải 67% và 33%.
`unrepresented_sessions` đếm các phiên có điểm neo mà không đường dẫn nào được
trả về đại diện. `paths_truncated: true` nghĩa là kết quả chưa đầy đủ.

Độ bao phủ đếm sự kiện, không đếm phiên. Ở đây, năm sự kiện khớp với điểm neo,
nhưng một sự kiện không có ID phiên. Sự kiện đó không thể nằm trong đường dẫn.
Mỗi đường dẫn trả về tối đa 3 trace exemplar. Dùng trace ID từ chính phản hồi
của bạn. Liên kết trace không cho biết điều gì gây ra hành động của người dùng
hay một lỗi.

| Trường | Ý nghĩa |
| - | - |
| `following` | Bắt đầu tại điểm neo khớp sớm nhất trong mỗi phiên. Điểm neo có vị trí `0`. Các nút sau đó có vị trí dương. |
| `preceding` | Kết thúc tại điểm neo khớp muộn nhất trong mỗi phiên. Các nút trước đó có vị trí âm. Điểm neo có vị trí `0`. |
| `depth` | Số nút liền kề điểm neo, không tính điểm neo. `1` đến `8`. Mặc định là `4`. Một đường dẫn có thể có ít nút hơn. |
| `collapse_repeated` | Gộp các nút liên tiếp có cùng loại và tên. Mặc định là `true`. |
| `path_limit` | Số đường dẫn tối đa được trả về, xếp hạng theo số phiên. `1` đến `20`. Mặc định là `10`. |

Các nút được sắp xếp theo thời gian ở cả hai hướng. Đường dẫn không phải bản
phát lại đầy đủ của phiên. LogBrew đọc tối đa 1024 sự kiện có tên trong mỗi
phiên trước khi chọn điểm neo: các sự kiện sớm nhất với `following` và các sự
kiện muộn nhất với `preceding`. Điểm neo nằm ngoài giới hạn đó có thể bị lược
bỏ.

### <span id="filter-the-anchor-by-property">Lọc điểm neo theo thuộc tính</span>

Gửi tối đa bốn `property_filters`, mỗi bộ lọc có đúng một `key` và `value`.
Sao chép khóa từ [danh mục thuộc tính](#analytics-property-catalog). Bộ lọc chỉ
áp dụng cho điểm neo, không áp dụng cho các sự kiện xung quanh. Giá trị phân
biệt chữ hoa chữ thường. Khi có bộ lọc, `query` lặp lại chúng, và
`coverage.anchor_property_filters` báo cáo:

| Trường | Ý nghĩa |
| - | - |
| `context_events` | Sự kiện điểm neo trong phạm vi, trước khi áp dụng bộ lọc thuộc tính. |
| `property_ready_events` | Sự kiện điểm neo có mọi khóa đã yêu cầu. |
| `missing_property_events` | Sự kiện điểm neo thiếu một hoặc nhiều khóa đã yêu cầu. |
| `matching_events` | Sự kiện điểm neo có giá trị khớp với mọi bộ lọc. |
| `nonmatching_value_events` | Sự kiện điểm neo có mọi khóa nhưng có giá trị khác. |
| `property_ready_rate` | `property_ready_events` chia cho `context_events`. |
| `match_rate` | `matching_events` chia cho `property_ready_events`. |

Thiếu khóa và khác giá trị cần cách sửa khác nhau. Không cộng hai số này với
nhau. Object này bị lược bỏ khi yêu cầu không có bộ lọc thuộc tính.

### Đường dẫn trống và yêu cầu bị từ chối

Mảng `paths` trống có thể là phản hồi `200` thành công. Đọc `summary`,
`coverage` và `next_action`. Các mã sau phân biệt nguyên nhân:
`capture_product_activity`, `choose_captured_path_anchor`,
`capture_anchor_properties`, `improve_anchor_property_coverage`,
`verify_anchor_property_values`, `sessionize_product_activity` và
`narrow_or_move_path_anchor`.

Ngoài [lỗi phạm vi dùng chung](#shared-scope-errors), các yêu cầu sau trả về
`422` và `validation_failed`:

| Nguyên nhân | `error` |
| - | - |
| `depth` nằm ngoài `1` đến `8` | `product analytics path depth must be between 1 and 8` |
| `path_limit` nằm ngoài `1` đến `20` | `product analytics path_limit must be between 1 and 20` |
| Hơn bốn bộ lọc thuộc tính | `product analytics paths accept at most four exact anchor property filters` |
| Khóa không có trong danh mục thuộc tính | `product analytics path property keys must be supported privacy-safe keys` |
| Cùng một khóa xuất hiện hai lần | `product analytics path property keys must be unique` |
| Giá trị trống, dài hơn 256 ký tự hoặc chứa ký tự điều khiển | `product analytics path property values must be non-empty, control-free, and at most 256 characters` |

Ví dụ, `depth: 0` trả về:

```json theme={null}
{
  "error": "product analytics path depth must be between 1 and 8",
  "code": "validation_failed",
  "next": "use depth from 1 through 8 adjacent named events",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

## <span id="analytics-property-catalog">Danh mục thuộc tính phân tích</span>

`GET /api/telemetry/analytics/properties` liệt kê các khóa thuộc tính trên sự
kiện sản phẩm đã phân loại trong một dự án. Dùng các khóa này trong
[so sánh phân khúc](#analytics-segment-comparison) và bộ lọc điểm neo đường dẫn.
Danh mục trả về khóa và số đếm. Danh mục không bao giờ trả về giá trị thuộc tính
hay định danh.

### Đọc các khóa thuộc tính có sẵn

Gửi `project_id` và `since`. Bạn cũng có thể gửi `until`, `service_name`,
`release`, `environment`, `limit` và `response_version`. `limit` nhận từ `1`
đến `50` khóa. Mặc định là `20`. Gửi `response_version=2` để nhận giá trị
`estimation.method` công khai.

```bash theme={null}
curl --get "https://api.logbrew.co/api/telemetry/analytics/properties" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --data-urlencode "project_id=<project_id>" \
  --data-urlencode "since=2026-06-01T00:00:00Z" \
  --data-urlencode "until=2026-06-02T00:00:00Z" \
  --data-urlencode "limit=20" \
  --data-urlencode "response_version=2"
```

### Danh mục thuộc tính thành công

Trong kết quả giả lập này, có 100 sự kiện đã phân loại. Năm sự kiện trong số đó
được ghi nhận trước khi có chỉ mục thuộc tính hiện tại.

```json theme={null}
{
  "schema_version": 2,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-02T00:00:00Z",
    "limit": 20
  },
  "purpose": "Discovers bounded privacy-safe runtime, framework, operating-system, device, application, and custom-tag keys captured on classified product events. It reports migration, capture, privacy-filtering, and per-key coverage without returning property values or identities, so humans and agents can build exact segment comparisons without guessing which dimensions exist.",
  "summary": {
    "classified_events": 100,
    "available_property_keys": 3,
    "returned_properties": 3
  },
  "coverage": {
    "indexed_events": 95,
    "unindexed_events": 5,
    "complete_index_events": 95,
    "incomplete_index_events": 0,
    "privacy_filtered_events": 4,
    "events_with_properties": 90,
    "index_coverage_rate": 0.95,
    "property_capture_rate": 0.9,
    "properties_truncated": false,
    "values_returned": false,
    "limitations": [
      "Property discovery returns keys and aggregate counts only; property values and identity columns are never returned.",
      "Property filters use exact case-sensitive bounded string equality and combine with logical AND inside each segment.",
      "Historical events written before the current property index are excluded from property descriptors and exact property filters.",
      "Direct-identity, credential-like, and network-address custom tag keys were intentionally excluded from the analytics property index."
    ]
  },
  "estimation": {
    "count_accuracy": "approximate",
    "method": "approximate_distinct",
    "description": "Available property-key and per-key distinct-value counts are approximate distinct counts. Classified-event, index-coverage, privacy-filtering, and per-key event counts are exact within the selected fully evaluated window."
  },
  "properties": [
    {
      "key": "resource.runtime.name",
      "source": "standard_context",
      "value_type": "string",
      "events": 90,
      "coverage_rate": 0.9,
      "distinct_values": 2
    },
    {
      "key": "resource.application.version",
      "source": "standard_context",
      "value_type": "string",
      "events": 70,
      "coverage_rate": 0.7,
      "distinct_values": 4
    },
    {
      "key": "tag.plan",
      "source": "custom_tag",
      "value_type": "string",
      "events": 60,
      "coverage_rate": 0.6,
      "distinct_values": 3
    }
  ],
  "next_action": {
    "code": "compare_property_segments",
    "target": "/api/telemetry/analytics/segments/compare",
    "reason": "Use exact returned keys with locally known values to compare behavior while preserving identity and property-value privacy."
  }
}
```

### Diễn giải danh mục

`source` là `standard_context` với khóa ngữ cảnh chuẩn, chẳng hạn
`resource.runtime.name`, hoặc `custom_tag` với khóa bắt đầu bằng `tag.`.
`value_type` luôn là `string`. `properties` được sắp xếp theo `events`, từ cao
xuống thấp.

`tag.plan` có trên 60 trong 100 sự kiện đã phân loại. Khóa này có khoảng 3 giá
trị khác nhau. Phần mô tả khóa không hiển thị các giá trị đó. Dùng các giá trị
mà bạn biết từ ứng dụng của mình. Không đoán giá trị từ số đếm. Một sự kiện có
thể có nhiều khóa, nên không cộng các số đếm `events` của từng khóa.

| Trường | Ý nghĩa |
| - | - |
| `summary.classified_events` | Số sự kiện đã phân loại trong phạm vi. Đây là mẫu số của mỗi `coverage_rate`. |
| `summary.available_property_keys` | Số khóa khác nhau ước tính, không phải số dòng được trả về. |
| `coverage.unindexed_events` | Sự kiện được ghi nhận trước khi có chỉ mục thuộc tính hiện tại. Chúng không thể đóng góp khóa. |
| `coverage.incomplete_index_events` | Sự kiện có một phần ngữ cảnh sai định dạng hoặc bị cắt bớt. Các khóa hợp lệ của chúng vẫn được tính. |
| `coverage.privacy_filtered_events` | Sự kiện mà LogBrew đã xóa các khóa tag tùy chỉnh nhạy cảm. Đây không phải số đếm khóa. |
| `coverage.properties_truncated` | `true` khi số khóa nhiều hơn `limit`. Thu hẹp phạm vi, hoặc tăng `limit` tối đa đến 50. |
| `coverage.values_returned` | Luôn là `false`. |

Mảng `properties` trống không chứng minh rằng dự án không có sự kiện sản phẩm.
Đọc `summary`, `coverage` và `next_action`.

### Lỗi danh mục thuộc tính

Ngoài [lỗi phạm vi dùng chung](#shared-scope-errors), `limit=0` hoặc
`limit=51` trả về `422`:

```json theme={null}
{
  "error": "product analytics property limit must be between 1 and 50",
  "code": "validation_failed",
  "next": "use limit=1 through limit=50",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

`response_version` khác `1` hoặc `2` trả về
`product analytics response_version must be 1 or 2`. LogBrew kiểm tra
`response_version` trước các giá trị khác.

Yêu cầu `POST` trả về `405`:

```json theme={null}
{
  "error": "Method not allowed",
  "code": "method_not_allowed",
  "next": "send GET /api/telemetry/analytics/properties with required project_id and since plus optional until, service_name, release, environment, limit, or response_version query parameters",
  "next_action": { "code": "use_supported_method", "target": "api_method" }
}
```

## <span id="analytics-segment-comparison">So sánh phân khúc phân tích</span>

`POST /api/telemetry/analytics/segments/compare` so sánh tần suất các phiên hoặc
người dùng đạt tới một sự kiện chính xác trên 2 đến 4 phân khúc trong một dự
án. Một phân khúc chọn sự kiện theo dịch vụ, bản phát hành, môi trường và giá
trị thuộc tính. Phân khúc đầu tiên là phân khúc mốc.

### Định nghĩa phép so sánh

Gửi body JSON này cùng xác thực tài khoản và
`Content-Type: application/json`. Ở đây, `basic` và `premium` là giá trị gói của
ứng dụng ví dụ, không phải gói của LogBrew:

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T11:00:00Z",
  "until": "2026-06-01T12:00:00Z",
  "interval": "1h",
  "analysis_unit": "session",
  "response_version": 2,
  "target": { "kind": "interaction", "event_name": "checkout_completed" },
  "segments": [
    {
      "key": "basic",
      "label": "Basic plan",
      "service_name": "checkout-api",
      "environment": "production",
      "property_filters": [{ "key": "tag.plan", "value": "basic" }]
    },
    {
      "key": "premium",
      "label": "Premium plan",
      "service_name": "checkout-api",
      "environment": "production",
      "property_filters": [{ "key": "tag.plan", "value": "premium" }]
    }
  ]
}
```

`target` và `segments` là bắt buộc. `analysis_unit` là `session` hoặc
`identified_user`. Mặc định là `session`, tức là đếm phiên, không đếm người.
`interval` nhận cùng các giá trị như route tổng quan. Mặc định là `auto`.

Mỗi phân khúc cần một `key` duy nhất, một `label` và một tập bộ lọc khác biệt:

* `key`: 1 đến 32 byte. Bắt đầu bằng chữ cái ASCII viết thường hoặc chữ số. Chỉ
  dùng chữ cái ASCII viết thường, chữ số, `_` và `-`.
* `label`: 1 đến 80 ký tự, không chứa ký tự điều khiển.
* `service_name`, `release`, `environment`: không bắt buộc. Mỗi giá trị có 1 đến
  256 ký tự, không chứa ký tự điều khiển.
* `property_filters`: 0 đến 4 bộ lọc. Mỗi khóa chỉ xuất hiện một lần trong một
  phân khúc. Sự kiện phải khớp với mọi bộ lọc của phân khúc. Giá trị phân biệt
  chữ hoa chữ thường, dài 1 đến 256 ký tự, và LogBrew cắt khoảng trắng ở đầu
  và cuối.

Phân khúc không có bộ lọc chọn toàn bộ hoạt động đã phân loại trong dự án và
khoảng thời gian. Các phân khúc có thể chồng lấn nhau. Nhãn hay khóa khác nhau
không làm cho hai tập bộ lọc giống hệt nhau trở nên hợp lệ.

### So sánh phân khúc thành công

Trong kết quả giả lập này, phân khúc mốc đạt tới bước thanh toán ở 10 trên 50
phiên. Phân khúc premium đạt tới bước đó ở 18 trên 60 phiên.

```json theme={null}
{
  "schema_version": 2,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T11:00:00Z",
    "until": "2026-06-01T12:00:00Z",
    "interval": "1h",
    "interval_seconds": 3600,
    "analysis_unit": "session",
    "target": { "kind": "interaction", "event_name": "checkout_completed" },
    "segments": [
      {
        "key": "basic",
        "label": "Basic plan",
        "service_name": "checkout-api",
        "release": null,
        "environment": "production",
        "property_filters": [{ "key": "tag.plan", "value": "basic" }]
      },
      {
        "key": "premium",
        "label": "Premium plan",
        "service_name": "checkout-api",
        "release": null,
        "environment": "production",
        "property_filters": [{ "key": "tag.plan", "value": "premium" }]
      }
    ]
  },
  "purpose": "Compares how often explicit sessions or typed opaque user subjects reach one exact versioned page-view, screen-view, or interaction outcome across two through four named service, release, environment, and exact safe-property segments. It distinguishes missing property capture from nonmatching values, returns time trends and descriptive differences from the first segment, and never returns identities or claims causality or statistical significance.",
  "summary": {
    "segment_count": 2,
    "baseline_segment_key": "basic",
    "segments_with_eligible_units": 2,
    "segments_with_target_events": 2,
    "segments_with_reached_units": 2
  },
  "confidence": {
    "interpretation": "descriptive_only",
    "unique_count_accuracy": "approximate",
    "estimation_method": "approximate_distinct",
    "causal_inference": "not_established",
    "statistical_significance": "not_tested",
    "segment_overlap": "possible",
    "limitations": [
      "Unique session or typed user-subject counts use bounded cardinality estimates; event and capture-coverage totals are exact within the fully evaluated window.",
      "Segments are evaluated independently and may overlap, so their totals must not be added or interpreted as a population partition.",
      "Differences and relative lift are descriptive only. They do not control for exposure, assignment, seasonality, selection bias, or other confounders.",
      "Bucket-level unique counts are recalculated inside each bucket and are not additive across the series.",
      "Session analysis compares visits or app sessions, not unique people.",
      "At least one segment has classified events without the selected unit ID; compare unit_coverage_rate before interpreting reach differences.",
      "Property predicates are exact case-sensitive string matches. Events without the current property index or every requested key are excluded from segment results and reported separately as missing_property_events.",
      "Direct-identity, credential-like, and network-address custom tag keys are excluded from the analytics property index and cannot be used for segmentation."
    ]
  },
  "segments": [
    {
      "key": "basic",
      "label": "Basic plan",
      "eligible_units": 50,
      "reached_units": 10,
      "reach_rate": 0.2,
      "usable_target_events_per_reached_unit": 1.8,
      "coverage": {
        "classified_events": 200,
        "unit_identified_events": 190,
        "excluded_events": 10,
        "unit_coverage_rate": 0.95,
        "target_events": 20,
        "usable_target_events": 18,
        "excluded_target_events": 2,
        "target_unit_coverage_rate": 0.9,
        "traced_target_events": 10,
        "target_trace_link_rate": 0.5,
        "property_filters": {
          "context_events": 500,
          "property_ready_events": 480,
          "missing_property_events": 20,
          "property_ready_rate": 0.96,
          "matching_events": 200,
          "nonmatching_value_events": 280,
          "match_rate": 0.4166666666666667
        }
      },
      "series": [
        {
          "bucket_start": "2026-06-01T11:00:00Z",
          "bucket_end": "2026-06-01T12:00:00Z",
          "classified_events": 200,
          "eligible_units": 50,
          "target_events": 20,
          "usable_target_events": 18,
          "reached_units": 10,
          "reach_rate": 0.2
        }
      ]
    },
    {
      "key": "premium",
      "label": "Premium plan",
      "eligible_units": 60,
      "reached_units": 18,
      "reach_rate": 0.3,
      "usable_target_events_per_reached_unit": 1.8888888888888888,
      "coverage": {
        "classified_events": 240,
        "unit_identified_events": 228,
        "excluded_events": 12,
        "unit_coverage_rate": 0.95,
        "target_events": 36,
        "usable_target_events": 34,
        "excluded_target_events": 2,
        "target_unit_coverage_rate": 0.9444444444444444,
        "traced_target_events": 18,
        "target_trace_link_rate": 0.5,
        "property_filters": {
          "context_events": 500,
          "property_ready_events": 480,
          "missing_property_events": 20,
          "property_ready_rate": 0.96,
          "matching_events": 240,
          "nonmatching_value_events": 240,
          "match_rate": 0.5
        }
      },
      "series": [
        {
          "bucket_start": "2026-06-01T11:00:00Z",
          "bucket_end": "2026-06-01T12:00:00Z",
          "classified_events": 240,
          "eligible_units": 60,
          "target_events": 36,
          "usable_target_events": 34,
          "reached_units": 18,
          "reach_rate": 0.3
        }
      ],
      "comparison_to_baseline": {
        "eligible_units_difference": 10,
        "reached_units_difference": 8,
        "target_events_difference": 16,
        "reach_rate_difference": 0.09999999999999998,
        "relative_reach_rate_lift": 0.4999999999999998
      }
    }
  ],
  "next_action": {
    "code": "investigate_segment_paths",
    "target": "/api/telemetry/analytics/paths",
    "reason": "Inspect paths around the target in the weakest segment, then use correlated traces to explain a material behavioral difference."
  }
}
```

### Đọc tỷ lệ và mức chênh lệch

`eligible_units` ước tính số phiên hoặc người dùng có hoạt động đã phân loại
trong phân khúc. `reached_units` ước tính bao nhiêu trong số đó đã đạt tới mục
tiêu. `reach_rate` bằng `reached_units` chia cho `eligible_units`. Sự kiện
không có ID của đơn vị đã chọn không được tính vào các đơn vị này.

Tỷ lệ của phân khúc mốc là 20%. Tỷ lệ của phân khúc premium là 30%. Mức chênh
lệch là 10 điểm phần trăm. Mức tăng tương đối là 50%, không phải 10%. Các sai
số thập phân nhỏ đến từ phép tính dấu phẩy động. Làm tròn tỷ lệ khi hiển thị,
nhưng tính toán bằng các giá trị được trả về. Phân khúc mốc không có
`comparison_to_baseline`. Mức tăng tương đối bị lược bỏ khi tỷ lệ đạt tới của
phân khúc mốc bằng 0.

Trong `query`, bộ lọc phân khúc mà bạn không gửi là `null`. Danh sách
`property_filters` trống bị lược bỏ.

`coverage.property_filters` có cùng các trường như
[độ bao phủ của bộ lọc điểm neo đường dẫn](#filter-the-anchor-by-property). Ở
đây, `matching_events` bằng `classified_events`. Tách riêng trường hợp thiếu
khóa và khác giá trị. Các phân khúc có thể chồng lấn, và một phiên có thể xuất
hiện trong nhiều khoảng gộp. Không cộng số đơn vị giữa các phân khúc hay các
khoảng gộp.

Phép so sánh này chỉ mang tính mô tả. `confidence.causal_inference` là
`not_established` và `confidence.statistical_significance` là `not_tested`.
Tỷ lệ 30% so với 20% không cho thấy một gói đã khiến số lượt thanh toán tăng
lên.

### Lỗi so sánh phân khúc

Ngoài [lỗi phạm vi dùng chung](#shared-scope-errors), các yêu cầu sau trả về
`422` và `validation_failed`:

| Nguyên nhân | `error` |
| - | - |
| Ít hơn 2 hoặc nhiều hơn 4 phân khúc | `product analytics segment comparison requires two through four segments` |
| Hai phân khúc có cùng khóa | `product analytics segment keys must be unique` |
| Hai phân khúc có cùng bộ lọc | `product analytics segment filters must be unique` |
| Khóa không gồm 1 đến 32 byte được phép | `product analytics segment keys must be 1 through 32 machine-safe bytes` |
| Nhãn trống, quá dài hoặc chứa ký tự điều khiển | `product analytics segment labels must be non-empty, control-free, and at most 80 characters` |
| Giá trị bộ lọc chứa ký tự điều khiển | `product analytics segment filters must be control-free` |
| Hơn bốn bộ lọc thuộc tính trong một phân khúc | `product analytics segments accept at most four exact property filters` |
| Khóa không có trong danh mục thuộc tính | `product analytics segment property keys must be supported privacy-safe keys` |
| Cùng một khóa thuộc tính xuất hiện hai lần trong một phân khúc | `product analytics segment property keys must be unique within each segment` |
| Giá trị thuộc tính trống, quá dài hoặc chứa ký tự điều khiển | `product analytics segment property values must be non-empty, control-free, and at most 256 characters` |
| `response_version` khác `1` hoặc `2` | `product analytics response_version must be 1 or 2` |

Các lỗi của `interval` giống với [lỗi tổng quan](#overview-errors).

Ví dụ, hai phân khúc có khóa khác nhau nhưng bộ lọc giống hệt nhau trả về:

```json theme={null}
{
  "error": "product analytics segment filters must be unique",
  "code": "validation_failed",
  "next": "change at least one exact service_name, release, environment, or property filter",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Nhãn khác hay thứ tự bộ lọc thuộc tính khác không làm thay đổi các sự kiện được
chọn. Lỗi kiểm tra hợp lệ không phải bằng chứng cho thấy không có sự kiện nào
khớp.

Yêu cầu `GET` trả về `405`:

```json theme={null}
{
  "error": "Method not allowed",
  "code": "method_not_allowed",
  "next": "send POST /api/telemetry/analytics/segments/compare with project_id, since, one exact target, two through four named segments, and optional until, interval, analysis_unit, property_filters, or response_version JSON fields",
  "next_action": { "code": "use_supported_method", "target": "api_method" }
}
```

## Phản hồi lượng tín hiệu

`GET /api/telemetry/summary/volume` đếm các tín hiệu được giữ lại của một dự án
trong một khoảng thời gian. Route này yêu cầu `project_id` và `since`. Route
không nhận `project_ids`.

`until` không được ở tương lai. Nếu bỏ `until`, thời điểm kết thúc là lúc gửi
yêu cầu. `since` dạng rút gọn như `24h` được tính lùi từ `until`. `interval` là
`auto`, `1m`, `5m`, `15m`, `1h`, `6h` hoặc `1d`. Giá trị mặc định `auto` chọn
độ dài khoảng gộp nhỏ nhất cần tối đa 120 khoảng gộp. Một yêu cầu không được
cần quá 500 khoảng gộp. `response_version` duy nhất là `1`.

### Số đếm tín hiệu

Phản hồi giả lập này bao gồm hai khoảng gộp một phút. Yêu cầu chạy lúc 12:02
UTC và không có `until`. Tài khoản có chính sách giữ dữ liệu 30 ngày. Đọc chính
sách và mốc cắt được trả về. Đừng giả định các giá trị này áp dụng cho tài khoản
của bạn.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "requested_since": "2026-09-08T12:00:00Z",
    "since": "2026-09-08T12:00:00Z",
    "until": "2026-09-08T12:02:00Z",
    "interval": "1m",
    "interval_seconds": 60,
    "bucket_alignment": "query_relative_utc_half_open",
    "bucket_count": 2,
    "service_name": "checkout-api",
    "release": "api@1.2.3",
    "environment": "production"
  },
  "purpose": "Compares retained issue occurrences, log events, unique traces, action events, and metric points over one exact project and time scope. Every lane is independently scalable, uses explicit zero-filled half-open buckets, returns no source telemetry rows, and qualifies retention and sampling so different signal volumes are not mistaken for equivalent impact.",
  "series": [
    {
      "signal": "issues",
      "count_unit": "issue_occurrences",
      "total": 1,
      "peak": 1,
      "non_empty_buckets": 1,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 1 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 0 }
      ]
    },
    {
      "signal": "logs",
      "count_unit": "log_events",
      "total": 3,
      "peak": 2,
      "non_empty_buckets": 2,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 2 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 1 }
      ]
    },
    {
      "signal": "traces",
      "count_unit": "unique_traces_by_first_observed_span",
      "total": 1,
      "peak": 1,
      "non_empty_buckets": 1,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 1 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 0 }
      ]
    },
    {
      "signal": "actions",
      "count_unit": "action_events",
      "total": 1,
      "peak": 1,
      "non_empty_buckets": 1,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 1 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 0 }
      ]
    },
    {
      "signal": "metrics",
      "count_unit": "metric_points",
      "total": 2,
      "peak": 2,
      "non_empty_buckets": 1,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 0 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 2 }
      ]
    }
  ],
  "coverage": {
    "storage_evaluation": "complete",
    "output_truncation": "not_truncated",
    "payload_shape": "aggregate_only",
    "count_precision": "exact",
    "integer_safety": "javascript_safe",
    "javascript_safe_integer_max": 9007199254740991,
    "returned_series": 5,
    "returned_points": 10,
    "max_buckets_per_series": 500,
    "retention": {
      "policy_days": 30,
      "cutoff": "2026-08-09T12:02:00Z",
      "window_clipped": false
    },
    "sampling": {
      "server": "not_applied",
      "upstream": "unknown"
    },
    "limitations": ["upstream_sampling_unknown", "release_volume_not_included"]
  }
}
```

### Đọc mỗi số đếm theo đơn vị riêng của nó

| Tín hiệu | `total` đếm gì | Không hiểu thành |
| - | - | - |
| `issues` | Số lần xảy ra của vấn đề được giữ lại | Số vấn đề đã gộp nhóm hoặc số người dùng bị ảnh hưởng |
| `logs` | Số sự kiện log được giữ lại | Số yêu cầu |
| `traces` | Số trace ID duy nhất, được tính tại span được giữ lại đầu tiên của chúng trong khoảng thời gian này | Số span hoặc số trace bắt đầu trong toàn bộ thời gian |
| `actions` | Số sự kiện hành động được giữ lại | Số người dùng hoặc số phiên |
| `metrics` | Số điểm chỉ số được giữ lại | Tổng giá trị chỉ số |

`total` là tổng số đếm của các khoảng gộp trong chuỗi. `peak` là số đếm lớn nhất
của một khoảng gộp. `non_empty_buckets` đếm các khoảng gộp có số đếm lớn hơn 0.
Năm chuỗi luôn xuất hiện theo thứ tự này. Không gộp số đếm của các tín hiệu khác
nhau thành một điểm tác động duy nhất.

Các khoảng gộp bắt đầu tại `query.since`. Mỗi khoảng gộp bao gồm thời điểm bắt
đầu và không bao gồm thời điểm kết thúc. Khoảng gộp cuối có thể ngắn hơn độ dài
khoảng gộp. Phản hồi không có chuỗi đếm bản phát hành. Không hiểu
`release_volume_not_included` là không có bản phát hành nào.

### Khoảng thời gian trống và bị rút ngắn

Nếu không có tín hiệu nào khớp, cả năm chuỗi vẫn còn, và các điểm dữ liệu của
chúng có số đếm 0 rõ ràng. Yêu cầu thất bại là trường hợp khác. Không thay lỗi
bằng một biểu đồ toàn giá trị 0.

So sánh `query.requested_since` với `query.since`. Nếu thời gian giữ dữ liệu
làm rút ngắn khoảng thời gian, `coverage.retention.window_clipped` là `true` và
`limitations` chứa `retention_window_clipped`. Nếu không còn phần nào của khoảng
thời gian đã yêu cầu, `query.bucket_count` là `0` và mỗi chuỗi có mảng `points`
trống. Điều này không chứng minh rằng không có sự kiện nào xảy ra trong giai
đoạn đó.

`policy_days` là `null` và `cutoff` bị lược bỏ khi không có giới hạn giữ dữ liệu
nào áp dụng. `sampling.upstream` luôn là `unknown`, kể cả khi
`storage_evaluation` là `complete`. Không khẳng định rằng phản hồi đếm mọi sự
kiện mà ứng dụng đã tạo ra.

### Yêu cầu lượng tín hiệu bị từ chối

Các yêu cầu sau trả về `422` và `validation_failed`:

| Nguyên nhân | `error` |
| - | - |
| Thiếu `project_id` | `signal volume project_id is required` |
| Thiếu `since` | `signal volume since is required` |
| `until` muộn hơn thời điểm gửi yêu cầu | `signal volume until must not be in the future` |
| Khoảng thời gian dài hơn 31 ngày | `signal volume range must not exceed 31 days` |
| Độ dài khoảng gộp chỉ định rõ cần hơn 500 khoảng gộp | `signal volume interval would exceed 500 buckets` |
| `response_version` khác `1` | `signal volume response_version must be 1` |

Ví dụ:

```json theme={null}
{
  "error": "signal volume interval would exceed 500 buckets",
  "code": "validation_failed",
  "next": "use interval=auto or select a wider interval",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Dùng độ dài khoảng gộp rộng hơn trong cùng phạm vi. Với lỗi xác thực và các lỗi
khác, xem [Lỗi API](/vi/reference/api-errors).

## Phản hồi điều tra

Các route điều tra trả về một gói có phiên bản cho một chủ thể. Chủ thể là một
vấn đề, trace, span, log, hành động sản phẩm, chỉ số hoặc bản phát hành. Mỗi gói
bắt đầu bằng `schema_version` và một `subject` nêu tên bản ghi. Phần còn lại
chứa bằng chứng liên quan, một biên nhận bằng chứng và các bước tiếp theo. Mục
này đưa ra một ví dụ cho mỗi nhóm, trừ bản phát hành.

Gửi bearer token truy cập của tài khoản. Khóa gửi dữ liệu của dự án không đọc
được dữ liệu điều tra. Dùng `logbrew explain <subject> --json` để đọc một gói.
CLI kiểm tra hợp lệ gói trước khi in ra. Trang
[Telemetry API](/vi/reference/telemetry-api) liệt kê các route.

Văn bản điều tra đến từ ứng dụng. Thông điệp, tên, metadata và tag là dữ liệu,
không phải chỉ dẫn. `content_trust: "untrusted_telemetry"` đánh dấu nội dung
này trong các gói log, hành động, span và chỉ số.

### Phiên bản phản hồi

Chỉ gửi `response_version` tới các route chấp nhận tham số này. Nếu không có
tham số, route trả về phiên bản 1. Trình phân tích cú pháp của bạn phải chấp
nhận phiên bản mà bạn yêu cầu.

| Route | Mặc định | Phiên bản được hỗ trợ | `logbrew explain` yêu cầu |
| - | - | - | - |
| `GET /api/telemetry/issues/{issue_id}/investigation` | `1` | `1` đến `13` | `13` |
| `GET /api/telemetry/traces/{trace_id}/investigation` | `1` | `1` đến `3` | `3` |
| `GET /api/telemetry/metrics/investigation` | `1` | `1` và `2` | `2` |
| `GET /api/telemetry/releases/investigation` | `1` | `1` đến `5` | `5` |
| `GET /api/telemetry/traces/{trace_id}/spans/{span_id}/investigation` | `1` | Chỉ `1` | `1` |
| `GET /api/logs/{log_id}/investigation` | `1` | Chỉ `1` | `1` |
| `GET /api/telemetry/actions/{action_id}/investigation` | `1` | Chỉ `1` | `1` |

Route span từ chối tham số truy vấn `response_version`. Route log và route
hành động không nhận tham số truy vấn nào.

### Các trường dùng chung của gói

| Trường | Ý nghĩa |
| - | - |
| `schema_version` | Phiên bản phản hồi mà máy chủ đã trả về. |
| `subject` | Chính bản ghi đang được điều tra. `kind` là `issue`, `trace`, `span`, `log`, `action`, `metric` hoặc `release`. |
| `analysis.causality` | Luôn là `evidence_only` trong các gói trace, span, log, hành động và chỉ số. Telemetry có tương quan không chứng minh nguyên nhân. |
| Các object collection | Bằng chứng liên quan, dạng `{ "status", "items", "truncated" }`. |
| `timeline` | Bằng chứng được trả về, từ cũ nhất đến mới nhất, kèm cờ `truncated` riêng. Thứ tự này không chứng minh nguyên nhân. |
| `evidence` | Biên nhận bằng chứng. `status` là `complete` hoặc `partial`. |
| `next_actions` | Các lượt đọc được gợi ý theo thứ tự `priority`, bắt đầu từ `1`. Chúng chưa được chạy. |

Mỗi collection liên quan báo một `status` về mức khả dụng:

| Trạng thái | Ý nghĩa | Cách client xử lý |
| - | - | - |
| `available` | Lượt đọc đã hoàn tất và trả về các mục. | Hiển thị các mục và cờ `truncated`. |
| `not_linked` | Chủ thể không có định danh cho liên kết này, chẳng hạn trace ID. | Giải thích liên kết bị thiếu. Không tự dựng liên kết từ dấu thời gian. |
| `not_found` | Lượt đọc đã hoàn tất và không tìm thấy bằng chứng nào được giữ lại. | Hiển thị kết quả trống. |
| `unavailable` | Lượt đọc không bắt buộc đã thất bại. Chủ thể vẫn hợp lệ. | Tiếp tục hiển thị chủ thể. Thử lại sau. Không hiển thị kết quả là 0 mục. |

Biên nhận bằng chứng có bốn danh sách tên trường ổn định đã sắp xếp:
`captured_fields`, `missing_fields`, `redacted_fields` và
`truncated_fields`. `status` chỉ là `complete` khi ba danh sách sau cùng trống.
Dữ liệu đã che không phải dữ liệu chưa ghi nhận. Dữ liệu bị cắt bớt không phải
dữ liệu đầy đủ. Không tự điền giá trị đã che hoặc bị cắt bớt.

### Giới hạn điều tra

Các giới hạn này áp dụng cho một phản hồi. Cờ `truncated` hoặc một mục trong
`truncated_fields` cho thấy giới hạn đã khiến dữ liệu bị bỏ bớt.

| Bằng chứng | Giới hạn |
| - | - |
| Các mục liên quan trong một collection | 20 |
| Số span được giữ lại được đọc cho một trace | 1.000 |
| Các mục trong timeline | 50 với gói log, hành động và span. 100 với gói trace và chỉ số. |
| Thuộc tính có cấu trúc (attributes, properties) và metadata | 64 giá trị vô hướng, 4 cấp object hoặc mảng, 16 mục trong mỗi mảng, 512 ký tự trong mỗi chuỗi |
| Khoảng thời gian tương quan | 5 phút trước và sau một log, hành động hoặc lần xảy ra đã chọn của vấn đề. Với trace hoặc span, 5 phút trước lúc bắt đầu và sau lúc kết thúc, tối đa 24 giờ. |

Mục của từng nhóm liệt kê giới hạn riêng.

### Phản hồi điều tra vấn đề

Dùng `GET /api/telemetry/issues/{issue_id}/investigation` để đọc bằng chứng cho
một lần xảy ra của vấn đề đã gộp nhóm.
Trang [Điều tra một vấn đề](/vi/guides/investigate-an-issue) cho biết cách đọc
bằng chứng theo thứ tự. Yêu cầu phiên bản 13:

```bash theme={null}
curl --fail-with-body -sS -G \
  "https://api.logbrew.co/api/telemetry/issues/$LOGBREW_ISSUE_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN" \
  --data-urlencode "response_version=13" \
  --data-urlencode "selection=recommended"
```

Các tham số truy vấn là `response_version`, `selection` và `occurrence_id`.
`selection` là `recommended`, `first` hoặc `latest`. Các giá trị phân biệt chữ
hoa chữ thường. Ở phiên bản 2 đến 13, nếu bỏ tham số chọn, route dùng
`recommended`. Phiên bản 1 trả về lần xảy ra gần nhất được giữ lại và không nhận
tham số chọn. Bộ lọc của danh sách vấn đề không áp dụng cho lượt đọc này.

<Accordion title="Ví dụ điều tra vấn đề phiên bản 13">
  Phản hồi `200 OK` giả lập này có một lần xảy ra `TypeError` đã xử lý, kèm một
  trace được liên kết. Phản hồi không có bằng chứng về yêu cầu, breadcrumb, log
  liên quan hay lần triển khai, nên `evidence.status` là `partial`.

  ```json theme={null}
  {
    "schema_version": 13,
    "subject": {
      "kind": "issue", "id": "11111111-1111-4111-8111-111111111111",
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "fingerprint": "checkout-cart-total", "status": "unresolved", "severity": "error",
      "title": "TypeError",
      "message": "Cannot read properties of undefined (reading 'total')",
      "occurrence_count": 1, "first_seen_at": "2026-08-03T11:05:00Z",
      "last_seen_at": "2026-08-03T11:05:00Z"
    },
    "event": {
      "id": "22222222-2222-4222-8222-222222222222",
      "occurred_at": "2026-08-03T11:05:00Z",
      "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
      "context": {
        "schema_version": 1,
        "resource": {
          "service": null,
          "deployment": null,
          "runtime": {"name": "node", "version": "24.4.0"},
          "framework": null,
          "operating_system": {"name": "Linux", "version": "6.8", "build": null},
          "device": {"family": null, "model": null, "architecture": "arm64"},
          "application": null
        },
        "trace": {
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "span_id": "00f067aa0ba902b7",
          "parent_span_id": null, "sampled": true
        },
        "session": null,
        "subject": null,
        "tags": {}
      },
      "exception": {"type": "TypeError", "mechanism": {"type": "javascript.error", "handled": true}},
      "exception_chain": {
        "status": "captured",
        "entries": [
          {
            "id": 0,
            "parent_id": null,
            "relationship": "reported",
            "type": "TypeError",
            "message": null,
            "message_state": "redacted",
            "module": null,
            "mechanism": {"type": "javascript.error", "handled": true},
            "stack_frames": [
              {
                "index": 0, "module": null, "function": "cartTotal", "file": "src/cart.ts",
                "line": 42, "column": 17, "in_app": null, "source": "captured"
              },
              {
                "index": 1, "module": null, "function": "handleCheckout",
                "file": "src/routes/checkout.ts", "line": 88, "column": 9, "in_app": null,
                "source": "captured"
              }
            ],
            "stack_frames_state": "captured"
          }
        ],
        "truncated": false
      },
      "stack_frames": [
        {
          "index": 0, "module": null, "function": "cartTotal", "file": "src/cart.ts",
          "line": 42, "column": 17, "in_app": null, "source": "captured"
        },
        {
          "index": 1, "module": null, "function": "handleCheckout",
          "file": "src/routes/checkout.ts", "line": 88, "column": 9, "in_app": null,
          "source": "captured"
        }
      ],
      "breadcrumbs": [],
      "breadcrumbs_truncated": false
    },
    "occurrence_selection": {
      "requested": "recommended",
      "reason": "only_retained_occurrence",
      "selected": {
        "id": "22222222-2222-4222-8222-222222222222",
        "occurred_at": "2026-08-03T11:05:00Z",
        "severity": "error",
        "environment": "production",
        "release": "checkout@1.2.3",
        "service_name": "checkout-api",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "exception_type": "TypeError",
        "trace_linked": true,
        "stack": {"frame_count": 2, "truncated": false},
        "breadcrumbs": {"count": 0, "truncated": false},
        "context_captured": true
      },
      "first": {
        "id": "22222222-2222-4222-8222-222222222222",
        "occurred_at": "2026-08-03T11:05:00Z",
        "severity": "error",
        "environment": "production",
        "release": "checkout@1.2.3",
        "service_name": "checkout-api",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "exception_type": "TypeError",
        "trace_linked": true,
        "stack": {"frame_count": 2, "truncated": false},
        "breadcrumbs": {"count": 0, "truncated": false},
        "context_captured": true
      },
      "latest": {
        "id": "22222222-2222-4222-8222-222222222222",
        "occurred_at": "2026-08-03T11:05:00Z",
        "severity": "error",
        "environment": "production",
        "release": "checkout@1.2.3",
        "service_name": "checkout-api",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "exception_type": "TypeError",
        "trace_linked": true,
        "stack": {"frame_count": 2, "truncated": false},
        "breadcrumbs": {"count": 0, "truncated": false},
        "context_captured": true
      },
      "recommended": {
        "id": "22222222-2222-4222-8222-222222222222",
        "occurred_at": "2026-08-03T11:05:00Z",
        "severity": "error",
        "environment": "production",
        "release": "checkout@1.2.3",
        "service_name": "checkout-api",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "exception_type": "TypeError",
        "trace_linked": true,
        "stack": {"frame_count": 2, "truncated": false},
        "breadcrumbs": {"count": 0, "truncated": false},
        "context_captured": true
      },
      "recommendation": {
        "algorithm_version": 1, "candidate_count": 1, "candidate_limit": 50,
        "candidate_window_truncated": false
      }
    },
    "lifecycle": {
      "persisted_status": "unresolved",
      "effective_status": "unresolved",
      "activity": {"status": "available", "changes": [], "truncated": false},
      "regression": {
        "status": "not_detected", "reason": "no_resolution_recorded",
        "resolution_changed_at": null, "first_reappeared_occurrence": null
      }
    },
    "occurrence_analysis": {
      "status": "complete",
      "coverage": {
        "retained_occurrences": 1, "trend_occurrences": 1, "available_distribution_count": 4,
        "expected_distribution_count": 4, "max_buckets": 30, "max_values_per_dimension": 10
      },
      "trend": {
        "scope_start": "2026-08-03T11:05:00Z",
        "scope_end": "2026-08-03T11:05:00Z",
        "interval_seconds": 60,
        "buckets": [
          {
            "bucket_start": "2026-08-03T11:05:00Z", "bucket_end": "2026-08-03T11:06:00Z",
            "occurrence_count": 1
          }
        ]
      },
      "distributions": [
        {
          "dimension": "release",
          "distinct_value_count": 1,
          "values": [
            {
              "value": "checkout@1.2.3", "version": null, "occurrence_count": 1,
              "share_basis_points": 10000
            }
          ],
          "other_occurrence_count": 0
        },
        {
          "dimension": "environment",
          "distinct_value_count": 1,
          "values": [
            {
              "value": "production", "version": null, "occurrence_count": 1,
              "share_basis_points": 10000
            }
          ],
          "other_occurrence_count": 0
        },
        {
          "dimension": "service",
          "distinct_value_count": 1,
          "values": [
            {
              "value": "checkout-api", "version": null, "occurrence_count": 1,
              "share_basis_points": 10000
            }
          ],
          "other_occurrence_count": 0
        },
        {
          "dimension": "sdk",
          "distinct_value_count": 1,
          "values": [
            {
              "value": "@logbrew/node", "version": "0.1.11", "occurrence_count": 1,
              "share_basis_points": 10000
            }
          ],
          "other_occurrence_count": 0
        }
      ],
      "limitations": []
    },
    "grouping": {"strategy": "sdk_fingerprint", "components": ["sdk_fingerprint"], "stack": null},
    "cause": {
      "status": "evidence_only",
      "summary": null,
      "provenance": null,
      "signals": ["handled_exception", "error_trace_span"]
    },
    "fix": {
      "status": "observed_frame",
      "location": {
        "component": null, "module": null, "function": "cartTotal", "file": "src/cart.ts",
        "line": 42, "column": 17, "in_app": null
      },
      "provenance": "backend_observed"
    },
    "source_locator": {
      "status": "not_found",
      "repository_provider": null,
      "repository_full_name": null,
      "component_path": null,
      "revision": null,
      "revision_source": null,
      "repository_relative_file": null,
      "evidence": {
        "status": "partial",
        "captured_fields": ["source.service"],
        "missing_fields": ["source.component"],
        "redacted_fields": [],
        "truncated_fields": []
      }
    },
    "reproduction": {
      "status": "insufficient_evidence",
      "baseline_occurrence_id": "22222222-2222-4222-8222-222222222222",
      "evidence": {
        "status": "partial",
        "captured_fields": [
          "reproduction.baseline_occurrence", "reproduction.code_location",
          "reproduction.expected_failure"
        ],
        "missing_fields": ["reproduction.trigger"],
        "redacted_fields": [],
        "truncated_fields": []
      }
    },
    "impact": {
      "occurrence_count": 1,
      "first_seen_at": "2026-08-03T11:05:00Z",
      "last_seen_at": "2026-08-03T11:05:00Z",
      "affected_users": null,
      "user_impact": {
        "status": "not_captured",
        "known_affected_users": null,
        "count_method": "unavailable",
        "coverage": {
          "retained_occurrences": 1, "indexed_occurrences": 1,
          "historical_unindexed_occurrences": 0, "identified_user_occurrences": 0,
          "anonymous_subject_occurrences": 0, "missing_subject_occurrences": 1,
          "privacy_filtered_subject_occurrences": 0, "index_coverage_basis_points": 10000,
          "identified_user_coverage_basis_points": 0
        },
        "limitations": ["missing_subject_context"]
      },
      "reported": null
    },
    "correlations": {
      "trace": {
        "status": "available",
        "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
        "summary": {
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
          "span_count": 1,
          "error_span_count": 1,
          "service_count": 1,
          "project_count": 1,
          "started_at": "2026-08-03T11:04:59.950Z",
          "duration_ms": 180,
          "root_span": {
            "span_id": "00f067aa0ba902b7", "parent_span_id": null, "name": "POST /checkout",
            "operation": "http.server", "status": "error",
            "started_at": "2026-08-03T11:04:59.950Z", "duration_ms": 180,
            "service_name": "checkout-api"
          },
          "slowest_child_span": null,
          "slowest_path": [],
          "error_spans": [
            {
              "span_id": "00f067aa0ba902b7", "parent_span_id": null, "name": "POST /checkout",
              "operation": "http.server", "status": "error",
              "started_at": "2026-08-03T11:04:59.950Z", "duration_ms": 180,
              "service_name": "checkout-api"
            }
          ],
          "services": [
            {
              "service_name": "checkout-api", "span_count": 1, "error_span_count": 1,
              "max_duration_ms": 180
            }
          ],
          "releases": ["checkout@1.2.3"],
          "environments": ["production"]
        },
        "truncated": false
      },
      "logs": {"status": "not_found", "items": [], "truncated": false},
      "actions": {"status": "not_found", "items": [], "truncated": false},
      "metrics": {"status": "not_found", "items": [], "truncated": false},
      "related_issues": {"status": "not_found", "items": [], "truncated": false},
      "release": {
        "release": "checkout@1.2.3", "environment": "production",
        "service_name": "checkout-api", "deployment_status": "not_found"
      }
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "context", "deployment.lookup", "exception", "exception.mechanism", "exception_chain",
        "exception_chain.stack_frames", "grouping", "grouping.components",
        "grouping.strategy", "grouping.strategy_details", "lifecycle.regression",
        "lifecycle.status_history", "likely_fix_area", "occurrence.boundaries",
        "occurrence.distribution.environment", "occurrence.distribution.release",
        "occurrence.distribution.sdk", "occurrence.distribution.service",
        "occurrence.recommendation", "occurrence.selection", "occurrence.trend", "release",
        "sdk", "source_locator", "stack_frames", "trace"
      ],
      "missing_fields": [
        "affected_users", "breadcrumbs", "deployment", "impact", "likely_root_cause",
        "related_actions", "related_issues", "related_logs", "related_metrics", "request",
        "source_locator.complete"
      ],
      "redacted_fields": ["exception_chain.messages"],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "inspect_code_location", "target": "source_code",
        "reason": "likely_fix_location_available"
      },
      {
        "priority": 2, "code": "inspect_trace", "target": "trace_summary",
        "reason": "linked_trace_available"
      },
      {
        "priority": 3, "code": "compare_release", "target": "release_summary",
        "reason": "release_identity_available"
      },
      {
        "priority": 4, "code": "improve_capture", "target": "sdk_configuration",
        "reason": "evidence_incomplete"
      }
    ]
  }
  ```
</Accordion>

| Trường | Phiên bản | Ý nghĩa |
| - | - | - |
| `subject` | 1 | Vấn đề đã gộp nhóm. `first_seen_at`, `last_seen_at` và `occurrence_count` mô tả cả nhóm. |
| `event` | 1 | Lần xảy ra được chọn: SDK, `context`, `exception`, `stack_frames` và `breadcrumbs`. Ở phiên bản 1, giá trị là `null` khi không đọc được lần xảy ra gần nhất nào. |
| `cause` | 1 | `status` là `reported_hypothesis`, `evidence_only` hoặc `unknown`. `signals` liệt kê các tín hiệu quan sát được. |
| `fix` | 1 | Một vị trí trong mã. `status` là `reported_location`, `observed_application_frame`, `observed_frame`, `observed_underlying_exception_frame` hoặc `unknown`. |
| `impact` | 1 | Số lần xảy ra và `user_impact`. `reported` chứa tác động được báo cáo bởi ứng dụng, hoặc `null`. |
| `correlations` | 1 | `trace`, `logs`, `actions`, `metrics` và `release`. |
| `occurrence_selection` | 2 | Tham số chọn đã yêu cầu, lý do, và bản tóm tắt của các lần xảy ra được chọn, đầu tiên, gần nhất và được đề xuất. |
| `lifecycle` | 3 | `persisted_status`, `effective_status`, hoạt động trạng thái và `regression`. `effective_status` có thể là `regressed`. |
| `occurrence_analysis` | 4 | Xu hướng lần xảy ra và phân bố theo bản phát hành, môi trường, dịch vụ và SDK. |
| `event.exception_chain` | 5 | Tối đa 8 ngoại lệ liên kết với nhau. `relationship` là `reported`, `cause`, `context`, `aggregate_member` hoặc `suppressed`. |
| `event.request` | 6 | `method`, `route_template` và `response_status_code`. Khóa này không có khi không ghi nhận được yêu cầu nào. |
| `grouping` | 7 | `strategy` nhóm, các `components` của nó và cách dùng khung ngăn xếp (stack frame). |
| `correlations.release.deployment_status` | 8 | Trạng thái tra cứu lần triển khai. `deployment`, `time_since_deployment_ms` và `deployment_causality` chỉ xuất hiện khi tìm thấy lần triển khai. |
| `correlations.related_issues` | 9 | Các vấn đề khác trên cùng trace. |
| `source_locator` | 10 | Repository, thành phần, revision và tệp theo đường dẫn tương đối trong repository khi LogBrew liên kết được. |
| `reproduction` | 11 | `status` là `ready`, `partial` hoặc `insufficient_evidence`. |
| Mã `verify_correction` trong `next_actions` | 12 | Xuất hiện khi `reproduction.status` là `ready`. |
| `impact.user_impact.count_method` | 13 | Báo số đếm riêng biệt ước tính là `approximate_distinct`. Các phiên bản trước dùng tên giá trị cũ hơn. `unavailable` nghĩa là không có số đếm. |

Khóa của phiên bản sau không có trong phiên bản trước. Không hiểu khóa bị thiếu
là `null`.

`subject.status` và các trạng thái trong `lifecycle` báo vấn đề đã lưu trữ là
`ignored`. Phản hồi danh sách và chi tiết vấn đề dùng `archived` từ phiên bản
phản hồi 2 trở đi.

Giới hạn của vấn đề: phần đề xuất đọc tối đa 50 lần xảy ra được giữ lại. Xu
hướng có tối đa 30 khoảng gộp. Mỗi phân bố trả về tối đa 10 giá trị. Một dấu
vết ngăn xếp (stack trace) có tối đa 32 khung.

#### Lỗi yêu cầu điều tra vấn đề

Chỉ dùng `selection` hoặc `occurrence_id`. Không gửi cả hai, kể cả khi chúng
chọn cùng một lần xảy ra:

```json theme={null}
{
  "error": "selection and occurrence_id are mutually exclusive",
  "code": "validation_failed",
  "next": "use response_version=2 through 13 with at most one of selection=first|latest|recommended or an exact occurrence_id copied from GET /api/telemetry/issues/{issue_id}/events",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

| HTTP | `error` | Nguyên nhân | Cách khắc phục |
| - | - | - | - |
| `422` | `selection and occurrence_id are mutually exclusive` | Yêu cầu có cả hai tham số chọn. | Chỉ giữ một tham số chọn. |
| `422` | `issue occurrence selection requires response_version=2 through 13` | Yêu cầu có tham số chọn nhưng dùng phiên bản 1 hoặc không có phiên bản. | Gửi `response_version=13`. Giữ nguyên tham số chọn. |
| `422` | `issue investigation response_version must be 1 through 13` | Phiên bản nằm ngoài phạm vi cho phép. | Gửi phiên bản được hỗ trợ. |
| `422` | `invalid query parameters` | Tham số không xác định, UUID không hợp lệ, phiên bản không phải số nguyên hoặc giá trị `selection` không xác định. | Sửa [truy vấn](/vi/reference/api-errors#invalid-query-parameters). |
| `404` | `issue occurrence not found` | Lần xảy ra không nằm trong lịch sử được giữ lại của nhóm này. | Sao chép ID lần xảy ra từ các sự kiện của chính vấn đề này. Không tự chuyển sang `latest` hay `recommended` khi chưa được chấp thuận. |
| `404` | `issue not found` | Không dự án nào đọc được có vấn đề này. | Kiểm tra tài khoản và UUID của vấn đề. Không gửi UUID của lần xảy ra làm ID vấn đề. |

Lần xảy ra không tồn tại không có nghĩa là vấn đề không tồn tại. `404` không cho
biết liệu tài khoản khác có đọc được vấn đề hay không.

### Phản hồi điều tra trace

Dùng `GET /api/telemetry/traces/{trace_id}/investigation` để đọc một trace cùng
đường đi lỗi, đường đi chậm nhất và các tín hiệu liên quan. Các tham số truy vấn là
`response_version`, `project_id`, `release` và `environment`. Tất cả đều không
bắt buộc. Yêu cầu phiên bản 3:

```bash theme={null}
curl --fail-with-body -sS -G \
  "https://api.logbrew.co/api/telemetry/traces/$TRACE_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN" \
  --data-urlencode "response_version=3"
```

Phiên bản 2 thêm `cause` và `fix` vào mỗi vấn đề liên quan. Phiên bản 3 thêm
`span_id` vào các vấn đề, hành động và chỉ số liên quan khi đã ghi nhận.

<Accordion title="Ví dụ điều tra trace phiên bản 3">
  Phản hồi giả lập này có một span gốc phía máy chủ và một span phía client bị
  lỗi. Span lỗi cũng là span con chậm nhất. Các span không có ngữ cảnh có cấu
  trúc, nên `spans.context` không có.

  ```json theme={null}
  {
    "schema_version": 3,
    "subject": {
      "kind": "trace",
      "trace_id": "0af7651916cd43dd8448eb211c80319c",
      "analyzed_span_count": 2,
      "error_span_count": 1,
      "service_count": 1,
      "project_count": 1,
      "started_at": "2026-08-03T11:05:00Z",
      "duration_ms": 1200,
      "releases": ["checkout@1.2.3"],
      "environments": ["production"]
    },
    "analysis": {
      "status": "errors_observed",
      "causality": "evidence_only",
      "root_span": {
        "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
        "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
        "duration_ms": 1200, "service_name": "checkout-api"
      },
      "first_error_span": {
        "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
        "name": "POST /v1/charges", "operation": "http.client", "status": "error",
        "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
        "service_name": "checkout-api"
      },
      "first_error_path": [
        {
          "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
          "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200, "service_name": "checkout-api"
        },
        {
          "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
          "name": "POST /v1/charges", "operation": "http.client", "status": "error",
          "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
          "service_name": "checkout-api"
        }
      ],
      "bottleneck_span": {
        "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
        "name": "POST /v1/charges", "operation": "http.client", "status": "error",
        "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
        "service_name": "checkout-api"
      },
      "bottleneck_path": [
        {
          "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
          "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200, "service_name": "checkout-api"
        },
        {
          "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
          "name": "POST /v1/charges", "operation": "http.client", "status": "error",
          "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
          "service_name": "checkout-api"
        }
      ]
    },
    "spans": {
      "items": [
        {
          "id": "33333333-3333-4333-8333-333333333333",
          "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
          "span_id": "b7ad6b7169203331",
          "parent_span_id": null,
          "name": "POST /checkout",
          "operation": "http.server",
          "status": "ok",
          "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200,
          "service_name": "checkout-api",
          "environment": "production",
          "release": "checkout@1.2.3",
          "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
          "context": null,
          "roles": ["root", "error_path", "bottleneck_path", "slow"]
        },
        {
          "id": "44444444-4444-4444-8444-444444444444",
          "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
          "span_id": "53995c3f42cd8ad8",
          "parent_span_id": "b7ad6b7169203331",
          "name": "POST /v1/charges",
          "operation": "http.client",
          "status": "error",
          "started_at": "2026-08-03T11:05:00.100Z",
          "duration_ms": 900,
          "service_name": "checkout-api",
          "environment": "production",
          "release": "checkout@1.2.3",
          "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
          "context": null,
          "roles": ["first_error", "error_path", "bottleneck", "bottleneck_path", "error", "slow"]
        }
      ],
      "truncated": false
    },
    "correlations": {
      "window": {
        "since": "2026-08-03T11:00:00Z",
        "until": "2026-08-03T11:10:01.200Z",
        "scopes": [
          {
            "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "environment": "production",
            "release": "checkout@1.2.3"
          }
        ],
        "truncated": false
      },
      "issues": {"status": "not_found", "items": [], "truncated": false},
      "logs": {
        "status": "available",
        "items": [
          {
            "id": "55555555-5555-4555-8555-555555555555",
            "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "severity": "error",
            "source": "payments", "message": "Charge request failed",
            "occurred_at": "2026-08-03T11:05:01Z", "service_name": "checkout-api",
            "span_id": "53995c3f42cd8ad8", "environment": "production",
            "release": "checkout@1.2.3"
          }
        ],
        "truncated": false
      },
      "actions": {"status": "not_found", "items": [], "truncated": false},
      "metrics": {"status": "not_found", "items": [], "truncated": false}
    },
    "timeline": {
      "items": [
        {
          "id": "b7ad6b7169203331", "kind": "span", "occurred_at": "2026-08-03T11:05:00Z",
          "name": "POST /checkout", "service_name": "checkout-api",
          "span_id": "b7ad6b7169203331", "severity": null, "status": "ok",
          "duration_ms": 1200
        },
        {
          "id": "53995c3f42cd8ad8", "kind": "span", "occurred_at": "2026-08-03T11:05:00.100Z",
          "name": "POST /v1/charges", "service_name": "checkout-api",
          "span_id": "53995c3f42cd8ad8", "severity": null, "status": "error",
          "duration_ms": 900
        },
        {
          "id": "55555555-5555-4555-8555-555555555555", "kind": "log",
          "occurred_at": "2026-08-03T11:05:01Z", "name": "Charge request failed",
          "service_name": "checkout-api", "span_id": "53995c3f42cd8ad8", "severity": "error",
          "status": null, "duration_ms": null
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "correlations.window", "related_actions", "related_issues", "related_logs",
        "related_metrics", "spans.sdk", "timeline", "trace.parentage", "trace.root",
        "trace.spans"
      ],
      "missing_fields": ["spans.context"],
      "redacted_fields": [],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "inspect_first_error_span", "target": "trace_span",
        "reason": "error_span_observed", "span_id": "53995c3f42cd8ad8", "issue_id": null
      },
      {
        "priority": 2, "code": "review_related_logs", "target": "telemetry_logs",
        "reason": "related_logs_available", "span_id": "53995c3f42cd8ad8", "issue_id": null
      },
      {
        "priority": 3, "code": "compare_release", "target": "release_summary",
        "reason": "release_identity_available", "span_id": null, "issue_id": null
      },
      {
        "priority": 4, "code": "improve_capture", "target": "sdk_configuration",
        "reason": "evidence_incomplete", "span_id": null, "issue_id": null
      }
    ]
  }
  ```
</Accordion>

| Trường | Ý nghĩa |
| - | - |
| `subject` | Tổng số liệu của trace, tính từ các span đã phân tích. |
| `analysis.status` | `errors_observed`, `latency_focus` hoặc `no_error_observed`. |
| `analysis.first_error_path` | Chuỗi span cha đã biết, từ span gốc đến span lỗi sớm nhất. |
| `analysis.bottleneck_path` | Chuỗi span cha đã biết dẫn đến span con chậm nhất. |
| `spans.items[].roles` | Lý do span có trong bản xem trước: `root`, `first_error`, `error_path`, `bottleneck`, `bottleneck_path`, `error` hoặc `slow`. |
| `correlations.window` | Khoảng thời gian và các phạm vi triển khai dùng cho các lượt đọc liên quan. |
| `correlations.issues`, `logs`, `actions`, `metrics` | Các tín hiệu có cùng trace ID trong khoảng thời gian đó. |

`trace.parentage` không có khi một span trỏ đến span cha mà LogBrew không giữ
lại. Bản xem trước span có tối đa 64 span. Mỗi đường đi phân tích có tối đa 64
span. Các lượt đọc liên quan dùng tối đa 8 phạm vi triển khai.

Hành động tiếp theo có target `trace_span` nêu một `span_id` trong gói này. Để
đọc span đó, gửi route span kèm `project_id`, `environment` và `release` của
span.

### Phản hồi điều tra span

Dùng `GET /api/telemetry/traces/{trace_id}/spans/{span_id}/investigation` để
đọc một thao tác trong trace. Gửi `project_id`, `environment` và `release`. Cả
ba đều bắt buộc. Sao chép chúng từ span đã chọn. Không gửi `id` của dòng span
làm `span_id`.

```bash theme={null}
curl --fail-with-body -sS -G \
  "https://api.logbrew.co/api/telemetry/traces/$TRACE_ID/spans/$SPAN_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN" \
  --data-urlencode "project_id=$PROJECT_ID" \
  --data-urlencode "environment=production" \
  --data-urlencode "release=checkout@1.2.3"
```

<Accordion title="Ví dụ điều tra span">
  Phản hồi giả lập này mô tả span phía client bị lỗi trong ví dụ trace ở trên.
  Một log lỗi có cùng span ID. Span chạy lâu hơn phân vị thứ 95 ước tính của các
  span cùng loại được giữ lại.

  ```json theme={null}
  {
    "schema_version": 1,
    "subject": {
      "kind": "span",
      "id": "44444444-4444-4444-8444-444444444444",
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "trace_id": "0af7651916cd43dd8448eb211c80319c",
      "span_id": "53995c3f42cd8ad8",
      "parent_span_id": "b7ad6b7169203331",
      "name": "POST /v1/charges",
      "operation": "http.client",
      "status": "error",
      "started_at": "2026-08-03T11:05:00.100Z",
      "duration_ms": 900,
      "service_name": "checkout-api",
      "environment": "production",
      "release": "checkout@1.2.3",
      "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
      "content_trust": "untrusted_telemetry"
    },
    "context": null,
    "payload": {
      "metadata": {
        "values": {"provider": "example-pay"},
        "included_leaf_count": 1,
        "redacted": false,
        "truncated": false
      },
      "events": [],
      "links": [],
      "included_leaf_count": 1,
      "redacted": false,
      "truncated": false
    },
    "analysis": {
      "status": "error_evidence",
      "causality": "evidence_only",
      "observations": ["subject_error", "exact_span_error_log", "subject_at_or_above_peer_p95"]
    },
    "topology": {
      "status": "available",
      "root": {
        "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
        "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
        "duration_ms": 1200, "service_name": "checkout-api"
      },
      "parent": {
        "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
        "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
        "duration_ms": 1200, "service_name": "checkout-api"
      },
      "ancestors": [
        {
          "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
          "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200, "service_name": "checkout-api"
        }
      ],
      "children": [],
      "descendant_count": 0,
      "cross_service_edges": [],
      "parent_chain_status": "complete",
      "truncated": false
    },
    "baseline": {
      "status": "available",
      "since": "2026-08-02T11:05:00.100Z",
      "until": "2026-08-03T11:05:00.100Z",
      "dimensions": {
        "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "environment": "production",
        "release": "checkout@1.2.3", "service_name": "checkout-api",
        "operation": "http.client", "name": "POST /v1/charges"
      },
      "retained_peer_count": 40,
      "error_peer_count": 2,
      "error_rate_basis_points": 500,
      "p50_duration_ms": 310.0,
      "p95_duration_ms": 620.0,
      "p99_duration_ms": 940.0,
      "subject_percentile_basis_points": 9500,
      "method": "approximate_t_digest",
      "limitations": [
        "retained_telemetry_only", "sampling_may_apply", "approximate_percentiles",
        "same_release_only"
      ]
    },
    "correlations": {
      "trace": {
        "status": "available",
        "summary": {
          "trace_id": "0af7651916cd43dd8448eb211c80319c",
          "span_count": 2,
          "error_span_count": 1,
          "service_count": 1,
          "project_count": 1,
          "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200,
          "root_span": {
            "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
            "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
            "duration_ms": 1200, "service_name": "checkout-api"
          },
          "slowest_child_span": {
            "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
            "name": "POST /v1/charges", "operation": "http.client", "status": "error",
            "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
            "service_name": "checkout-api"
          },
          "slowest_path": [
            {
              "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
              "operation": "http.server", "status": "ok",
              "started_at": "2026-08-03T11:05:00Z", "duration_ms": 1200,
              "service_name": "checkout-api"
            },
            {
              "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
              "name": "POST /v1/charges", "operation": "http.client", "status": "error",
              "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
              "service_name": "checkout-api"
            }
          ],
          "error_spans": [
            {
              "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
              "name": "POST /v1/charges", "operation": "http.client", "status": "error",
              "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
              "service_name": "checkout-api"
            }
          ],
          "services": [
            {
              "service_name": "checkout-api", "span_count": 2, "error_span_count": 1,
              "max_duration_ms": 1200
            }
          ],
          "releases": ["checkout@1.2.3"],
          "environments": ["production"]
        },
        "truncated": false
      },
      "issues": {"status": "not_found", "items": [], "truncated": false},
      "logs": {
        "status": "available",
        "items": [
          {
            "id": "55555555-5555-4555-8555-555555555555",
            "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "severity": "error",
            "source": "payments", "message": "Charge request failed",
            "occurred_at": "2026-08-03T11:05:01Z", "service_name": "checkout-api",
            "span_id": "53995c3f42cd8ad8", "environment": "production",
            "release": "checkout@1.2.3"
          }
        ],
        "truncated": false
      },
      "actions": {"status": "not_found", "items": [], "truncated": false},
      "metrics": {"status": "not_found", "items": [], "truncated": false},
      "release": {
        "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "release": "checkout@1.2.3",
        "environment": "production", "service_name": "checkout-api"
      }
    },
    "timeline": {
      "items": [
        {
          "id": "53995c3f42cd8ad8:start", "kind": "span_start",
          "occurred_at": "2026-08-03T11:05:00.100Z", "offset_ms": 0,
          "name": "POST /v1/charges", "service_name": "checkout-api",
          "span_id": "53995c3f42cd8ad8", "severity": null, "status": "error",
          "duration_ms": 900
        },
        {
          "id": "55555555-5555-4555-8555-555555555555", "kind": "log",
          "occurred_at": "2026-08-03T11:05:01Z", "offset_ms": 900, "name": "payments",
          "service_name": "checkout-api", "span_id": "53995c3f42cd8ad8", "severity": "error",
          "status": null, "duration_ms": null
        },
        {
          "id": "53995c3f42cd8ad8:end", "kind": "span_end",
          "occurred_at": "2026-08-03T11:05:01Z", "offset_ms": 900, "name": "POST /v1/charges",
          "service_name": "checkout-api", "span_id": "53995c3f42cd8ad8", "severity": null,
          "status": "error", "duration_ms": 900
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "attributes.metadata.provider", "baseline", "correlations.actions",
        "correlations.issues", "correlations.logs", "correlations.metrics",
        "correlations.trace", "subject.content_trust", "subject.deployment",
        "subject.identity", "subject.sdk", "subject.timing", "topology"
      ],
      "missing_fields": ["context"],
      "redacted_fields": [],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "inspect_parent_span", "target": "span_investigation",
        "reason": "parent_context_available", "span_id": "b7ad6b7169203331", "issue_id": null
      },
      {
        "priority": 2, "code": "review_exact_span_logs", "target": "telemetry_logs",
        "reason": "exact_span_logs_available", "span_id": "53995c3f42cd8ad8",
        "issue_id": null
      },
      {
        "priority": 3, "code": "inspect_trace", "target": "trace_investigation",
        "reason": "trace_context_available", "span_id": "53995c3f42cd8ad8", "issue_id": null
      },
      {
        "priority": 4, "code": "compare_peer_baseline", "target": "peer_baseline",
        "reason": "subject_latency_elevated", "span_id": "53995c3f42cd8ad8", "issue_id": null
      },
      {
        "priority": 5, "code": "compare_release", "target": "release_investigation",
        "reason": "exact_release_available", "span_id": null, "issue_id": null
      },
      {
        "priority": 6, "code": "improve_capture", "target": "sdk_capture",
        "reason": "capture_incomplete", "span_id": "53995c3f42cd8ad8", "issue_id": null
      }
    ]
  }
  ```
</Accordion>

| Trường | Ý nghĩa |
| - | - |
| `payload` | `metadata` của span, tối đa 8 `events` và tối đa 8 `links`. Chúng dùng chung hạn mức 64 giá trị. |
| `analysis.observations` | `subject_error`, `child_error`, `exact_span_error_log`, `related_issue`, `subject_at_or_above_peer_p95` hoặc `subject_at_or_above_peer_p99`. |
| `topology` | `root`, `parent`, `ancestors`, các `children` trực tiếp, `descendant_count` và `cross_service_edges`. |
| `topology.parent_chain_status` | `root`, `complete`, `missing`, `cycle`, `truncated` hoặc `unavailable`. |
| `baseline` | Các span trước đó có cùng dự án, môi trường, bản phát hành, dịch vụ, thao tác và tên. |
| `correlations.logs` | Các log có cùng trace ID và span ID. |
| `correlations.issues`, `actions`, `metrics` | Các tín hiệu có cùng trace ID trong cùng dự án, môi trường và bản phát hành. |
| `timeline[].offset_ms` | Số mili giây tính từ lúc span bắt đầu. Giá trị âm nghĩa là sớm hơn span. |

Mốc so sánh đọc 24 giờ trước lúc span bắt đầu. `since` được tính vào khoảng thời
gian, còn `until` thì không. `error_rate_basis_points: 500` nghĩa là 5%.
`subject_percentile_basis_points: 9500` nghĩa là 95% các span cùng loại được giữ
lại chạy không lâu hơn span này. Các phân vị là giá trị ước tính. Giữ
`baseline.limitations` đi kèm các giá trị. Mốc so sánh `not_found` không có
span cùng loại nào được giữ lại. Mốc so sánh `unavailable` là lượt đọc thất bại,
không phải số đếm bằng 0.

`parent_chain_status: "complete"` nghĩa là chuỗi span được giữ lại đi đến một
span gốc. Điều này không chứng minh LogBrew đã giữ lại mọi span của yêu cầu.
Cấu trúc liên kết trả về tối đa 64 span tổ tiên, 50 span con trực tiếp và 50
cạnh nối giữa các dịch vụ.

| HTTP | `error` | Cách khắc phục |
| - | - | - |
| `422` | `trace_id must be a non-zero 32-character hexadecimal value` | Sao chép `trace_id` từ một phản hồi trace của LogBrew. |
| `422` | `span_id must be a non-zero 16-character hexadecimal value` | Sao chép `span_id` từ một phản hồi trace của LogBrew. |
| `422` | `environment and release must be non-empty exact span scope values` | Sao chép phạm vi từ span đã chọn. |
| `422` | `invalid query parameters` | Gửi `project_id`, `environment` và `release`, không gửi tham số nào khác. |
| `404` | `span not found` | Kiểm tra các ID, dự án, môi trường và bản phát hành. |

### Phản hồi điều tra log

Dùng `GET /api/logs/{log_id}/investigation` để đọc một log và bằng chứng liên
quan. Route này không có tham số truy vấn. Sao chép ID log từ một danh sách log.

```bash theme={null}
curl --fail-with-body -sS \
  "https://api.logbrew.co/api/logs/$LOG_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN"
```

Lượt đọc có thể trả về bằng chứng nằm ngoài bộ lọc của danh sách log. Các lượt
đọc liên quan dùng dự án, môi trường và bản phát hành của log, cùng 5 phút
trước và sau log. Các log lân cận cũng dùng cùng dịch vụ. Chúng không cần trace
ID. Các lượt đọc theo đúng trace cần trace ID của log và có thể bao gồm dịch vụ
khác. Bản tóm tắt trace dùng cùng trace ID và phạm vi, không có giới hạn khoảng
thời gian.

<Accordion title="Ví dụ điều tra log">
  Phản hồi giả lập này có một log cảnh báo không có ngữ cảnh trace và một log lân
  cận. Phản hồi không dựng liên kết trace từ dấu thời gian.

  ```json theme={null}
  {
    "schema_version": 1,
    "subject": {
      "kind": "log",
      "id": "66666666-6666-4666-8666-666666666666",
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "severity": "warning",
      "content_trust": "untrusted_telemetry",
      "source": "inventory",
      "message": "Inventory update delayed",
      "occurred_at": "2026-08-03T12:00:00Z",
      "service_name": "checkout-api",
      "environment": "production",
      "release": "checkout@1.2.3",
      "sdk": {"name": "@logbrew/node", "version": "0.1.11"}
    },
    "context": null,
    "attributes": {
      "values": {"retry_count": 2},
      "included_leaf_count": 1,
      "redacted": false,
      "truncated": false
    },
    "analysis": {
      "status": "warning_evidence",
      "causality": "evidence_only",
      "observations": ["subject_warning"]
    },
    "correlations": {
      "trace": {
        "status": "not_linked", "trace_id": null, "span_id": null, "exact_span": null,
        "summary": null, "truncated": false
      },
      "issues": {"status": "not_linked", "items": [], "truncated": false},
      "trace_logs": {"status": "not_linked", "items": [], "truncated": false},
      "nearby_logs": {
        "status": "available",
        "items": [
          {
            "id": "77777777-7777-4777-8777-777777777777",
            "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "severity": "info",
            "source": "inventory", "message": "Inventory retry started",
            "occurred_at": "2026-08-03T11:59:58Z", "service_name": "checkout-api",
            "trace_id": null, "span_id": null, "environment": "production",
            "release": "checkout@1.2.3", "relationship": "nearby_scope"
          }
        ],
        "truncated": false
      },
      "actions": {"status": "not_linked", "items": [], "truncated": false},
      "metrics": {"status": "not_linked", "items": [], "truncated": false},
      "release": {
        "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "release": "checkout@1.2.3",
        "environment": "production", "service_name": "checkout-api"
      }
    },
    "timeline": {
      "items": [
        {
          "id": "77777777-7777-4777-8777-777777777777", "kind": "log",
          "relationship": "nearby_scope", "occurred_at": "2026-08-03T11:59:58Z",
          "name": "inventory", "message": "Inventory retry started",
          "service_name": "checkout-api", "span_id": null, "severity": "info", "status": null,
          "duration_ms": null
        },
        {
          "id": "66666666-6666-4666-8666-666666666666", "kind": "log",
          "relationship": "subject", "occurred_at": "2026-08-03T12:00:00Z",
          "name": "inventory", "message": "Inventory update delayed",
          "service_name": "checkout-api", "span_id": null, "severity": "warning",
          "status": null, "duration_ms": null
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "attributes", "attributes.retry_count", "correlations.nearby_logs",
        "correlations.release", "subject.content_trust", "subject.environment", "subject.id",
        "subject.message", "subject.occurred_at", "subject.project_id", "subject.release",
        "subject.sdk.name", "subject.sdk.version", "subject.service_name", "subject.severity",
        "subject.source", "timeline"
      ],
      "missing_fields": ["context", "correlations.trace.trace_id"],
      "redacted_fields": [],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "review_nearby_logs", "target": "telemetry_logs",
        "reason": "nearby_logs_available", "issue_id": null, "trace_id": null,
        "span_id": null
      },
      {
        "priority": 2, "code": "improve_capture", "target": "sdk_configuration",
        "reason": "evidence_incomplete", "issue_id": null, "trace_id": null, "span_id": null
      },
      {
        "priority": 3, "code": "compare_release", "target": "release_investigation",
        "reason": "release_identity_available", "issue_id": null, "trace_id": null,
        "span_id": null
      }
    ]
  }
  ```
</Accordion>

| Trường | Ý nghĩa |
| - | - |
| `attributes` | Các thuộc tính có cấu trúc đã được giới hạn. `values` không chứa `context`, vốn nằm trong trường `context` ở cấp cao nhất. |
| `analysis.status` | `critical_evidence`, `error_evidence`, `warning_evidence` hoặc `no_failure_observed`. |
| `correlations.trace` | Trace ID, span ID, `exact_span` và `summary` của trace. |
| `correlations.trace_logs` | Các log có cùng trace ID. `relationship` là `exact_trace`. |
| `correlations.nearby_logs` | Các log cùng dịch vụ trong khoảng thời gian. `relationship` là `nearby_scope`. Không bao gồm chủ thể và các log cùng trace. |
| `correlations.issues`, `actions`, `metrics` | Các tín hiệu có cùng trace ID. |
| `correlations.release` | Phạm vi bản phát hành dành cho điều tra bản phát hành. Trường này không chứa phép so sánh. |
| `timeline[].relationship` | `subject`, `exact_span`, `exact_trace` hoặc `nearby_scope`. |

Trace ID có thể có mặt khi trạng thái trace là `not_found` hoặc
`unavailable`. Bản tóm tắt trace khả dụng không bảo đảm có `exact_span`.

### Phản hồi điều tra hành động

Dùng `GET /api/telemetry/actions/{action_id}/investigation` để đọc một hành động
sản phẩm, trạng thái được báo cáo của nó và bằng chứng liên quan. Route này
không có tham số truy vấn. Các lượt đọc liên quan dùng cùng khoảng thời gian và
phạm vi như điều tra log.

```bash theme={null}
curl --fail-with-body -sS \
  "https://api.logbrew.co/api/telemetry/actions/$ACTION_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN"
```

`correlations`, `timeline` và `next_actions` dùng cấu trúc của điều tra log.
Các hành động liên quan không bao gồm hành động chủ thể.

<Accordion title="Ví dụ điều tra hành động">
  Phản hồi giả lập này mô tả một hành động thanh toán thất bại của một người dùng
  đã đăng nhập. Hành động không có trace ID.

  ```json theme={null}
  {
    "schema_version": 1,
    "subject": {
      "kind": "action",
      "id": "14141414-1414-4141-8141-141414141414",
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "name": "checkout.submit",
      "status": "failure",
      "content_trust": "untrusted_telemetry",
      "occurred_at": "2026-08-03T11:05:00Z",
      "service_name": "checkout-api",
      "environment": "production",
      "release": "checkout@1.2.3",
      "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
      "subject_classification": "user",
      "session_captured": true
    },
    "context": null,
    "properties": {
      "values": {"plan": "team", "step": "payment"},
      "included_leaf_count": 2,
      "redacted": false,
      "truncated": false
    },
    "analysis": {
      "status": "subject_failure",
      "causality": "evidence_only",
      "observations": ["subject_failure"]
    },
    "correlations": {
      "trace": {
        "status": "not_linked", "trace_id": null, "span_id": null, "exact_span": null,
        "summary": null, "truncated": false
      },
      "issues": {"status": "not_linked", "items": [], "truncated": false},
      "trace_logs": {"status": "not_linked", "items": [], "truncated": false},
      "nearby_logs": {"status": "not_found", "items": [], "truncated": false},
      "actions": {"status": "not_linked", "items": [], "truncated": false},
      "metrics": {"status": "not_linked", "items": [], "truncated": false},
      "release": {
        "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "release": "checkout@1.2.3",
        "environment": "production", "service_name": "checkout-api"
      }
    },
    "timeline": {
      "items": [
        {
          "id": "14141414-1414-4141-8141-141414141414", "kind": "action",
          "relationship": "subject", "occurred_at": "2026-08-03T11:05:00Z",
          "name": "checkout.submit", "message": null, "service_name": "checkout-api",
          "span_id": null, "severity": null, "status": "failure", "duration_ms": null
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "correlations.nearby_logs", "correlations.release", "properties.metadata",
        "properties.metadata.plan", "properties.metadata.step", "subject.content_trust",
        "subject.environment", "subject.id", "subject.name", "subject.occurred_at",
        "subject.project_id", "subject.release", "subject.sdk.name", "subject.sdk.version",
        "subject.service_name", "subject.session_captured", "subject.status",
        "subject.subject_classification", "timeline"
      ],
      "missing_fields": ["context", "correlations.trace.trace_id"],
      "redacted_fields": ["subject.distinct_id", "subject.session_id"],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "inspect_analytics_paths", "target": "analytics_paths",
        "reason": "session_captured", "issue_id": null, "trace_id": null, "span_id": null
      },
      {
        "priority": 2, "code": "improve_capture", "target": "sdk_configuration",
        "reason": "evidence_incomplete", "issue_id": null, "trace_id": null, "span_id": null
      },
      {
        "priority": 3, "code": "compare_release", "target": "release_investigation",
        "reason": "release_identity_available", "issue_id": null, "trace_id": null,
        "span_id": null
      }
    ]
  }
  ```
</Accordion>

| Trường | Ý nghĩa |
| - | - |
| `subject.status` | `queued`, `running`, `success`, `failure`, hoặc `null` khi không ghi nhận được trạng thái nào được hỗ trợ. |
| `subject.subject_classification` | `user`, `anonymous`, `legacy_unknown`, `missing`, `historical_unindexed` hoặc `unsupported`. |
| `subject.session_captured` | Hành động có phiên hay không. Phản hồi không bao giờ trả về ID phiên. |
| `properties` | Object `metadata` đã được giới hạn của hành động. |
| `analysis.status` | `subject_failure`, `correlated_failure_evidence`, `in_progress`, `success_observed` hoặc `status_not_captured`. |

Phản hồi không bao giờ trả về định danh chủ thể hay định danh phiên. Biên nhận
bằng chứng luôn liệt kê `subject.distinct_id` là đã che, và cả
`subject.session_id` khi đã ghi nhận phiên. Vì vậy, mọi gói hành động đều là
`partial` và có `improve_capture`. Không gỡ các biện pháp bảo vệ quyền riêng tư
chỉ để đáp ứng gợi ý đó.

### Phản hồi điều tra chỉ số

Dùng `GET /api/telemetry/metrics/investigation` để đọc một tên chỉ số trong một
dự án và một khoảng thời gian. Phản hồi có chuỗi hiện tại, phép so sánh với
khoảng thời gian liền trước có cùng độ dài, mẫu gần nhất, các trace exemplar và
các lần triển khai đã hoàn tất. Phiên bản 2 thêm mô tả chỉ số lấy từ mẫu gần
nhất được giữ lại. Phiên bản 1 luôn báo
`description_status: "not_captured"`.

```bash theme={null}
curl --fail-with-body -sS -G \
  "https://api.logbrew.co/api/telemetry/metrics/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN" \
  --data-urlencode "project_id=$PROJECT_ID" \
  --data-urlencode "name=http.server.duration" \
  --data-urlencode "since=2026-08-02T12:00:00Z" \
  --data-urlencode "until=2026-08-03T12:00:00Z" \
  --data-urlencode "interval=5m" \
  --data-urlencode "group_by=service_name" \
  --data-urlencode "environment=production" \
  --data-urlencode "series_limit=12" \
  --data-urlencode "response_version=2"
```

`project_id`, `name` và `since` là bắt buộc. `since` được tính vào khoảng thời
gian, còn `until` thì không. `until` mặc định là thời điểm hiện tại. Phép so
sánh cũng đọc khoảng thời gian liền trước có cùng độ dài.

<Accordion title="Ví dụ điều tra chỉ số phiên bản 2">
  Histogram giả lập này có 5 mẫu trong hai khoảng gộp 5 phút. Khoảng gộp gần nhất
  có p95 là 48 ms. Khoảng gộp gần nhất của khoảng thời gian trước có p95 là 24 ms.

  ```json theme={null}
  {
    "schema_version": 2,
    "subject": {
      "kind": "metric", "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "name": "http.server.duration", "description_status": "captured",
      "description": "Duration of one completed server request."
    },
    "query": {
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "name": "http.server.duration",
      "since": "2026-08-02T12:00:00Z", "until": "2026-08-03T12:00:00Z", "interval": "5m",
      "interval_seconds": 300, "group_by": "service_name", "environment": "production",
      "series_limit": 12
    },
    "purpose": "Explains one metric's latest application-supplied description and bounded change, compares the immediately preceding equal window, exposes one privacy-bounded latest-sample capture context, exact trace/span exemplars, and nearby completed deployments, and keeps every correlation evidence-only rather than claiming an anomaly or root cause.",
    "content_trust": "untrusted_telemetry",
    "analysis": {
      "status": "change_observed",
      "causality": "evidence_only",
      "focus": {
        "comparison_index": 0, "selection": "largest_absolute_relative_change",
        "direction": "increased", "absolute_change": 24.0, "relative_change_percent": 100.0
      }
    },
    "coverage": {
      "samples": 5, "series": 1, "returned_series": 1, "points": 2,
      "expected_buckets_per_series": 288, "first_seen_at": "2026-08-03T11:00:10Z",
      "last_seen_at": "2026-08-03T11:09:50Z", "truncated": false
    },
    "series": [
      {
        "identity": {
          "kind": "histogram", "unit": "ms", "temporality": "delta",
          "group_by": "service_name", "group_value": "checkout-api"
        },
        "status": "ready",
        "aggregation": {
          "code": "distribution_p95",
          "description": "Primary value is the approximate p95 of raw observations in each bucket; p50, p99, range, average, count, and sum preserve distribution context."
        },
        "sample_count": 5,
        "points": [
          {
            "bucket_start": "2026-08-03T11:00:00Z", "bucket_end": "2026-08-03T11:05:00Z",
            "sample_count": 2, "value": 42.0, "min": 42.0, "max": 42.0, "average": 42.0,
            "sum": 84.0, "p50": 42.0, "p95": 42.0, "p99": 42.0, "trace_exemplars": []
          },
          {
            "bucket_start": "2026-08-03T11:05:00Z",
            "bucket_end": "2026-08-03T11:10:00Z",
            "sample_count": 3,
            "value": 48.0,
            "min": 48.0,
            "max": 48.0,
            "average": 48.0,
            "sum": 144.0,
            "p50": 48.0,
            "p95": 48.0,
            "p99": 48.0,
            "trace_exemplars": ["4bf92f3577b34da6a3ce929d0e0e4736"]
          }
        ]
      }
    ],
    "comparison": {
      "status": "available",
      "method": "adjacent_equal_window_latest_bucket",
      "previous_since": "2026-08-01T12:00:00Z",
      "previous_until": "2026-08-02T12:00:00Z",
      "items": [
        {
          "identity": {
            "kind": "histogram", "unit": "ms", "temporality": "delta",
            "group_by": "service_name", "group_value": "checkout-api"
          },
          "aggregation": "distribution_p95",
          "current": {
            "bucket_start": "2026-08-03T11:05:00Z", "bucket_end": "2026-08-03T11:10:00Z",
            "sample_count": 3, "value": 48.0
          },
          "previous": {
            "bucket_start": "2026-08-02T11:55:00Z", "bucket_end": "2026-08-02T12:00:00Z",
            "sample_count": 2, "value": 24.0
          },
          "direction": "increased",
          "absolute_change": 24.0,
          "relative_change_percent": 100.0
        }
      ],
      "truncated": false,
      "limitation": "Each item compares the latest non-empty semantic bucket in adjacent equal-length windows. It is an observed value change, not seasonality-aware anomaly detection or evidence that a deployment caused the change."
    },
    "latest_sample": {
      "status": "available",
      "sample": {
        "id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd",
        "kind": "histogram",
        "value": 48.0,
        "unit": "ms",
        "temporality": "delta",
        "occurred_at": "2026-08-03T11:09:50Z",
        "service_name": "checkout-api",
        "environment": "production",
        "release": "checkout@1.2.3",
        "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
        "span_id": "00f067aa0ba902b7",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "context": null,
        "metadata": {"values": {}, "included_leaf_count": 0, "redacted": false, "truncated": false}
      }
    },
    "exemplars": {
      "status": "available",
      "coverage": {
        "matching_samples": 5, "trace_linked_samples": 1, "span_linked_samples": 1,
        "returned_exemplars": 1
      },
      "items": [
        {
          "id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd",
          "value": 48.0,
          "occurred_at": "2026-08-03T11:09:50Z",
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
          "span_id": "00f067aa0ba902b7",
          "service_name": "checkout-api",
          "environment": "production",
          "release": "checkout@1.2.3",
          "sdk": {"name": "@logbrew/node", "version": "0.1.11"}
        }
      ],
      "truncated": false
    },
    "deployments": {
      "status": "available",
      "items": [
        {
          "deployment_id": "deploy-123", "release": "checkout@1.2.3",
          "environment": "production", "service_name": "checkout-api", "status": "succeeded",
          "started_at": "2026-08-03T11:02:00Z", "finished_at": "2026-08-03T11:03:00Z",
          "commit_sha": "0123456789abcdef"
        }
      ],
      "truncated": false
    },
    "timeline": {
      "items": [
        {
          "id": "deploy-123", "kind": "deployment_finished",
          "occurred_at": "2026-08-03T11:03:00Z", "value": null, "trace_id": null,
          "span_id": null, "release": "checkout@1.2.3", "service_name": "checkout-api"
        },
        {
          "id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd", "kind": "metric_exemplar",
          "occurred_at": "2026-08-03T11:09:50Z", "value": 48.0,
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "span_id": "00f067aa0ba902b7",
          "release": "checkout@1.2.3", "service_name": "checkout-api"
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "metric.current_window_coverage", "metric.deployment_overlays", "metric.description",
        "metric.identity", "metric.latest_sample", "metric.latest_sample.kind",
        "metric.latest_sample.occurred_at", "metric.latest_sample.scope",
        "metric.latest_sample.sdk.name", "metric.latest_sample.sdk.version",
        "metric.latest_sample.span_id", "metric.latest_sample.trace_id",
        "metric.latest_sample.value", "metric.prior_window_comparison", "metric.query_scope",
        "metric.series_semantics", "metric.span_exemplars", "metric.trace_exemplars"
      ],
      "missing_fields": ["metric.latest_sample.context", "metric.latest_sample.metadata"],
      "redacted_fields": [],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1,
        "code": "inspect_exact_span",
        "target": "span_investigation",
        "reason": "Inspect the exact span that emitted a retained metric exemplar, then review its failure, latency, log, issue, action, and trace evidence.",
        "context": {
          "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "span_id": "00f067aa0ba902b7",
          "environment": "production", "release": "checkout@1.2.3",
          "service_name": "checkout-api"
        }
      },
      {
        "priority": 2,
        "code": "review_deployment",
        "target": "release_investigation",
        "reason": "Review release-scoped telemetry for a completed deployment inside the compared evidence window without treating temporal proximity as causality.",
        "context": {
          "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "trace_id": null,
          "span_id": null, "environment": "production", "release": "checkout@1.2.3",
          "service_name": "checkout-api"
        }
      }
    ]
  }
  ```
</Accordion>

| Trường | Ý nghĩa |
| - | - |
| `subject.description_status` | `captured`, `not_captured` hoặc `unavailable`. |
| `query` | Truy vấn đã chuẩn hóa. `service_name`, `release` và `environment` chỉ xuất hiện khi được gửi. |
| `analysis.status` | `no_samples`, `change_observed`, `no_change_observed`, `baseline_not_found` hoặc `comparison_unavailable`. |
| `analysis.focus` | Mục so sánh có thay đổi tương đối lớn nhất, hoặc có thay đổi tuyệt đối lớn nhất khi không có thay đổi tương đối nào. `null` khi không có mục nào so sánh được. |
| `series[].aggregation.code` | `gauge_last`, `delta_sum`, `distribution_p95`, `raw_cumulative_last` hoặc `raw_last`. |
| `comparison.status` | `available`, `partial`, `not_found`, `unavailable` hoặc `no_current_samples`. |
| `comparison.items[]` | Khoảng gộp không trống gần nhất của mỗi khoảng thời gian, cho cùng một định danh chuỗi. |
| `latest_sample` | Mẫu thô gần nhất, kèm SDK, `context`, `metadata` và liên kết trace. |
| `exemplars` | Các mẫu thô có trace ID. `coverage` đếm các mẫu có liên kết. |
| `deployments` | Các lần triển khai đã hoàn tất, từ lúc bắt đầu khoảng thời gian trước đến `until`. |
| `next_actions[]` | `code`, `target`, `reason` dạng văn bản thuần và một phạm vi `context` cho lượt đọc tiếp theo. |

`relative_change_percent` bằng `(current - previous) / abs(previous) * 100`.
Giá trị này là `null` khi giá trị trước bằng 0 hoặc bị thiếu. `expected_buckets_per_series`
đếm số khoảng gộp có thể có, không phải số khoảng gộp có dữ liệu. Không vẽ
khoảng gộp trống thành giá trị 0. Một lần triển khai gần thời điểm thay đổi
không chứng minh rằng nó gây ra thay đổi đó.

Dự án mà tài khoản không đọc được trả về `200 OK` với
`analysis.status: "no_samples"`, không phải `404`. Kết quả trống không mô tả các
loại tín hiệu khác.

Giới hạn của chỉ số: khoảng thời gian tối đa 31 ngày. Mỗi chuỗi có tối đa 500
khoảng gộp. `series_limit` từ 1 đến 20, mặc định là 10. Phản hồi trả về tối đa
20 exemplar và 20 lần triển khai.

| HTTP | `error` | Cách khắc phục |
| - | - | - |
| `422` | `metric investigation response_version must be 1 or 2` | Bỏ `response_version` hoặc gửi `2`. |
| `422` | `metric series project_id is required` | Gửi một ID dự án đọc được. |
| `422` | `metric series name is required` | Sao chép tên từ danh sách chỉ số. |
| `422` | `metric series since is required` | Gửi một giá trị như `24h` hoặc một dấu thời gian RFC 3339. |
| `422` | `metric series range must not exceed 31 days` | Dùng khoảng thời gian ngắn hơn. |
| `422` | `metric series interval would exceed 500 buckets` | Dùng `interval=auto` hoặc độ dài khoảng gộp rộng hơn. |
| `422` | `metric series_limit must be between 1 and 20` | Gửi giá trị từ 1 đến 20. |

`interval` là `auto`, `1m`, `5m`, `15m`, `1h`, `6h` hoặc `1d`. `group_by` là
`none`, `service_name`, `release` hoặc `environment`. Các giá trị khác trả về
`422`.

### Lỗi điều tra

| HTTP | Route | `error` |
| - | - | - |
| `404` | Log | `log not found` |
| `404` | Hành động | `action not found` |
| `404` | Trace | `trace not found` |
| `422` | Trace | `trace investigation response_version must be 1, 2, or 3` |
| `400` | Log, hành động, vấn đề | `invalid URL path parameters` khi ID trong đường dẫn URL không phải UUID |
| `422` | Vấn đề, trace, span, chỉ số | `invalid query parameters` khi có tham số không xác định hoặc giá trị sai kiểu |

`404` nghĩa là không dự án nào đọc được có bản ghi đó. Mỗi route cũng trả về
`401` khi không có xác thực hợp lệ và `405` với phương thức khác `GET`.
Xem [Lỗi API](/vi/reference/api-errors) để biết các phản hồi
[không tìm thấy](/vi/reference/api-errors#resource-not-found),
[đường dẫn](/vi/reference/api-errors#invalid-path-value),
[xác thực](/vi/reference/api-errors#authentication-failure) và
[phương thức](/vi/reference/api-errors#unsupported-method).

Một lượt đọc bằng chứng không bắt buộc có thể thất bại bên trong phản hồi
`200 OK`. Khi đó, collection báo `unavailable`. Không hiển thị nó thành
`not_found` hay thành 0 bản ghi.

## <span id="severity-values">Giá trị mức độ nghiêm trọng</span>

Các giá trị mức độ nghiêm trọng hiển thị cho người dùng là `info`, `warning`,
`error` và `critical`. SDK và runtime có thể gửi các bí danh phổ biến như
`trace`, `debug`, `warn` hoặc `fatal`. Phản hồi REST và phản hồi trực tiếp luôn
trả về giá trị chuẩn. Ví dụ, LogBrew nhận `warn` làm đầu vào và trả về
`warning`. Khi tiếp nhận dữ liệu, LogBrew từ chối các giá trị mức độ nghiêm
trọng không xác định.

| Bí danh | Giá trị chuẩn |
| - | - |
| `trace`, `debug` | `info` |
| `warn` | `warning` |
| `fatal` | `critical` |

## <span id="severity-rule-responses">Phản hồi quy tắc mức độ nghiêm trọng</span>

Quy tắc mức độ nghiêm trọng thay đổi cách LogBrew hiển thị một log hoặc một vấn
đề. Quy tắc không thay đổi mức độ nghiêm trọng mà ứng dụng đã ghi nhận. Log và
vấn đề trả về object `triage`:

| Trường | Ý nghĩa |
| - | - |
| `effective_severity` | Mức độ nghiêm trọng cần hiển thị. Khi không có quy tắc, giá trị này bằng `severity`. |
| `ignored` | `true` khi quy tắc log bỏ qua log đó, hoặc khi vấn đề đã lưu trữ. |
| `rule_applied` | `true` khi có quy tắc mức độ nghiêm trọng hoặc trạng thái bỏ qua được áp dụng. `false` là giá trị mặc định, không phải dữ liệu bị thiếu. |

Dùng `triage.effective_severity` để hiển thị. Giữ `severity` là giá trị đã ghi
nhận. Theo mặc định, danh sách log không hiển thị các log bị bỏ qua. Gửi `status=ignored`
hoặc `status=all` trong `GET /api/logs` để lấy cả các log đó.

Tài khoản phải có quyền quản lý vấn đề trong dự án. Quyền đọc là chưa đủ. Nếu
không có quyền này, thao tác đổi quy tắc trả về `403` với `code: forbidden`.

### Đổi quy tắc log

`PUT /api/logs/{log_id}/triage-rule` đặt quy tắc cho log này và cho các log sau
có cùng chữ ký. Body cần cả `severity` lẫn `ignored`:

```bash theme={null}
curl --request PUT "https://api.logbrew.co/api/logs/$LOG_ID/triage-rule" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --header "Content-Type: application/json" \
  --data '{ "severity": "info", "ignored": true }'
```

Phản hồi `200 OK` chứa toàn bộ [log](#log-response). `severity` của log vẫn là
`warning`. `triage` của log thể hiện quy tắc:

```json theme={null}
{
  "severity": "warning",
  "triage": {
    "effective_severity": "info",
    "ignored": true,
    "rule_applied": true
  }
}
```

Đoạn trích này chỉ hiển thị các trường đã thay đổi. `severity` trong yêu cầu là
`source`, `info`, `warning`, `error` hoặc `critical`. `source` khôi phục mức độ
nghiêm trọng đã ghi nhận. Giá trị này không làm log bị bỏ qua hoạt động trở lại.
Để hiển thị lại log, gửi `"ignored": false`.

### Đổi quy tắc vấn đề

`PUT /api/telemetry/issues/{issue_id}/triage-rule` đặt mức độ nghiêm trọng hiển
thị của một vấn đề đã gộp nhóm và các lần xảy ra sau đó. Body chỉ nhận
`severity`:

```bash theme={null}
curl --request PUT "https://api.logbrew.co/api/telemetry/issues/$ISSUE_ID/triage-rule" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --header "Content-Type: application/json" \
  --data '{ "severity": "warning" }'
```

Phản hồi `200 OK` chứa toàn bộ [vấn đề](#issue-response) ở phiên bản 1.
`severity` đã ghi nhận và `status` không thay đổi:

```json theme={null}
{
  "severity": "error",
  "status": "unresolved",
  "triage": {
    "effective_severity": "warning",
    "ignored": false,
    "rule_applied": true
  }
}
```

Đoạn trích này chỉ hiển thị một số trường. Quy tắc không giải quyết, lưu trữ hay
mở lại vấn đề. Dùng [thao tác đổi trạng thái](#issue-status-response-examples)
cho việc đó. Mức ưu tiên suy ra sẽ theo mức độ nghiêm trọng hiệu lực mới. Đọc
vấn đề với `response_version=2` hoặc `3` để xem mức ưu tiên đó.

Mức độ nghiêm trọng không được hỗ trợ trả về `422`:

```json theme={null}
{
  "error": "triage severity must be source, info, warning, error, or critical",
  "code": "validation_failed",
  "next": "use source to restore captured severity, or choose info, warning, error, or critical",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

Trường không xác định trong body, chẳng hạn `status` trong quy tắc vấn đề, trả
về `422` với `code: invalid_json`. Log hoặc vấn đề không tồn tại hay không đọc
được trả về `404` với `code: not_found`. Nếu mất phản hồi, đọc lại log hoặc vấn
đề trước khi gửi lại quy tắc.

## Định dạng phản hồi lỗi

Lỗi ứng dụng trả về một envelope JSON. Ví dụ này cho thấy một yêu cầu bị từ
chối; văn bản `error` và `next` tùy thuộc vào lỗi cụ thể:

```json theme={null}
{
  "error": "<what is wrong>",
  "code": "validation_failed",
  "next": "<how to fix it>",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

Dùng `code` để rẽ nhánh trong chương trình và `next_action` cho tự động hóa.
Hiển thị `error` và `next` cho người đọc dưới dạng văn bản thuần. Không phân tích
cú pháp câu chữ của chúng. Một số lỗi có thêm trường, chẳng hạn `limit`,
`reset_at` hoặc `retry_after_seconds`. Phản hồi không có body JSON thì không có
`code` của LogBrew. Xem [Lỗi API](/vi/reference/api-errors) để biết mọi mã lỗi.

## Đọc dữ liệu bằng CLI

CLI đọc cùng các route và trả về cùng JSON khi dùng `--json`. Bắt đầu với phạm
vi rộng, rồi thu hẹp dần:

```bash theme={null}
logbrew read releases --environment production --json
logbrew read issues --release api@1.2.3 --status unresolved --json
logbrew read logs --release api@1.2.3 --since 24h --json
logbrew read actions --name checkout_failed --since 24h --json
logbrew read traces --status error --since 24h --json
logbrew read trace <trace_id> --json
```

Thêm `--pagination cursor` để nhận envelope cursor. CLI yêu cầu phản hồi vấn đề
phiên bản 4. Xem [Đọc trang tiếp theo](/vi/reference/cli#read-the-next-page)
và [Theo dõi trực tiếp](/vi/reference/cli#live-watch).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.