Skip to content

feat(cloudflare): Add R2 bucket auto-instrumentation#21327

Open
JPeer264 wants to merge 2 commits into
developfrom
jp/cloudflare-r2-instrumentation
Open

feat(cloudflare): Add R2 bucket auto-instrumentation#21327
JPeer264 wants to merge 2 commits into
developfrom
jp/cloudflare-r2-instrumentation

Conversation

@JPeer264

@JPeer264 JPeer264 commented Jun 3, 2026

Copy link
Copy Markdown
Member

closes #20836
closes JS-2448

This implements R2 spans. All attributes were taken from Cloudflare itself. The only thing which does not exist in Cloudflare and is added here (inspired by AWS S3), is cloudflare.r2.bucket and gives information of the binding itself.

This should be merged after the Sentry conventions PR and the Sentry docs PR (or at least after approval, in case some OPs change)


AI generated text:

Auto-detect R2 bucket bindings via duck-typing in instrumentEnv and wrap all operations with spans. Span names and attributes align with Cloudflare's built-in tracing conventions (r2_get, r2_put, etc.).

Instrumented methods: get, head, put, delete, list, createMultipartUpload, resumeMultipartUpload, and the resulting multipart upload operations (uploadPart, abort, complete).

@JPeer264 JPeer264 self-assigned this Jun 3, 2026
@JPeer264 JPeer264 requested a review from a team as a code owner June 3, 2026 13:21
@JPeer264 JPeer264 requested review from andreiborza and mydea and removed request for a team June 3, 2026 13:21
Comment thread dev-packages/e2e-tests/test-applications/cloudflare-workers/tests/r2.test.ts Outdated
Comment on lines +75 to +82
export function isR2Bucket(item: unknown): item is R2Bucket {
return (
item != null &&
isNotJSRPC(item) &&
typeof item.head === 'function' &&
typeof item.put === 'function' &&
typeof item.createMultipartUpload === 'function'
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The isR2Bucket function uses fragile duck-typing to detect R2 buckets, which could misidentify other objects and lacks test coverage for validation.
Severity: LOW

Suggested Fix

Add comprehensive unit tests for the isR2Bucket function in isBinding.test.ts. The tests should cover positive and negative cases, including objects that have some but not all of the required methods, to ensure the detection logic is robust and prevent future regressions.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/cloudflare/src/utils/isBinding.ts#L75-L82

Potential issue: The `isR2Bucket` function identifies R2 buckets by checking for the
presence of `head`, `put`, and `createMultipartUpload` methods. This duck-typing
approach is inherently fragile and could lead to false positives. If a different type of
object, such as a custom user object or a future Cloudflare binding, happens to have the
same method names, it would be incorrectly wrapped for R2 instrumentation. This would
not cause a crash but would generate incorrect telemetry spans, which could mislead
debugging efforts. The analysis highlights that this new function lacks any test
coverage in `isBinding.test.ts`, unlike other binding detection functions in the same
file.

Also affects:

  • packages/cloudflare/src/instrumentations/worker/instrumentEnv.ts:57~62

Did we get this right? 👍 / 👎 to inform future reviews.

@linear-code

linear-code Bot commented Jun 3, 2026

Copy link
Copy Markdown

JS-2448

@JPeer264 JPeer264 requested review from isaacs and removed request for mydea June 3, 2026 13:32
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 27.45 kB - -
@sentry/browser - with treeshaking flags 25.88 kB - -
@sentry/browser (incl. Tracing) 45.88 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 48.11 kB - -
@sentry/browser (incl. Tracing, Profiling) 50.65 kB - -
@sentry/browser (incl. Tracing, Replay) 85.08 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 74.68 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 89.78 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 102.44 kB - -
@sentry/browser (incl. Feedback) 44.62 kB - -
@sentry/browser (incl. sendFeedback) 32.25 kB - -
@sentry/browser (incl. FeedbackAsync) 37.38 kB - -
@sentry/browser (incl. Metrics) 28.52 kB - -
@sentry/browser (incl. Logs) 28.76 kB - -
@sentry/browser (incl. Metrics & Logs) 29.45 kB - -
@sentry/react 29.25 kB - -
@sentry/react (incl. Tracing) 48.17 kB - -
@sentry/vue 32.56 kB - -
@sentry/vue (incl. Tracing) 47.74 kB - -
@sentry/svelte 27.48 kB - -
CDN Bundle 29.86 kB - -
CDN Bundle (incl. Tracing) 48.28 kB - -
CDN Bundle (incl. Logs, Metrics) 31.4 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 49.58 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 70.71 kB - -
CDN Bundle (incl. Tracing, Replay) 85.61 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 86.88 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 91.46 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 92.71 kB - -
CDN Bundle - uncompressed 88.8 kB - -
CDN Bundle (incl. Tracing) - uncompressed 146.04 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 93.5 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 150.02 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 218.33 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 264.91 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 268.87 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 278.61 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 282.56 kB - -
@sentry/nextjs (client) 50.58 kB - -
@sentry/sveltekit (client) 46.27 kB - -
@sentry/core/server 76.14 kB - -
@sentry/core/browser 63.29 kB - -
@sentry/node-core 61.84 kB +0.01% +1 B 🔺
@sentry/node 128.29 kB +0.01% +1 B 🔺
@sentry/node - without tracing 74.22 kB +0.01% +1 B 🔺
@sentry/aws-serverless 85.47 kB +0.01% +1 B 🔺
@sentry/cloudflare (withSentry) - minified 177.29 kB +1.61% +2.81 kB 🔺
⛔️ @sentry/cloudflare (withSentry) (max: 439.3 kB) 441.89 kB +1.23% +5.36 kB 🔺

View base workflow run

@JPeer264 JPeer264 force-pushed the jp/cloudflare-r2-instrumentation branch from 3605367 to 3671f29 Compare June 3, 2026 13:54
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

👋 @isaacs, @andreiborza — Please review this PR when you get a chance!

Comment thread packages/cloudflare/src/instrumentations/worker/instrumentR2.ts Outdated
const requestKey = Array.isArray(key) ? key.join(', ') : typeof key === 'string' ? key : undefined;

return {
op: 'cloud.r2',

@andreiborza andreiborza Jun 9, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: This op seems weird, maybe file would make a more meaningful op to mark that these are operations on the "filesystem" (I know it's not 100% applicable as these are objects but seems the closest).

@JPeer264 JPeer264 Jun 15, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe cloudflare.r2 fits the best, as it is definitely no file

Edit: I asked internally what we could use the best.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it changed to a proper OP 💯

...(requestKey !== undefined && { 'cloudflare.r2.request.key': requestKey }),
...(isR2ListOptions(key) && key.prefix !== undefined && { 'cloudflare.r2.request.prefix': key.prefix }),
...(isR2ListOptions(key) && key.delimiter !== undefined && { 'cloudflare.r2.request.delimiter': key.delimiter }),
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cloud.r2',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here.

@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs — Please review this PR when you get a chance!

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit de254da. Configure here.

@JPeer264 JPeer264 force-pushed the jp/cloudflare-r2-instrumentation branch from de254da to e51fed0 Compare June 15, 2026 09:05
@JPeer264 JPeer264 marked this pull request as draft June 16, 2026 11:24
@JPeer264

JPeer264 commented Jun 16, 2026

Copy link
Copy Markdown
Member Author

Moving to draft as the OP is not yet decided for object (see getsentry/sentry-docs#18410)

Also the e2e tests are failing

@JPeer264 JPeer264 force-pushed the jp/cloudflare-r2-instrumentation branch 2 times, most recently from 03f9066 to 2be24fb Compare June 16, 2026 15:22
@JPeer264 JPeer264 marked this pull request as ready for review June 16, 2026 15:22
@JPeer264 JPeer264 requested a review from andreiborza June 16, 2026 15:22

@andreiborza andreiborza left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

JPeer264 and others added 2 commits June 17, 2026 19:16
Auto-detect R2 bucket bindings via duck-typing in instrumentEnv and
wrap all operations with spans. Span names and attributes align with
Cloudflare's built-in tracing conventions (r2_get, r2_put, etc.).

Instrumented methods: get, head, put, delete, list,
createMultipartUpload, resumeMultipartUpload, and the resulting
multipart upload operations (uploadPart, abort, complete).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JPeer264 JPeer264 force-pushed the jp/cloudflare-r2-instrumentation branch from f5359b8 to 97398f7 Compare June 17, 2026 17:16
@JPeer264 JPeer264 enabled auto-merge (squash) June 17, 2026 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloudflare R2 instrumentation

2 participants