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

ref(core): Reduce inboundfilters bundle size #4625

Merged
merged 11 commits into from
Mar 23, 2022

Conversation

AbhiPrasad
Copy link
Member

@AbhiPrasad AbhiPrasad commented Feb 23, 2022

Had this branch lying around for a while, went back and cleaned it up

  • Move all private methods from InboundFilters into their own standalone functions
  • Pass in options explicitly so you can do allowUrls.length instead of options.allowUrls.length (can't minify allowUrls in the 2nd option)
  • Remove typeof self logic since now we explicitly pass everything in
  • Rewrite tests to stop relying on private methods but instead assert on event processor

@AbhiPrasad AbhiPrasad requested review from a team, Lms24 and lobsterkatie and removed request for a team February 23, 2022 20:47
@github-actions
Copy link
Contributor

github-actions bot commented Feb 23, 2022

size-limit report

Path Base Size (20b3e38) Current Size Change
@sentry/browser - ES5 CDN Bundle (gzipped + minified) 19.66 KB 19.58 KB -0.4% 🔽
@sentry/browser - ES5 CDN Bundle (minified) 62.83 KB 62.46 KB -0.59% 🔽
@sentry/browser - ES6 CDN Bundle (gzipped + minified) 18.24 KB 18.19 KB -0.28% 🔽
@sentry/browser - ES6 CDN Bundle (minified) 56.15 KB 55.96 KB -0.34% 🔽
@sentry/browser - Webpack (gzipped + minified) 22.78 KB 22.72 KB -0.24% 🔽
@sentry/browser - Webpack (minified) 80.16 KB 80.38 KB +0.28% 🔺
@sentry/react - Webpack (gzipped + minified) 22.81 KB 22.76 KB -0.24% 🔽
@sentry/nextjs Client - Webpack (gzipped + minified) 47.78 KB 47.69 KB -0.18% 🔽
@sentry/browser + @sentry/tracing - ES5 CDN Bundle (gzipped + minified) 25.53 KB 25.46 KB -0.3% 🔽
@sentry/browser + @sentry/tracing - ES6 CDN Bundle (gzipped + minified) 23.85 KB 23.81 KB -0.19% 🔽

@AbhiPrasad AbhiPrasad added this to the Treeshaking / Bundle Size milestone Feb 23, 2022
return true;
/** JSDoc */
export function _mergeOptions(
intOptions: Partial<InboundFiltersOptions> = {},
Copy link
Member

Choose a reason for hiding this comment

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

What is int in intOptions? Could we give this a clearer name?

Copy link
Member Author

Choose a reason for hiding this comment

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

integrationOptions, we can make that clearer (internalIntegrationOptions?)

I tried not to touch the original variables names as much as possible to make it clear how we've migrated from before -> after.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, got it. Yeah, I think spelling it out is clearer.

And yeah, if you want this to be a pure moving-stuff-around PR and then integrate some of the improvements separately, I think that's fine and I get the reasoning.

packages/core/src/integrations/inboundfilters.ts Outdated Show resolved Hide resolved
packages/core/test/lib/integrations/inboundfilters.test.ts Outdated Show resolved Hide resolved
import { InboundFilters, InboundFiltersOptions } from '../../../src/integrations/inboundfilters';

/** JSDoc */
function createInboundFiltersEventProcessor(
Copy link
Member

Choose a reason for hiding this comment

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

It took me a second or third read to totally grok this function, specifically the fact that

a) all of the machinery is only there in aid of the side effect of creating the event processor, and
b) as a consequence, these aren't mocks I need to care about later on in the tests.

It's also not totally clear to me as a reader (yet) why what we want is the event processor rather than a dummy instance of the integration.

I think it would be helpful to add a docstring explaining those things.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's also not totally clear to me as a reader (yet) why what we want is the event processor rather than a dummy instance of the integration.

This is also a function of the unit testing of integrations being kind of inconsistent.

Will add a doc string

packages/core/test/lib/integrations/inboundfilters.test.ts Outdated Show resolved Hide resolved
packages/core/test/lib/integrations/inboundfilters.test.ts Outdated Show resolved Hide resolved
Comment on lines 84 to 93
if (_isSentryError(event, options.ignoreInternal)) {
if (isDebugBuild()) {
logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`);
}
if (this._isIgnoredError(event, options)) {
if (isDebugBuild()) {
logger.warn(
`Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`,
);
}
return true;
return true;
}
Copy link
Member

Choose a reason for hiding this comment

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

Rather than passing the option and checking it in _isSentryError (and it potentially turning effectively into a no-op), I think it would be better to check it here, and not even call the function if the question is made moot by the option's value.

(That said, do you know why we even have this option? It's not documented, and it's not used anywhere in any sentry repo. Could we just get rid of it?)

Copy link
Member Author

Choose a reason for hiding this comment

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

We use this to drop all SentryError errors, which is used pretty extensively throughout the codebase. I don't think we want people to turn this off.

For example, we throw a SentryError if we don't parse a DSN properly.

I think it would be better to check it here, and not even call the function if the question is made moot by the option's value

Great point, will change.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we want people to turn this off.

Exactly. And we don't anywhere. What I'm asking is why we need to have an off switch at all.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a good question. I'm going to open up a follow up issue - but leave it like this for now.

if (!options.allowUrls || !options.allowUrls.length) {
return true;
/** JSDoc */
function _isSentryError(event: Event, ignoreInternal: Partial<InboundFiltersOptions>['ignoreInternal']): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
function _isSentryError(event: Event, ignoreInternal: Partial<InboundFiltersOptions>['ignoreInternal']): boolean {
function _isSentryError(event: Event, ignoreInternal: boolean): boolean {

It's not going to change, so why not just say what it is?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's not going to change, so why not just say what it is?

It's to communicate intent - the whole purpose of aliasing types.

packages/core/src/integrations/inboundfilters.ts Outdated Show resolved Hide resolved
Copy link
Member

@lobsterkatie lobsterkatie left a comment

Choose a reason for hiding this comment

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

Three more, same idea as above.


/** JSDoc */
function _isDeniedUrl(event: Event, denyUrls: Partial<InboundFiltersOptions>['denyUrls']): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
function _isDeniedUrl(event: Event, denyUrls: Partial<InboundFiltersOptions>['denyUrls']): boolean {
function _isDeniedUrl(event: Event, denyUrls: Array<string | RegExp>;): boolean {

(options.ignoreErrors as Array<RegExp | string>).some(pattern => isMatchingPattern(message, pattern)),
);
/** JSDoc */
function _isAllowedUrl(event: Event, allowUrls: Partial<InboundFiltersOptions>['allowUrls']): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
function _isAllowedUrl(event: Event, allowUrls: Partial<InboundFiltersOptions>['allowUrls']): boolean {
function _isAllowedUrl(event: Event, allowUrls: Array<string | RegExp>;]): boolean {

return false;
}
/** JSDoc */
function _isIgnoredError(event: Event, ignoreErrors: Partial<InboundFiltersOptions>['ignoreErrors']): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
function _isIgnoredError(event: Event, ignoreErrors: Partial<InboundFiltersOptions>['ignoreErrors']): boolean {
function _isIgnoredError(event: Event, ignoreErrors: Array<string | RegExp>;): boolean {

Copy link
Member Author

Choose a reason for hiding this comment

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

Although this may make that specific line, I like using the alias here, it makes things more consistent. Readers can scroll to the InboundFiltersOptions above and see the type exactly.

The alias makes the intent of the function very clear, and also communicates how exactly this function is being used - which I think is worth the extra search step a reader has to do to find the exact type.

My rationale here applies for the suggestions below.

Copy link
Member

Choose a reason for hiding this comment

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

All right - agree to disagree on this one.

I'm definitely with you that communicating intent and correct usage is important - that's why I'm pretty religious about adding full docstrings everywhere. When it comes to types, though, what I'm generally going for is ease of reading and the ability to understand quickly what something is - so that scrolling you mentioned is precisely what I'm trying to avoid.

(To be fair, it's not just you - I take issue with derived types in general. To me they're a tool of absolute last resort, and I only use them when I've utterly failed to get TS to accept any other, more direct description, and finally give up and say, Okay, TS, if you're going to be so difficult about it, you figure it out.)

Copy link
Member

Choose a reason for hiding this comment

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

All of the above said - if we are going to keep it as derived types, I don't think we need the Partial, do we?

Copy link
Member Author

@AbhiPrasad AbhiPrasad Mar 1, 2022

Choose a reason for hiding this comment

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

You're right, we can remove the Partial usage.

@lobsterkatie
Copy link
Member

  • Rewrite tests to stop relying on private methods but instead assert on event processor

This makes the tests a lot cleaner. Nice!

lobsterkatie added a commit that referenced this pull request Mar 2, 2022
As part of centralizing and unifying our CDN rollup config, this uses the config generation function introduced in #4650 to generate the config for all browser bundles.

Unlike many of the other PRs in this series, this one does actually have an effect on certain bundles, to wit:

- `_mergeOptions` is no longer a protected-from-minifcation property, as it's about to be extracted into a stand-alone function. (See #4625.)

- Up until this point, one difference between the `@sentry/browser` rollup config and all of the other rollup configs was the former's use of the `__SENTRY_NO_DEBUG__` flag to suppress logs in the minified bundles. Rather than add a parameter to the function controlling whether or not each package should use the flag, I decided it was better to just apply the flag to all minified bundles.
AbhiPrasad pushed a commit that referenced this pull request Mar 2, 2022
As part of centralizing and unifying our CDN rollup config, this uses the config generation function introduced in #4650 to generate the config for all browser bundles.

Unlike many of the other PRs in this series, this one does actually have an effect on certain bundles, to wit:

- `_mergeOptions` is no longer a protected-from-minifcation property, as it's about to be extracted into a stand-alone function. (See #4625.)

- Up until this point, one difference between the `@sentry/browser` rollup config and all of the other rollup configs was the former's use of the `__SENTRY_NO_DEBUG__` flag to suppress logs in the minified bundles. Rather than add a parameter to the function controlling whether or not each package should use the flag, I decided it was better to just apply the flag to all minified bundles.
@AbhiPrasad
Copy link
Member Author

Changed to remove the type alias

@AbhiPrasad AbhiPrasad requested a review from a team March 18, 2022 08:16
@AbhiPrasad AbhiPrasad enabled auto-merge (squash) March 18, 2022 08:49
@AbhiPrasad
Copy link
Member Author

Hmm idk what's going on with size-bot. Any ideas?

@AbhiPrasad
Copy link
Member Author

Size bot fixed itself 🙏

@AbhiPrasad AbhiPrasad requested a review from lforst March 23, 2022 13:11
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.

Big fan of this PR. Left some optional action items. The one on the ignoreInternal arg would be really nice to have.

}
return false;
/** JSDoc */
export function _mergeOptions(
Copy link
Member

Choose a reason for hiding this comment

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

(optional) Wondering if we should drop the underscore in the extracted function names...

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll leave it here for now, but I'll remove the JSDoc as per your comments below.

I left it with the underscore initially to minimize the diff, and make it clear as possible how the functions moved.

if (!options.allowUrls || !options.allowUrls.length) {
return true;
/** JSDoc */
function _isSentryError(event: Event, ignoreInternal?: boolean): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

Can we get rid of the ignoreInternal argument? It seems unrelated to what the function is saying it does.

The if (_isSentryError(event, options.ignoreInternal)) { above would become if (!options.ignoreInternal && _isSentryError(event)) {. Might even save some bytes 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

Good change, will do!

packages/core/src/integrations/inboundfilters.ts Outdated Show resolved Hide resolved
@AbhiPrasad AbhiPrasad requested a review from lforst March 23, 2022 17:28
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.

Thanks for implementing my feedback!

@AbhiPrasad AbhiPrasad merged commit 59a0cb6 into master Mar 23, 2022
@AbhiPrasad AbhiPrasad deleted the abhi-private-inboundfilter branch March 23, 2022 17:57
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.

None yet

3 participants