Bỏ qua tới nội dung
Mục lục

Offline và gửi bền

Lỗi được giữ lại khi chưa gửi được: thử lại có độ trễ ngẫu nhiên, hàng đợi IndexedDB với offline: true trên trình duyệt, và @belvador/spool ghi xuống đĩa cho Node.js, Bun và Deno.

Bản Markdown
Trong bài này

Lỗi thường xảy ra đúng lúc mạng tệ nhất: đi qua đường hầm, node của bạn đang khởi động lại, máy chủ mất kết nối tới dịch vụ phía trên. Trang này cho biết SDK của Belvador làm gì khi một lỗi chưa gửi được, và cách giữ lỗi lại cho tới khi gửi được. Mọi thứ ở đây có từ SDK 0.6.0.

Mọi SDK đã làm sẵn#

Mỗi lần gửi được thử tối đa 5 lần. Thời gian chờ trước mỗi lần thử lại là ngẫu nhiên, từ 0 tới 1, 2, 4, rồi 8 giây (tối đa 30 giây) — để một nghìn app cùng mất kết nối không quay lại cùng một giây. 503 có Retry-After thì chờ đúng như yêu cầu. Mỗi lần thử lại gửi đúng envelope cũ với cùng event id, nên node của bạn chỉ đếm lỗi một lần.

Nếu không bật các tuỳ chọn dưới đây, lỗi vẫn không gửi được sau lần thử cuối sẽ mất, và trang bị đóng sẽ mang theo các lỗi đang chờ. Quy tắc đầy đủ nằm ở Cách gửi.

Trình duyệt: offline: true#

src/instrument.ts
import { init } from "@belvador/browser"; // or @belvador/react, @belvador/tanstack-start/clientinit({  dsn: "https://<public-key>@ingest.belvador.dev/<project-id>",  // Errors that cannot be sent wait in this browser, then go out when it is back online.  offline: true,});

Với offline: true, lỗi gửi hỏng vì mạng được giữ trong trình duyệt này (IndexedDB) và gửi lại:

  • ngay khi trình duyệt báo đã có mạng lại,

  • hoặc ở lần tải trang kế tiếp, kể cả khi tab đã bị đóng.

Quy tắcGiá trị
Giữ tối đa50 envelope cho mỗi DSN — vượt quá thì bỏ cái cũ nhất và đếm là tràn hàng đợi
Giữ trong72 giờ — cũ hơn thì bỏ thay vì gửi
Thứ tựcũ nhất trước
Câu trả lời không phải lỗi mạng4xx từ node không bao giờ được lưu: gửi lại cũng không đổi được gì
Chi phíkhoảng 1,8 KB gzip, tải thành một tệp riêng chỉ khi đặt offline: true

Dùng giống hệt với @belvador/react và @belvador/tanstack-start/client. Ở chế độ xem trước (preview: true) không lưu gì, vì không gửi gì.

Khi trình duyệt không dùng được IndexedDB (một số cửa sổ ẩn danh, chính sách chặn lưu trữ) hoặc không tải được tệp offline, SDK gửi như cũ, không có hàng đợi, và báo BLV_OFFLINE_UNAVAILABLE một lần.

Node.js, Bun và Deno: @belvador/spool#

Máy chủ dùng SDK chính thức của Sentry với DSN của Belvador có thể giữ lỗi trên đĩa khi node chưa liên lạc được. Khi node trả lời lại, lỗi được gửi theo thứ tự cũ nhất trước — cả bởi tiến trình kế tiếp, nếu tiến trình này đã khởi động lại hoặc bị kill.

Terminal
npm install @belvador/spool@0.6.1

Node.js (@sentry/node):

