getsentry / getsentry/sentry-javascript

@sentry/cloudflare: Durable Object RPC methods drop metrics, logs and errors unless the caller propagates a trace

Đã đóng
#24,443 2 bình luận 0 reaction 0 người được giao Xem trên GitHub
Cloudflare Workers
Ngôn ngữ chính
TypeScript
Star
8.7k
Fork
1.8k
Merge trung bình
1 ngày 17 giờ
Pull request đã merge (30 ngày)
523

Mô tả

### Environment
- `@sentry/cloudflare`: 10.74.0 (same logic on `develop` / `11.0.0-beta.2`)
- DO wrapped with `instrumentDurableObjectWithSentry`, `enableRpcTracePropagation: true` (the only
supported way to instrument RPC methods in v11, now that `instrumentPrototypeMethods` is removed)

### Description
`createRpcPrototypeWrapper` only calls `wrapMethodWithSentry` when the last argument carries
`__sentry_rpc_meta__`. Otherwise the original method runs with no client bound. Then:

- `Sentry.metrics.count/gauge/distribution` return early (no client);
- `Sentry.captureException` and `Sentry.logger.*` are dropped;
- no `rpc` span is recorded, and a thrown error is not captured.

Callers send the metadata only if they are Sentry-instrumented, have an active trace, **and** got the stub
through `get`/`getByName` on the instrumented env (see #24442). Common cases that lose everything:

- calls from uninstrumented workers or mixed deployments;
- calls from code running outside the request's async context;
- any call through `jurisdiction()`.

`WorkerEntrypoint` already covers this case: `instrumentWorkerEntrypoint` uses a capture-only wrapper
when the metadata is missing. Durable Objects have no equivalent. `fetch`, `alarm` and `webSocket*` are
always wrapped, so only RPC is affected. That makes the gap easy to miss: our production data had
14 days of DO `alarm` spans and zero DO `rpc` spans.

### Reproduction
```ts
class MyDO extends DurableObject {
async ping() {
Sentry.metrics.count('my_do.ping', 1);
throw new Error('boom');
}
}
export const MyDOInstrumented = Sentry.instrumentDurableObjectWithSentry(
env => ({ dsn: env.SENTRY_DSN, tracesSampleRate: 1, enableRpcTracePropagation: true }),
MyDO,
);
// From a plain (uninstrumented) worker:
await env.MY_DO.get(env.MY_DO.idFromName('x')).ping();
```
Neither the metric nor the error reaches Sentry.

### Expected
External RPC calls without metadata still run inside a client and isolation scope with flush, as
`WorkerEntrypoint` does. Internal `this.method()` calls stay unwrapped.

### Proposed fix
A PR with this change will follow.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Hướng nghiên cứu

Start at createRpcPrototypeWrapper and compare its metadata-missing path with instrumentWorkerEntrypoint's capture-only wrapper and wrapMethodWithSentry. Reproduce an external RPC call from the plain worker in the issue, then verify that calls without metadata run with a client and isolation scope, flush metrics and errors, and leave internal this.method() calls unwrapped.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
typescript
Lĩnh vực
observability
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
63/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.