Skip to content
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

feat(nestjs): Add function-level span decorator to nestjs #12721

Merged
merged 19 commits into from
Jul 4, 2024

Conversation

nicohrubec
Copy link
Contributor

@nicohrubec nicohrubec commented Jul 2, 2024

Adds a decorator @SentryTraced() to the nestjs sdk that can be used on functions to wrap them in a span.

Manual test from my sample application see screenshot below.

Screenshot 2024-07-02 at 13 58 51

  • e2e test
  • README update with short example demonstrating how to use this feature

@nicohrubec nicohrubec marked this pull request as ready for review July 3, 2024 13:55
@@ -38,6 +38,23 @@ Sentry.init({

Note that it is necessary to initialize Sentry **before you import any package that may be instrumented by us**.

## Span Decorator

Use the @GetSentrySpan() decorator to gain additional performance insights for any function within your NestJS application.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: Is GetX a pattern that is common for nest? To me it reads a bit weird, something like WrapWithSentrySpan or something along these lines would feel more explanatory to me, but no strong feelings!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SentryTraced

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, GetX is not super common in nest was just an initial idea. I like SentryTraced if everyone is happy with that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to SentryTraced

Copy link
Member

@lforst lforst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few things that should be adressed but otherwise looks great.

Comment on lines 19 to 23
try {
return await originalMethod.apply(this, args);
} catch (e) {
captureException(e);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h: We do not want to wrap this with a try-catch-captureException. We only want to capture errors when they bubble up to an unexpected place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@@ -1,3 +1,5 @@
export * from '@sentry/node';

export { init } from './sdk';

export * from './span-decorator';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h: In the index file, let's be specific about what we export. This is to avoid accidentally widening the API surface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

const originalMethod = descriptor.value as (...args: any[]) => Promise<any>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
descriptor.value = async function (...args: any[]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h: We should not modify the return value. Currently we are wrapping all non-promise return values in a Promise. To fix this we can just remove all async and await keywords and everything will work perfectly fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

expect.objectContaining({
span_id: expect.any(String),
trace_id: expect.any(String),
data: expect.any(Object),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: Let's assert on the sentry.origin and sentry.source attibutes in the data object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I explicitly assert the data object now, there is no sentry.source property though

Comment on lines 80 to 83
@SentryTraced('wait function')
async wait() {
return new Promise(resolve => setTimeout(resolve, 500));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: We could add a second method that is not async and assert on it in the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean a second non-async function and then check whether the transaction includes spans for both?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@nicohrubec nicohrubec mentioned this pull request Jul 4, 2024
@nicohrubec nicohrubec linked an issue Jul 4, 2024 that may be closed by this pull request
@nicohrubec nicohrubec requested a review from lforst July 4, 2024 12:46
@nicohrubec nicohrubec merged commit 41d946e into develop Jul 4, 2024
87 of 88 checks passed
@nicohrubec nicohrubec deleted the nh/nestjs-span-decorator branch July 4, 2024 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

startSpan decorator to get spans for arbitrary functions
3 participants