instrument.mjs
import * as Sentry from "@sentry/node";import { scrubBreadcrumb, scrubEvent } from "@belvador/core/sentry";import { withSpool } from "@belvador/spool";Sentry.init({  dsn: process.env.BELVADOR_DSN ?? "https://<public-key>@ingest.belvador.dev/<project-id>",  release: process.env.APP_VERSION,  environment: process.env.NODE_ENV,  sendDefaultPii: false,  tracesSampleRate: 0,  maxBreadcrumbs: 50,  maxValueLength: 8192,  // Belvador's scrubbing: request bodies, cookies and credentials never leave the app.  beforeSend: scrubEvent,  beforeBreadcrumb: scrubBreadcrumb,  // Errors that cannot be sent wait on disk and go out after a restart.  transport: withSpool(Sentry.makeNodeTransport, {    dir: process.env.BELVADOR_SPOOL_DIR ?? "/var/lib/my-app/belvador",  }),});

Bun (@sentry/bun):

instrument.ts
import * as Sentry from "@sentry/bun";import { scrubBreadcrumb, scrubEvent } from "@belvador/core/sentry";import { withSpool } from "@belvador/spool";Sentry.init({  dsn: process.env.BELVADOR_DSN ?? "https://<public-key>@ingest.belvador.dev/<project-id>",  release: process.env.APP_VERSION,  environment: process.env.NODE_ENV,  sendDefaultPii: false,  tracesSampleRate: 0,  maxBreadcrumbs: 50,  maxValueLength: 8192,  // Belvador's scrubbing: request bodies, cookies and credentials never leave the app.  beforeSend: scrubEvent,  beforeBreadcrumb: scrubBreadcrumb,  // Errors that cannot be sent wait on disk and go out after a restart.  transport: withSpool(Sentry.makeFetchTransport, {    dir: process.env.BELVADOR_SPOOL_DIR ?? "./.belvador-spool",  }),});

Deno (npm:@sentry/deno):

instrument.ts
import * as Sentry from "npm:@sentry/deno@11.9.0";import { scrubBreadcrumb, scrubEvent } from "npm:@belvador/core@0.6.1/sentry";import { makeFetchTransport, withSpool } from "npm:@belvador/spool@0.6.1";Sentry.init({  dsn: Deno.env.get("BELVADOR_DSN") ?? "https://<public-key>@ingest.belvador.dev/<project-id>",  release: Deno.env.get("APP_VERSION"),  environment: Deno.env.get("APP_ENV") ?? "production",  sendDefaultPii: false,  tracesSampleRate: 0,  maxBreadcrumbs: 50,  maxValueLength: 8192,  // Belvador's scrubbing: request bodies, cookies and credentials never leave the app.  beforeSend: scrubEvent,  beforeBreadcrumb: scrubBreadcrumb,  // Errors that cannot be sent wait on disk and go out after a restart.  transport: withSpool(makeFetchTransport, {    dir: Deno.env.get("BELVADOR_SPOOL_DIR") ?? "./.belvador-spool",  }),});

Spool cần quyền mạng tới host trong DSN, hai biến môi trường và quyền đọc/ghi thư mục của nó:

Terminal
deno run --allow-net=ingest.belvador.dev \  --allow-env=BELVADOR_DSN,BELVADOR_SPOOL_DIR \  --allow-read=./.belvador-spool --allow-write=./.belvador-spool \  main.ts
Tuỳ chọnMặc địnhTác dụng
dir— (bắt buộc)Mỗi app một thư mục, tạo với quyền 0700; tệp có quyền 0600. Nhiều tiến trình của cùng app có thể dùng chung.
maxBytes64 MiBTổng dung lượng trên đĩa. Envelope cũ nhất bị bỏ trước, đếm là tràn hàng đợi.
ttlHours72Envelope cũ hơn bị bỏ thay vì gửi.
keychưa đặt32 byte ngẫu nhiên của riêng bạn: envelope trên đĩa được mã hoá AES-256-GCM.

Những gì đã kiểm thử: 200 lỗi trong lúc điểm nhận lỗi ngừng, tiến trình bị kill bằng SIGKILL, tiến trình mới khởi động khi điểm nhận chạy lại — đủ 200 lỗi tới nơi, không lỗi nào hai lần, trên Node.js, Bun và Deno. Tiến trình bị kill giữa lúc ghi chỉ để lại tối đa một tệp ghi dở, lần khởi động sau bỏ và đếm nó; mọi envelope hoàn chỉnh vẫn tới đúng một lần. Một đợt lỗi dồn dập lớn hơn bộ đệm trong bộ nhớ của SDK Sentry (64 lần gửi) được ghi xuống đĩa thay vì bị bỏ. Các công thức ở trên, đúng như bản phát hành, cũng đã chạy tới một node thật với @sentry/node và @sentry/bun 11.9.0: lỗi xảy ra khi node không liên lạc được đều tới sau một lần SIGKILL và, với Node.js, sau một lần sập vì hết bộ nhớ.

Đang dùng makeOfflineTransport của SDK Sentry? Truyền createStore: makeFileStore({ dir }) từ @belvador/spool thay cho kho mặc định. Dù vậy withSpool vẫn là lựa chọn tốt hơn: nó giữ được cả đợt lỗi vượt bộ đệm 64 lần gửi và không đếm lỗi đã lưu là bị mất.

Môi trường chạy không có đĩa#

  • Cloudflare Workers không có đĩa và isolate có thể dừng bất cứ lúc nào. @belvador/cloudflare thử lại như trên bên trong waitUntil; lỗi vẫn hỏng thì mất.

  • Supabase Edge Functions và các function sống ngắn khác: spool trên đĩa tạm sẽ biến mất cùng instance, nên không được lợi gì. Thay vào đó hãy gửi trước khi trả lời — xem Supabase Edge Functions.

  • Python (sentry-sdk) chỉ có hàng đợi trong bộ nhớ; chưa có spool trên đĩa.

Điều này không hứa hẹn#

Cả hàng đợi trình duyệt lẫn spool đều không hứa mọi lỗi sẽ tới nơi. Đĩa hoặc hạn mức lưu trữ đầy, tệp hỏng, hay envelope quá thời hạn sẽ bị bỏ và được đếm trong báo cáo gửi của SDK. App của bạn không bao giờ phải chờ bộ lưu trữ và không bao giờ thấy lỗi từ nó.

Thấy chỗ sai hoặc thiếu? Gửi cho chúng tôi: hello@belvador.dev