getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
8.02k stars 1.59k forks source link

Sentry.GCPFunction.wrapHttpFunction cause Error [ERR_STREAM_WRITE_AFTER_END]: write after end #8848

Open jiangbo0216 opened 1 year ago

jiangbo0216 commented 1 year ago

Is there an existing issue for this?

How do you use Sentry?

Self-hosted/on-premise

Which SDK are you using?

@sentry/serverless

SDK Version

"@sentry/serverless": "^7.64.0"

Framework Version

No response

Link to Sentry event

No response

SDK Setup

No response

Steps to Reproduce

new a simple google-cloud demo

pnpm i @google-cloud/functions-framework @sentry/serverless

  1. create index.js

    const Sentry = require('@sentry/serverless');
    Sentry.GCPFunction.init({
    dsn: <your dsn>,
    tracesSampleRate: 1.0,
    });
    exports.helloWorld = Sentry.GCPFunction.wrapHttpFunction(async (req, res) => {
    Promise.reject('error');
    res.send('Hello, World');
    });
  2. start function

    
    npx @google-cloud/functions-framework --target=helloWorld

### Expected Result

process run and don't exit

### Actual Result

link: https://github.com/getsentry/sentry-javascript/issues/2344

get a error: Error [ERR_STREAM_WRITE_AFTER_END]: write after end
sentry patch end function, cause res.end turn sync to async

https://github.com/getsentry/sentry-javascript/blob/2d80b4b2cfabb69f0cfd4a96ea637a8cabbd37cb/packages/serverless/src/gcpfunction/http.ts#L105-L118

and @google-cloud/functions-framework depend res.end onfinished to handle error

https://github.com/GoogleCloudPlatform/functions-framework-nodejs/blob/35533b76face60714a9f6050aaced98da231016b/src/server.ts#L137-L143

https://github.com/GoogleCloudPlatform/functions-framework-nodejs/blob/35533b76face60714a9f6050aaced98da231016b/src/function_wrappers.ts#L105-L130

const wrapHttpFunction = (execute) => { return (req, res) => { const d = domain.create(); const errorHandler = (err) => { if (res.locals.functionExecutionFinished) { console.error(Exception from a finished function: ${err}); } else { res.locals.functionExecutionFinished = true; (0, logger_1.sendCrashResponse)({ err, res }); } }; // Catch unhandled errors originating from this request. d.on('error', errorHandler); d.run(() => { process.nextTick(() => { const ret = execute(req, res); // Catch rejected promises if the function is async. if (ret instanceof Promise) { ret.catch(errorHandler); } }); }); }; };


in this case,

res.send('Hello, World')


start to end response but it is async

so when a error in user handler, 
    d.on('error', errorHandler);

errorHandler will be triggered, and sendCrashResponse will be called, At this point, Error [ERR_STREAM_WRITE_AFTER_END]: write after end may occur
Lms24 commented 1 year ago

Hi @jiangbo0216, thanks for writing in and for opening a PR! We're very busy this week but we'll try to look into this next week. Thanks!

jiangbo0216 commented 1 year ago

hava any update?

Hi @jiangbo0216, thanks for writing in and for opening a PR! We're very busy this week but we'll try to look into this next week. Thanks!

simonnztg commented 3 months ago

What's happening with this issue? We're looking to use Sentry but this issues prevents us from using it in our serverless functions environment

andreiborza commented 3 months ago

Hey @simonnztg thanks for writing in. We're currently on company-wide hackweek and thus on limited support. We'll take another look at this next week.

lforst commented 3 months ago

Hi, @simonnztg currently we are not working on this issue because bluntly said, the gcpfunction integration doesn't get much use (might be a self-fulfilling prophecy). If you want to use Sentry in your GCP functions, as a workaround, you should be able to just use the @sentry/node package and call Sentry.init() somewhere in the global scope. This will not automatically track the performance of your functions, but you can manually add Sentry.startSpan() calls though.

(Corporate speech off: I low-key want to use GCP functions for my side project so this integration may get some love soon.)

contactsimonwilson commented 3 months ago

Hi, @simonnztg currently we are not working on this issue because bluntly said, the gcpfunction integration doesn't get much use (might be a self-fulfilling prophecy). If you want to use Sentry in your GCP functions, as a workaround, you should be able to just use the @sentry/node package and call Sentry.init() somewhere in the global scope. This will not automatically track the performance of your functions, but you can manually add Sentry.startSpan() calls though.

(Corporate speech off: I low-key want to use GCP functions for my side project so this integration may get some love soon.)

Thanks for getting back to me. I thought this might be the case, and I have a workaround in place so we can keep using it for now. FWIW, functions support was one of the main things that attracted me to Sentry.