bun icon indicating copy to clipboard operation
bun copied to clipboard

Bun HTTP breaks Sentry Tracing

Open r614 opened this issue 2 years ago • 9 comments

What version of Bun is running?

1.0.7+b0393fba6200d8573f3433fb0af258a0e33ac157

What platform is your computer?

Darwin 23.1.0 arm64 arm

What steps can reproduce the bug?

Ref: https://github.com/getsentry/sentry-javascript/issues/9564 and https://github.com/getsentry/sentry-javascript/issues/9608

Code Sample

index.ts

import { uploadS3  } from "./files";
import * as Sentry from "@sentry/bun";

Sentry.init({
  dsn: <dsn>,
  tracesSampleRate: 1.0,
});

await uploadS3(
  "test",
  "/dev/backend/src/index.ts",
  "text/plain"
);

files.ts

import {
  S3Client,
} from "@aws-sdk/client-s3";
import * as Sentry from "@sentry/bun";
import { Upload } from "@aws-sdk/lib-storage";
import { createReadStream } from "node:fs";

const s3 = new S3Client({
  logger: console,
});

s3.middlewareStack.add((next) => async (args) => {
  console.log("s3 request", args);
  const result = await next(args);
  console.log("s3 response", result);
  return result;
});

const bucketName = <bucketName>

export const uploadS3 = async (
  fileId: string,
  fpath: string,
  mimeType: string
) => {
  console.log(
    "uploading file to S3",
    fileId,
    fpath,
    bucketName,
    mimeType,
  );
  try {
    const upload = new Upload({
      client: s3,
      params: {
        Bucket: bucketName,
        Key: fileId,
        Body: createReadStream(fpath),
      },
      queueSize: 4,
    });

    return upload.done();
  } catch (err) {
    console.error("error uploading file to S3", err);
    Sentry.captureException(err);
  }
};

package.json

{
  "name": "backend",
  "version": "1.0.50",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "bun run --watch src/index.ts"
  },
  "dependencies": {
    "@aws-sdk/client-s3": "^3.451.0",
    "@aws-sdk/lib-storage": "^3.454.0",
    "@sentry/bun": "^7.80.1",
  },
  "devDependencies": {
    "bun-types": "latest"
  },
  "module": "src/index.js"
}

What is the expected behavior?

File is uploaded to S3 successfully, action is logged to Sentry.

What do you see instead?

Request is never completed. It doesn't timeout either, just keeps the client waiting. AFAIK I understand it, the S3 client doesn't even get a response so not sure if the file upload request is even sent.

Logs:

