-
-
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
ref(node): Move non-handler code out of handlers
module
#5190
Conversation
size-limit report 📦
|
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.
Technically this PR has a breaking change, in that now all Node events will have runtime and servername data, whereas before only events generated by our middleware have had it. (So, for example, if you've built a CLI in Node and are monitoring it with Sentry, your events will now include this data.) This feels like an okay thing to me, but I'm open to other opinions.
I think it's a non-issue - more like a feature actually! We've never hesitated with adding additional tags/contexts before. I did ask about moving stuff into a default integration, maybe that might appease folks who would want to turn it off (idk who would though).
version: global.process.version, | ||
}, | ||
}; | ||
event.server_name = this.getOptions().serverName || global.process.env.SENTRY_NAME || os.hostname(); |
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.
What do you think about putting this event mutation into a default integration instead of in the prepareEvent
step here?
This is the pattern most of the other SDKs follow for 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.
Interesting idea. I looked but didn't actually find any examples where we're using an integration to just set a few pieces of metadata. Which ones were you thinking of?
TBH, my gut feeling on it is that it feels kinda like overkill - it's a lot of machinery to wrap two lines of code, no? (Also, I know bundle size isn't as much of a thing on the node side of things, but given serverless functions it's still something to be at least vaguely aware of, so I'd only want to do this if it seemed worth the extra code.)
Let's wait and see if anyone complains, and then if we need to pull it into an integration so that people can shut it off, we can do that.
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.
Sure that sounds fine to me!
export interface HttpFunctionWrapperOptions extends WrapperOptions { | ||
parseRequestOptions: ParseRequestOptions; | ||
// TODO (v8): Remove this | ||
interface OldHttpFunctionWrapperOptions extends WrapperOptions { |
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 applies to the other items that are todo v8. Would you mind updating #5194 when you merge this? In the issue we probably just want a link to the PR doing the deprecation, and a short sentence about how it is replaced.
If we do this now, it'll be much less work for us to figure it out what to do for v8, we can just look at the issue and check off the items.
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.
Done.
packages/node/src/requestdata.ts
Outdated
return extractExpressTransactionName(req, { path: true }); | ||
} | ||
case 'handler': { | ||
return req.route?.stack[0].name || '<anonymous>'; |
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.
return req.route?.stack[0].name || '<anonymous>'; | |
return req.route?.stack[0]?.name || '<anonymous>'; |
Feels like one of those that will happen, just a matter of time 😄
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.
Happy to add it, but I actually am not sure it's possible for stack
to be empty. If you look at the Express router here and here, you can see that every route gets at least a layer for /
added to its stack. (It's been more than a year since I last mucked about in the Express innards trying to solve #3155, so I wouldn't swear that there isn't some way around stack
having at least one entry, but I don't think so.)
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.
Since you already doing route?
I wouldn't mind, my only concern is that far too often, the correct
assumptions were true only at X given time.
Again, there is nothing wrong at all as of today. Just that off-by-one errors are a thing 😄
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.
It's true. And as I said, happy to add it. (You'll see that in fact, I already have!)
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.
Nice refactoring! Looks good to me overall. I agree that the "breaking" change is fine in this case.
expect.assertions(10); | ||
expect.assertions(9); |
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.
Why did the number of expected assertions decrease?
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.
Because of the removal of the expect
on line 49, which happened because that info is now set by the node client, not the aws integration.
de6b20f
to
c252036
Compare
c252036
to
31c6675
Compare
This change broke the Electron SDK upgrade since it overrides the sentry-javascript/packages/node/src/client.ts Lines 143 to 149 in fb267e0
|
Perhaps we should move that logic into an integration then! cc @lobsterkatie |
…5257) (See #5190 for a detailed description of the motivation for and main substance of this change. TL;DR, isomorphic frameworks like Nextjs need this code to live in a neutral location (rather than in the node package) so it can be used in a browser setting as well.) This is a second take on #5190, which had to be reverted because it relied on a peer dependency (`cookie`) which browser-only apps wouldn't have installed. Even if those code didn't _use_ `cookie`, they still failed to compile because without `cookie` installed, `@sentry/utils` didn't typecheck correctly. This fixes that problem by using `cookie` (and `url`, for node 8 compatibility) only as injected dependencies, not as direct ones. It also creates node-specific versions of the relevant functions (`parseRequest`, now renamed `addRequestDataToEvent`, and `extractRequestData`) which do the injection automatically. If the dependencies aren't passed (as would be the case in a browser setting, or when using the functions directly from `@sentry/utils`), the code about cookies no-ops, and the code about URLs uses `URL`, which should be defined in all modern browsers and Node 10 and above. Other changes from the original PR: - Now only the backwards-compatibility-preserving wrappers of the legacy code live in `handlers.ts`, while the legacy code itself lives in its own file. This both makes it easier to delete in the future and ensures that treeshaking algorithms which only work file-by-file (rather than function-by-function) are able to exclude that code. (Though it's being kept until v8 because it's part of the node package's public API, it's no longer used anywhere in the SDK.) - Using DI changed the options interface for both of the functions in question, which in turn required a bit more gymnastics in terms of preserving and test backwards compatibility, specifically in the serverless package and the backwards-compatibility tests. This will make it a little harder to delete the old stuff when it comes time, but there are TODOs which hopefully will make it clear enough what needs to happen. - There's a new `CrossPlatformRequest` type for use in place of `ExpressRequest`. A few helper functions have also been renamed to make them less Express-centric.
Currently, the
handlers
module includes not just our middleware handlers but also a bunch of code for extracting context data and applying it to events. That latter code is indeed used in the handlers, but it's also used in a number of other places in the repo. This pulls that code into its own module in@sentry/utils
, to make it possible to use in a platform-agnostic context.Key changes:
requestData
module in@sentry/utils
to hold the data extraction code (and a new test file for its tests).handlers
module for backwards compatibility. (IOW, callingHandlers.someFunc()
still works, but it's now just a passthrough tosomeFunc
from the new module.)describe
s in the tests, to run the tests against both the real functions and their wrappers, to make sure the wrappers work identically to the real functions. (This means that for the moment, the test file needs to live in@sentry/node
, since it depends on the wrappers as well as the real functions. Once the wrappers are removed, the test file can be moved to@sentry/utils
.)parseRequest
has been renamedaddRequestDataToEvent
for greater accuracy and clarity for the reader. (The corresponding options type has also been renamed.)parseRequest
, but which have nothing to do with the request and are Node-only (namelyruntime
andserver_name
) are now set by the Node client. As a result, they no longer need to be set separately in the serverless package. (The exception isserver_name
in the AWS integration, because it pulls from a non-standard location.)Notes:
parseRequest
/addRequestDataToEvent
in the nextjs SDK, in code which can run either in Node or the browser, which means it can't be exported from@sentry/node
.runtime
andservername
data, whereas before only events generated by our middleware have had it. (So, for example, if you've built a CLI in Node and are monitoring it with Sentry, your events will now include this data where they didn't before.) This feels like an okay thing to me, but I'm open to other opinions.