# Liên kết lỗi qua nhiều tầng bằng trace

> Bật tracePropagation để lỗi trình duyệt, lỗi máy chủ và lượt chạy của job cùng một request hiện chung trong “Cùng trace”.

Một cú bấm trên trình duyệt có thể kết thúc bằng một lỗi cách đó ba tầng: server function, rồi một Worker, rồi một job. Khi bật **trace propagation**, mọi lỗi và lượt chạy job do cú bấm đó gây ra mang cùng một **trace ID**, và Belvador hiện chúng cùng nhau trong **Cùng trace** ở mỗi issue và ở trang **Trace**.

Đây là liên kết, không phải tracing hiệu năng: các SDK Belvador không tạo span hay đo thời gian từng tầng — chỉ ghi lỗi và lượt chạy nào chung một trace. Muốn có span và thời gian, hãy gửi [traces OpenTelemetry](https://belvador.dev/vi/docs/otel/overview); tuỳ chọn bên dưới giúp lỗi khớp với chúng.

## Bật lên

Có từ `@belvador/*` 0.3.0. Mặc định **tắt**, vì thêm header vào request có thể kích hoạt kiểm tra CORS ở các API bạn không kiểm soát.

### Trình duyệt và React

```ts
import { init } from "@belvador/browser"; // or @belvador/react

init({
  dsn: "https://<public-key>@ingest.belvador.dev/<project-id>",
  // Only your own APIs. Every other URL is left alone.
  tracePropagation: { targets: ["/api/", "https://api.example.com/"] },
});
```

### TanStack Start

```ts title="src/router.tsx"
import { init } from "@belvador/tanstack-start/client";

if (typeof window !== "undefined") {
  init({
    dsn: "https://<public-key>@ingest.belvador.dev/<project-id>",
    // Same-origin server functions and routes; the server SDK continues the trace.
    tracePropagation: { targets: ["/_serverFn/", "/api/"] },
  });
}
```

`targets` liệt kê các URL được thêm header trace: chuỗi khớp mọi URL có chứa nó (và, trên trình duyệt, đường dẫn của request cùng origin); RegExp được thử trên URL. Chỉ liệt kê API của chính bạn. Danh sách rỗng là tắt.

Các gói phía máy chủ (`@belvador/tanstack-start/server`, `@belvador/cloudflare`) tự nối tiếp trace đi vào: lỗi hay lượt `withMonitor` trong request đó mang trace ID của bên gọi. Worker cũng chuyển header tiếp ở các lệnh `fetch` của chính nó khi bạn đặt `tracePropagation` trong tuỳ chọn của `withBelvador`.

## Khi đã dùng OpenTelemetry

Nếu app đã chạy OpenTelemetry, hãy để OpenTelemetry làm chủ trace và đưa API của nó cho Belvador. Lỗi được bắt trong lúc một span đang chạy sẽ mang trace ID và span ID của span đó, nên issue mở đúng span trong [waterfall của trace](https://belvador.dev/vi/docs/otel/overview):

```ts title="src/index.ts"
import * as api from "@opentelemetry/api";
import { withBelvador } from "@belvador/cloudflare"; // same option in every @belvador/* init

export default withBelvador(
  (env: { BELVADOR_DSN?: string }) => ({
    dsn: env.BELVADOR_DSN ?? "https://<public-key>@ingest.belvador.dev/<project-id>",
    // The same @opentelemetry/api copy your OpenTelemetry setup uses.
    otel: { api },
  }),
  handler,
);
```

- Truyền chính module (`import * as api from "@opentelemetry/api"`) — bản mà SDK OpenTelemetry của bạn đã đăng ký provider. Belvador không tự import nó, không tạo span và không đăng ký provider.
- ID lấy từ span đang chạy lúc bắt lỗi: `captureException` bên trong span của bạn, hoặc lỗi framework báo trước khi span kết thúc. Lỗi thoát ra khỏi span rồi mới được handler bên ngoài báo thì giữ trace ID của request, không có span đó.
- Khi đã đặt `otel`, `tracePropagation` bị bỏ qua (OpenTelemetry đã gửi `traceparent`), và SDK báo chẩn đoán `BLV_TRACE_OWNER_OTEL` cho tới khi bạn bỏ nó đi.
- Có từ `@belvador/*` 0.4.0.

## Header được gửi

| Header | Khi nào | Nội dung |
|---|---|---|
| `traceparent` | Luôn luôn (W3C Trace Context) | `00-<trace id>-<span id>-00` |
| `sentry-trace` | Luôn luôn | `<trace id>-<span id>` |
| `baggage` | Chỉ khi `baggage: true` | Chỉ các khoá `sentry-*` của SDK |

Request tới cổng nhận của Belvador không bao giờ được thêm header trace.

## CORS

Nếu API ở origin khác, preflight CORS của nó phải cho phép các header mới, nếu không trình duyệt chặn request:

```text
Access-Control-Allow-Headers: traceparent, sentry-trace
# only when you also turn on baggage:
Access-Control-Allow-Headers: traceparent, sentry-trace, baggage
```

Hãy kiểm việc này trước khi bật ở production: thiếu header trong `Access-Control-Allow-Headers` làm **request** thất bại, không chỉ mất trace.

## Đọc một trace

- Ở issue, **Cùng trace** liệt kê tối đa 200 lỗi và lượt chạy cùng trace ID trong ±24 giờ quanh event đó, trên các project của workspace mà bạn được xem.
- **Mở trace** hiện chúng theo thứ tự thời gian. Bạn có thể dán trace ID hoặc nguyên header `traceparent` vào ⌘K để mở.
- Trace chỉ gom dữ liệu trong một workspace. Request đi vào app của workspace khác hiện ở đó thành một mảnh riêng.

Event không có trace ID sẽ ghi rõ trên issue; điều đó bình thường với lỗi không đến từ một request có truyền trace.
