import { startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, isObjectLike } from '@sentry/core'; const ORIGIN = "auto.faas.cloudflare.r2"; const R2_OPERATIONS = { get: { spanName: "r2_get", op: "object.get", operation: "GetObject" }, head: { spanName: "r2_head", op: "object.head", operation: "HeadObject" }, put: { spanName: "r2_put", op: "object.put", operation: "PutObject" }, delete: { spanName: "r2_delete", op: "object.delete", operation: "DeleteObject" }, list: { spanName: "r2_list", op: "object.list", operation: "ListObjects" }, uploadPart: { spanName: "r2_uploadPart", op: "object.upload_part", operation: "UploadPart" }, abortMultipartUpload: { spanName: "r2_abortMultipartUpload", op: "object.multipart_upload.abort", operation: "AbortMultipartUpload" }, createMultipartUpload: { spanName: "r2_createMultipartUpload", op: "object.multipart_upload.create", operation: "CreateMultipartUpload" }, completeMultipartUpload: { spanName: "r2_completeMultipartUpload", op: "object.multipart_upload.complete", operation: "CompleteMultipartUpload" } }; function isR2ListOptions(key) { return isObjectLike(key) && !Array.isArray(key); } function createSpanOptions(bindingName, r2Op, key) { const { spanName, op, operation } = R2_OPERATIONS[r2Op]; const requestKey = Array.isArray(key) ? key.join(", ") : typeof key === "string" ? key : void 0; return { op, name: spanName, attributes: { "cloudflare.r2.operation": operation, "cloudflare.r2.bucket": bindingName, ...requestKey !== void 0 && { "cloudflare.r2.request.key": requestKey }, ...isR2ListOptions(key) && key.prefix !== void 0 && { "cloudflare.r2.request.prefix": key.prefix }, ...isR2ListOptions(key) && key.delimiter !== void 0 && { "cloudflare.r2.request.delimiter": key.delimiter }, [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN } }; } function instrumentR2MultipartUpload(upload, bindingName) { const { key } = upload; return new Proxy(upload, { get(target, prop, receiver) { if (prop === "uploadPart") { const original = Reflect.get(target, prop, receiver); return function(...args) { const [partNumber] = args; return startSpan( { ...createSpanOptions(bindingName, "uploadPart", key), attributes: { ...createSpanOptions(bindingName, "uploadPart", key).attributes, "cloudflare.r2.request.part_number": partNumber } }, () => Reflect.apply(original, target, args) ); }; } if (prop === "abort") { const original = Reflect.get(target, prop, receiver); return function() { return startSpan( createSpanOptions(bindingName, "abortMultipartUpload", key), () => Reflect.apply(original, target, []) ); }; } if (prop === "complete") { const original = Reflect.get(target, prop, receiver); return function(...args) { return startSpan( createSpanOptions(bindingName, "completeMultipartUpload", key), () => Reflect.apply(original, target, args) ); }; } return Reflect.get(target, prop, receiver); } }); } function instrumentR2Bucket(bucket, bindingName) { return new Proxy(bucket, { get(target, prop, receiver) { if (prop === "get" || prop === "head" || prop === "put" || prop === "delete" || prop === "list") { const original = Reflect.get(target, prop, receiver); return function(...args) { const [key] = args; return startSpan(createSpanOptions(bindingName, prop, key), () => Reflect.apply(original, target, args)); }; } if (prop === "createMultipartUpload") { const original = Reflect.get(target, prop, receiver); return function(...args) { const [key] = args; return startSpan(createSpanOptions(bindingName, "createMultipartUpload", key), async () => { const upload = await Reflect.apply(original, target, args); return instrumentR2MultipartUpload(upload, bindingName); }); }; } if (prop === "resumeMultipartUpload") { const original = Reflect.get(target, prop, receiver); return function(...args) { const upload = Reflect.apply(original, target, args); return instrumentR2MultipartUpload(upload, bindingName); }; } return Reflect.get(target, prop, receiver); } }); } export { instrumentR2Bucket }; //# sourceMappingURL=instrumentR2.js.map