-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
test(node): Add tests for Undici #7628
Conversation
@@ -89,7 +93,7 @@ export class Undici implements Integration { | |||
const url = new URL(request.path, request.origin); | |||
const stringUrl = url.toString(); | |||
|
|||
if (isSentryRequest(stringUrl)) { | |||
if (isSentryRequest(stringUrl) || request.__sentry__ !== undefined) { |
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.
I kept running into this, but I'm not sure why it's happening, the spec doesn't allow for it.
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.
Hmm this looks strange. As if the same request went twice through this channel? Anyway, I think it's fine to bail out in this case
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.
This looks good, thanks for adding the tests!
// Please note that you cannot use `console.log` to debug the callbacks registered to the `diagnostics_channel` API. | ||
// To debug, you can use `writeFileSync` to write to a file: | ||
// https://nodejs.org/api/async_hooks.html#printing-in-asynchook-callbacks | ||
|
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.
Sounds painful :/
@@ -89,7 +93,7 @@ export class Undici implements Integration { | |||
const url = new URL(request.path, request.origin); | |||
const stringUrl = url.toString(); | |||
|
|||
if (isSentryRequest(stringUrl)) { | |||
if (isSentryRequest(stringUrl) || request.__sentry__ !== undefined) { |
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.
Hmm this looks strange. As if the same request went twice through this channel? Anyway, I think it's fine to bail out in this case
it('does not create a span for sentry requests', async () => { | ||
const transaction = hub.startTransaction({ name: 'test-transaction' }) as Transaction; | ||
hub.getScope().setSpan(transaction); | ||
|
||
try { | ||
await fetch(`${SENTRY_DSN}/sub/route`, { | ||
method: 'POST', | ||
}); | ||
} catch (e) { | ||
// ignore | ||
} | ||
|
||
expect(transaction.spanRecorder?.spans.length).toBe(1); | ||
}); | ||
|
||
it('does not create a span for sentry requests', async () => { | ||
const transaction = hub.startTransaction({ name: 'test-transaction' }) as Transaction; | ||
hub.getScope().setSpan(transaction); | ||
|
||
expect(transaction.spanRecorder?.spans.length).toBe(1); | ||
|
||
try { | ||
await fetch(`${SENTRY_DSN}/sub/route`, { | ||
method: 'POST', | ||
}); | ||
} catch (e) { | ||
// ignore | ||
} | ||
|
||
expect(transaction.spanRecorder?.spans.length).toBe(1); | ||
}); |
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: duplicate?
it('does not create a span for sentry requests', async () => { | |
const transaction = hub.startTransaction({ name: 'test-transaction' }) as Transaction; | |
hub.getScope().setSpan(transaction); | |
try { | |
await fetch(`${SENTRY_DSN}/sub/route`, { | |
method: 'POST', | |
}); | |
} catch (e) { | |
// ignore | |
} | |
expect(transaction.spanRecorder?.spans.length).toBe(1); | |
}); | |
it('does not create a span for sentry requests', async () => { | |
const transaction = hub.startTransaction({ name: 'test-transaction' }) as Transaction; | |
hub.getScope().setSpan(transaction); | |
expect(transaction.spanRecorder?.spans.length).toBe(1); | |
try { | |
await fetch(`${SENTRY_DSN}/sub/route`, { | |
method: 'POST', | |
}); | |
} catch (e) { | |
// ignore | |
} | |
expect(transaction.spanRecorder?.spans.length).toBe(1); | |
}); | |
it('does not create a span for sentry requests', async () => { | |
const transaction = hub.startTransaction({ name: 'test-transaction' }) as Transaction; | |
hub.getScope().setSpan(transaction); | |
try { | |
await fetch(`${SENTRY_DSN}/sub/route`, { | |
method: 'POST', | |
}); | |
} catch (e) { | |
// ignore | |
} | |
expect(transaction.spanRecorder?.spans.length).toBe(1); | |
}); |
await fetch(`${SENTRY_DSN}/sub/route`, { | ||
method: 'POST', | ||
}); |
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 (and more a question than a suggestion):
This makes me wonder about our isSentryRequest
check. As I mentioned yesterday, we have 5 slightly different checks for identifying a sentry request all over the code base. I'll sooner or later clean this up (after #7626) but should this check take the Http method into account? Some checks do (example) while others (like the one you're using here) don't. I'd argue it's probably not necessary to check for the method but wdyt?
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.
All sentry requests use POST atm, so I don't see anything wrong with this for now, but the more future-proof and correct solution is to not take into account the http method (in case we do ever introduce GET
methods - think something like dynamic config).
Going to keep this as is for the test, we can come back and refactor all instances of isSentryRequest
later.
it('does create a span if `shouldCreateSpanForRequest` is defined', async () => { | ||
const transaction = hub.startTransaction({ name: 'test-transaction' }) as Transaction; | ||
hub.getScope().setSpan(transaction); | ||
|
||
const client = new NodeClient({ ...DEFAULT_OPTIONS, shouldCreateSpanForRequest: url => url.includes('yes') }); | ||
hub.bindClient(client); | ||
|
||
await fetch('http://localhost:18099/no', { method: 'POST' }); | ||
|
||
expect(transaction.spanRecorder?.spans.length).toBe(1); | ||
|
||
await fetch('http://localhost:18099/yes', { method: 'POST' }); | ||
|
||
expect(transaction.spanRecorder?.spans.length).toBe(2); | ||
}); | ||
|
||
it('attaches the sentry trace and baggage headers', async () => { | ||
const transaction = hub.startTransaction({ name: 'test-transaction' }) as Transaction; | ||
hub.getScope().setSpan(transaction); | ||
|
||
await fetch('http://localhost:18099', { method: 'POST' }); | ||
|
||
expect(transaction.spanRecorder?.spans.length).toBe(2); | ||
const span = transaction.spanRecorder?.spans[1]; | ||
|
||
expect(requestHeaders['sentry-trace']).toEqual(span?.toTraceparent()); | ||
expect(requestHeaders['baggage']).toEqual( | ||
`sentry-environment=production,sentry-transaction=test-transaction,sentry-public_key=0,sentry-trace_id=${transaction.traceId},sentry-sample_rate=1`, | ||
); | ||
}); |
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: Let's add a test to cover the case where shouldCreateSpanForRequest
returns false
which should lead to the tracing headers not being attached.
7d88183
to
3dd7943
Compare
size-limit report 📦
|
ref #7624
Tests for #7582!
Ended up pulling in the undici dep to make testing easier.
Tests are not as clean as I wished to be, but I'm optimizing for speed here - we can clean this up afterwards.