oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
72.29k stars 2.58k forks source link

Bun HTTP breaks Sentry Tracing #7472

Open r614 opened 7 months ago

r614 commented 7 months ago

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)),
});
approached commented 7 months ago

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

colinricardo commented 6 months ago

experiencing this also with:

HazAT commented 6 months ago

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

lsnow99 commented 6 months ago

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

opensourceinterfaces292 commented 3 months ago

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!

AbhiPrasad commented 3 months ago

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 commented 2 months ago

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

rhuanbarreto commented 2 months ago

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

AbhiPrasad commented 2 months ago

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

Yes!

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