-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
test: Add test utility to intercept requests to Sentry #7271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
size-limit report 📦
|
Replay SDK metrics 🚀
develop |
Revision | LCP | CLS | CPU | JS heap avg | JS heap max | netTx | netRx | netCount | netTime |
---|---|---|---|---|---|---|---|---|---|
e60cd02 | +56.25 ms | -0.00 ms | +6.32 pp | +927.44 kB | +1.06 MB | +2.21 kB | +41 B | +1 | +117.55 ms |
e25c067 | +48.34 ms | +0.00 ms | +5.59 pp | +926.37 kB | +1.05 MB | +2.22 kB | +41 B | +1 | +65.23 ms |
b1b249b | +43.88 ms | +0.00 ms | +4.80 pp | +937.99 kB | +1.05 MB | +2.22 kB | +41 B | +1 | +111.56 ms |
12e34d4 | +28.57 ms | +0.00 ms | +5.77 pp | +930.12 kB | +1.04 MB | +2.26 kB | +41 B | +1 | +109.67 ms |
c46c56c | +65.45 ms | -0.00 ms | +5.38 pp | +930.26 kB | +1.07 MB | +2.21 kB | +41 B | +1 | +91.29 ms |
7f4c4ec | +56.64 ms | -0.00 ms | +5.57 pp | +927.42 kB | +1.06 MB | +2.21 kB | +41 B | +1 | +110.83 ms |
00d2360 | +55.18 ms | +0.00 ms | +2.23 pp | +934.14 kB | +1.05 MB | +2.22 kB | +41 B | +1 | +71.65 ms |
Last updated: Thu, 23 Feb 2023 14:42:24 GMT
const sentryRequest = https.request( | ||
sentryIngestUrl, | ||
{ headers: proxyRequest.headers, method: proxyRequest.method }, | ||
sentryResponse => { | ||
sentryResponse.addListener('data', (chunk: Buffer) => { | ||
proxyResponse.write(chunk, 'binary'); | ||
sentryResponseChunks.push(chunk); | ||
}); | ||
|
||
sentryResponse.addListener('end', () => { | ||
eventCallbackListeners.forEach(listener => { | ||
const rawProxyRequestBody = Buffer.concat(proxyRequestChunks).toString(); | ||
const rawSentryResponseBody = Buffer.concat(sentryResponseChunks).toString(); | ||
|
||
const data: SentryRequestCallbackData = { | ||
envelope: parseEnvelope(rawProxyRequestBody, new TextEncoder(), new TextDecoder()), | ||
rawProxyRequestBody, | ||
rawSentryResponseBody, | ||
sentryResponseStatusCode: sentryResponse.statusCode, | ||
}; | ||
|
||
listener(Buffer.from(JSON.stringify(data)).toString('base64')); | ||
}); | ||
proxyResponse.end(); | ||
}); | ||
|
||
sentryResponse.addListener('error', err => { | ||
throw err; | ||
}); | ||
|
||
proxyResponse.writeHead(sentryResponse.statusCode || 500, sentryResponse.headers); | ||
}, | ||
); |
Check failure
Code scanning / CodeQL
Server-side request forgery
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need both the eventCallbackServer
and a proxyServer
?
for (const envelopeItem of envelopeItems) { | ||
if (callback(envelopeItem)) { | ||
resolve(envelopeItem); | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m: Why are we returning from the promise? Ditto for the other waitForX
methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're not returning from the promise, we're returning from the callback of waitForRequest
. This is to stop listening for events. Do you know a better way to do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup you're right, the nesting just confused me.
I think it's fine, just takes a bit to get - this is the best way to share state this functional way.
The alternative would be to have this all be in a class mutating some internal state, but that is prob less clean.
proxyServerName: string, | ||
callback: (eventData: SentryRequestCallbackData) => boolean, | ||
): Promise<SentryRequestCallbackData> { | ||
const tmpFileWithPort = path.join(os.tmpdir(), `event-proxy-server-${proxyServerName}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
l: If this is expected to keep in sync with tmpFileWithPort
generated from eventCallbackServerStartupPromise
, I would like it to be a helper func. This way there's no way that it'll ever differ unless done intentionally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 9090f79
callback: (eventData: SentryRequestCallbackData) => boolean, | ||
): Promise<SentryRequestCallbackData> { | ||
const tmpFileWithPort = path.join(os.tmpdir(), `event-proxy-server-${proxyServerName}`); | ||
const eventCallbackServerPort = fs.readFileSync(tmpFileWithPort, 'utf8'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
l: Can this be async?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 9090f79
} | ||
eventContents = ''; | ||
} else { | ||
eventContents = eventContents.concat(char); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
l: why concat
over push
? push is faster, and we already break mutability by using let eventContents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly string doesn't have a push method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
omg im a dummy
|
||
const eventCallbackServerStartupPromise = new Promise<void>(resolve => { | ||
const listener = eventCallbackServer.listen(0, () => { | ||
const port = String((listener.address() as AddressInfo).port); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const port = String((listener.address() as AddressInfo).port); | |
const port = String(eventCallbackServer.address().port); |
l: We can then forgo the listener return as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 f2bc116
Co-authored-by: Abhijeet Prasad <aprasad@sentry.io>
@AbhiPrasad Thought about just making it different endpoints on the same server but it simplifies defining the tunnel a lot. |
This PR adds a package containing utilities to start a proxy server that is able to intercept requests to sentry (via the
tunnel
option) and additionally provides utility functions to listen for particular envelopes/events.Resolves #7263