uploading file to S3 test /dev/backend/src/index.ts <bucketName> text/plain
s3 request {
  middlewareStack: {
    add: [Function: add],
    addRelativeTo: [Function: addRelativeTo],
    clone: [Function: clone],
    use: [Function: use],
    remove: [Function: remove],
    removeByTag: [Function: removeByTag],
    concat: [Function: concat],
    applyToStack: [Function: cloneTo],
    identify: [Function: identify],
    identifyOnResolve: [Function: identifyOnResolve],
    resolve: [Function: resolve]
  },
  input: {
    Bucket: <bucket>,
    Key: "test",
    Body: Buffer(2205) [ 105, 109, 112, 111, 114, 116, 32, 123, 32, 69, 108, 121, 115, 105, 97, 44, 32, 116, 32, 125, 32, 102, 114, 111, 109, 32, 34, 101, 108, 121, 115, 105, 97, 34, 59, 10, 105, 109, 112, 111, 114, 116, 32, 123, 32, 99, 114, 101, 97, 116, 101, 65, 117, 116, 104, 48, 85, 115, 101, 114, 32, 125, 32, 102, 114, 111, 109, 32, 34, 46, 47, 109, 111, 100, 117, 108, 101, 115, 47, 97, 117, 116, 104, 48, 34, 59, 10, 105, 109, 112, 111, 114, 116, 32, 123, 32, 103, 101, 116, 68, 114, 105, 118, 101, 67, 108, 105, 101, 110, 116, 44, 32, 117, 112, 108, 111, 97, 100, 70, 105, 108, 101, 84, 111, 71, 111, 111, 103, 108, 101, 68, 114, 105, 118, 101, 32, 125, 32, 102, 114, 111, 109, 32, 34, 46, 47, 109, 111, 100, 117, 108, 101, 115, 47, 103, 100, 114, 105, 118, 101, 34, 59, 10, 105, 109, 112, 111, 114, 116, 32, 123, 32, 100, 111, 119, 110, 108, 111, 97, 100, 70, 105, 108, 101, 44, 32, 117, 112, 108, 111, 97, 100, 70, 105, 108, 101, 32, 125, 32, 102, 114, 111, 109, 32, 34, 46, 47, 109, 111, 100, 117, 108, 101, 115, 47, 102, 105, 108, 101, 115, 34, 59, 10, 105, 109, 112, 111, 114, 116, 32, 123, 32, 105, 115, 73, 110, 116, 101, 114, 110, 97, 108, 65, 112, 112, 32, 125, 32, 102, 114, 111, 109, 32, 34, 46, 47, 109, 111, 100, 117, 108, 101, 115, 47, 109, 105, 100, 100, 108, 101, 119, 97, 114, 101, 34, 59, 10, 105, 109, 112, 111, 114, 116, 32, 123, 32, 115, 119, 97, 103, 103, 101, 114, 32, 125, 32, 102, 114, 111, 109, 32, 34, 64, 101, 108, 121, 115, 105, 97, 106, 115, 47, 115, 119, 97, 103, 103, 101, 114, 34, 59, 10, 105, 109, 112, 111, 114, 116, 32, 42, 32, 97, 115, 32, 83, 101, 110, 116, 114, 121, 32, 102, 114, 111, 109, 32, 34, 64, 115, 101, 110, 116, 114, 121, 47, 98, 117, 110, 34, 59, 10, 105, 109, 112, 111, 114, 116, 32, 123, 32, 99, 111, 114, 115, 32, 125, 32, 102, 114, 111, 109, 32, 34, 64, 101, 108, 121, 115, 105, 97, 106, 115, 47, 99, 111, 114, 115, 34, 59, 10, 10, 105, 102, 32, 40, 112, 114, 111, 99, 101, 115, 115, 46, 101, 110, 118, 46, 78, 79, 68, 69, 95, 69, 78, 86, 32, 61, 61, 61, 32, 34, 112, 114, 111, 100, 117, 99, 116, 105, 111, 110, 34, 41, 32, 123, 10, 32, 32, 83, 101, 110, 116, 114, 121, 46, 105, 110, 105, 116, 40, 123, 10, 32, 32, 32, 32, 100, 115, 110, 58, 32, 34, 104, 116, 116, 112, 115, 58, 47, 47, 52, 99, 102, 52, 98, 102, 53, 51, 57, 53, 51, 57, 56, 101, 97, 97, 56, 100, 54, 49, 98, 99, 51, 97, 102, 98, 54, 53, 53, 54, 52, 49, 64, ... 1692 more ]
  }
}
endpoints Initial EndpointParams: {
  "Bucket": <bucket>,
  "ForcePathStyle": false,
  "UseArnRegion": false,
  "DisableMultiRegionAccessPoints": false,
  "Accelerate": false,
  "UseGlobalEndpoint": false,
  "UseFIPS": false,
  "Region": "us-west-2",
  "UseDualStack": false
}
endpoints evaluateCondition: isSet($Region) = true
endpoints evaluateCondition: booleanEquals($Accelerate, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: booleanEquals($UseFIPS, true) = false
endpoints evaluateCondition: isSet($Bucket) = true
endpoints evaluateCondition: substring($Bucket, 49, 50, true) = null
endpoints evaluateCondition: isSet($Bucket) = true
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: booleanEquals($ForcePathStyle, false) = true
endpoints evaluateCondition: aws.isVirtualHostableS3Bucket($Bucket, false) = true
endpoints evaluateCondition: aws.partition($Region) = {
  "dnsSuffix": "amazonaws.com",
  "dualStackDnsSuffix": "api.aws",
  "implicitGlobalRegion": "us-east-1",
  "name": "aws",
  "supportsDualStack": true,
  "supportsFIPS": true,
  "description": "US West (Oregon)"
}
endpoints assign: partitionResult := {
  "dnsSuffix": "amazonaws.com",
  "dualStackDnsSuffix": "api.aws",
  "implicitGlobalRegion": "us-east-1",
  "name": "aws",
  "supportsDualStack": true,
  "supportsFIPS": true,
  "description": "US West (Oregon)"
}
endpoints evaluateCondition: isValidHostLabel($Region, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: isSet($Endpoint) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: not(isSet($Endpoint)) = true
endpoints evaluateCondition: stringEquals($Region, aws-global) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: not(isSet($Endpoint)) = true
endpoints evaluateCondition: not(stringEquals($Region, aws-global)) = true
endpoints evaluateCondition: booleanEquals($UseGlobalEndpoint, true) = false
endpoints evaluateCondition: booleanEquals($UseDualStack, false) = true
endpoints evaluateCondition: booleanEquals($UseFIPS, false) = true
endpoints evaluateCondition: booleanEquals($Accelerate, false) = true
endpoints evaluateCondition: not(isSet($Endpoint)) = true
endpoints evaluateCondition: not(stringEquals($Region, aws-global)) = true
endpoints evaluateCondition: booleanEquals($UseGlobalEndpoint, false) = true
endpoints Resolving endpoint from template: {
  "url": "https://{Bucket}.s3.{Region}.{partitionResult#dnsSuffix}",
  "properties": {
    "authSchemes": [
      {
        "disableDoubleEncoding": true,
        "name": "sigv4",
        "signingName": "s3",
        "signingRegion": "{Region}"
      }
    ]
  },
  "headers": {}
}
endpoints Resolved endpoint: {
  "headers": {},
  "properties": {
    "authSchemes": [
      {
        "disableDoubleEncoding": true,
        "name": "sigv4",
        "signingName": "s3",
        "signingRegion": "us-west-2"
      }
    ]
  },
  "url": "https://<bucket>.s3.us-west-2.amazonaws.com/"
}

Additional information

Seems like a Bun issue from https://github.com/getsentry/sentry-javascript/issues/9564#issuecomment-1841082305 Removing the HTTP integration from Sentry fixes the issue for now, but we lose some logs we really need

Sentry.init({
  dsn: <dsn>,
  tracesSampleRate: 1.0,
  debug: true,
  integrations: (int) =>
    int.filter((i) => !["Http"].includes(i.name)),
});

r614 avatar Dec 05 '23 19:12 r614

Here is the problem: https://github.com/oven-sh/bun/issues/5091

approached avatar Dec 18 '23 19:12 approached

experiencing this also with:

  • @sentry/bun version 7.93.0
  • bun version 1.0.20

colindotfun avatar Jan 15 '24 15:01 colindotfun

Can I ask, is this an issue with the Sentry SDK, like does it work if you remove/disable Sentry?

HazAT avatar Jan 16 '24 15:01 HazAT

Can I ask, is this an issue with the Sentry SDK, like does it work if you remove/disable Sentry?

Disabling sentry fixes the issue for me (commenting out Sentry.init or adding this line to the Sentry.init config object: integrations: (int) => int.filter((i) => !["BunServer", "Http"].includes(i.name)), - as shown in the original issue)

The response on the relevant sentry issue was that since their monkey patching works for node that this must be an issue with bun

lsnow99 avatar Jan 21 '24 19:01 lsnow99

Hello! Thanks for all of your hard work. @Jarred-Sumner I think lots of teams are eager to move to Bun but can't due this issue, do you know when we can expect a fix for this? 🥲 Thanks again!

opensourceinterfaces292 avatar Apr 04 '24 20:04 opensourceinterfaces292

We changed how we do monkeypatching of HTTP in our upcoming new Sentry JavaScript SDKs major version, 8.0.

Currently there is a beta release: https://github.com/getsentry/sentry-javascript/releases/tag/8.0.0-beta.1

This means you can use Sentry with the v8 beta and tracing should work with Bun!

AbhiPrasad avatar Apr 17 '24 13:04 AbhiPrasad

Fixed with 8.0.0 of @sentry/bun - please give it a try. Thanks!

https://docs.sentry.io/platforms/javascript/guides/bun

https://docs.sentry.io/platforms/javascript/guides/bun/migration/v7-to-v8

AbhiPrasad avatar May 15 '24 13:05 AbhiPrasad

@AbhiPrasad Does this use the latest changes from v1.1.8?

rhuanbarreto avatar May 15 '24 13:05 rhuanbarreto

@AbhiPrasad Does this use the latest changes from v1.1.8?

Yes!

PR here: https://github.com/getsentry/sentry-javascript/pull/11960

AbhiPrasad avatar May 15 '24 13:05 AbhiPrasad