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: manually capture errors #1374

Merged
merged 17 commits into from
Aug 29, 2024
Merged

feat: manually capture errors #1374

merged 17 commits into from
Aug 29, 2024

Conversation

daibhin
Copy link
Contributor

@daibhin daibhin commented Aug 20, 2024

Changes

Add the manual captureException method to the SDK

Copy link

vercel bot commented Aug 20, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
posthog-js ✅ Ready (Inspect) Visit Preview Aug 29, 2024 9:35am

Copy link

github-actions bot commented Aug 20, 2024

Size Change: +1.71 kB (+0.15%)

Total Size: 1.17 MB

Filename Size Change
dist/array.full.js 335 kB +443 B (+0.13%)
dist/array.js 156 kB +412 B (+0.27%)
dist/exception-autocapture.js 10.4 kB +27 B (+0.26%)
dist/main.js 157 kB +412 B (+0.26%)
dist/module.js 156 kB +412 B (+0.27%)
ℹ️ View Unchanged
Filename Size
dist/recorder-v2.js 110 kB
dist/recorder.js 110 kB
dist/surveys-preview.js 59.8 kB
dist/surveys.js 66 kB
dist/tracing-headers.js 8.26 kB
dist/web-vitals.js 5.79 kB

compressed-size-action

src/posthog-core.ts Outdated Show resolved Hide resolved
@@ -1815,6 +1815,11 @@ export class PostHog {
return !!this.sessionRecording?.started
}

/** Checks the feature flags associated with this Survey to see if the survey can be rendered. */
captureException(error: Error, additionalProperties?: Properties): void {
this.exceptionObserver?.captureException(error, additionalProperties)
Copy link
Member

Choose a reason for hiding this comment

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

hmmmm....

exception capture is ~10% of the bundle if it wasn't lazily loaded.

if someone doesn't have exception capture enabled posthog will still advertise this method as part of its contract, what should it do?

just log?

Copy link
Member

Choose a reason for hiding this comment

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

exception capture enabled

this is mostly about the auto-capture, right? people could still do capture(thisError) manually, if we allow that, it should always be part of the bundle.
Maybe we need a different config for auto-capture and manual capture, so people that don't use either, don't pay the bundle price.

Comment on lines 121 to 125
captureException(error: Error, additionalProperties: Properties = {}) {
const errorEventArgs: ErrorEventArgs = [error.message, undefined, undefined, undefined, error]
const errorProperties = errorToProperties(errorEventArgs)
this._captureException({ ...errorProperties, ...additionalProperties })
}
Copy link
Member

Choose a reason for hiding this comment

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

yep, I think this is the 3% bump in bundle... we're pulling in errorToProperties which would otherwise not be imported unless exception capture is configured

I think this should check if error stuff is on the window and log if not
and we give people a local config to turn it on (if it's not already possible)

if lots of people use it we can make it the default or have remote config to allow manual but not auto capture???

or we add this and stand the 3% bump for everyone but that feels wrong IMHO open to challenge

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Certainly wasn't my intention to increase the default bundle size... I actually thought I'd avoid it by moving errorToProperties into this file rather than src/posthog-core.ts.

I pushed another commit that hopefully moves things in the right direction but not sure how to fully evaluate this. Is there any prior art for how we do this with something similar?

Do you think there should be a local config to enable manual capture if someone doesn't have autocapture enabled? It feels like a bit of a gotcha to me but get that it might be necessary if we want to ensure the bundle size stays small for folks not using it. I wonder what the flow looks like for manually showing surveys, we should make sure that both function the same way at the very least

Copy link
Collaborator

Choose a reason for hiding this comment

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

the core capture in surveys is part of the main SDK - this is always available and anyone can use it. The extension is all the code for showing surveys.

What imo would be ideal here (and what we did for surveys as well) is to figure out how the manual exception capture API would look like, and re-use that inside the extension as well (instead of the manual _captureException function) - I think the interface you have already looks reasonable, and the personURL can be just another part of additionalProperties.

The contention here is that the errorToProperties function (+dependents) is pretty big, while the surveys core code is pretty small, so taking the same approach might not make the most sense.

As such, I think there are two three options:

  1. Keep basic manual exception capture as part of main SDK (which does not do stack trace parsing). And when they enable autocapture/stack trace parsing - we do this parsing to get all the details of the error.
  2. Since autocapture is 10% of bundle and stack trace parsing is 3%, we can make two extensions: One for manual capture, one for autocapture. Enabling autocapture also enables manual capture.
  3. Make stack trace parsing part of the core SDK, 3% isn't that big of a hit (what you already currently have).

I'm currently leaning towards (1), specially because least effort currently, and gives us enough information (by users having to turn on autocapture to get the stack trace details) to make a decision whether (2) or (3) is worth it. Also doesn't affect current bundle size for existing users 👌 . My hypothesis is that we'll find out people who want to do manual capture would be very happy with having autocapture as well, so would anyways turn it on.

Copy link
Collaborator

Choose a reason for hiding this comment

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

re-reading, looks like Paul said the exact same thing but in fewer words 🙈 🙈

Copy link
Member

Choose a reason for hiding this comment

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

it is a rare event that I'm the most concise person 🤣

captureException(errorProperties: Properties) {
captureException(error: Error, additionalProperties: Properties = {}) {
if (!window || !this.isEnabled || this.isCapturing) {
logger.error(LOGGER_PREFIX + ' error tracking is not enabled - cannot capture exception')
Copy link
Member

Choose a reason for hiding this comment

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

I think the !window has to be a different logging message so as not to mislead customers or us when debugging things

@daibhin
Copy link
Contributor Author

daibhin commented Aug 27, 2024

@pauldambra @neilkakkar I think I followed what you both suggested, hopefully I haven't overcooked things and made it overly complicated. There's still tests to be fixed but wanted to make sure I was on the right path first. Size change looks to be down but I'm surprised it's still ~1.5%. Does that seem reasonable?

@neilkakkar
Copy link
Collaborator

yeah looks reasonable! I think the only thing missing is upgrading to have the stack if autocapture is enabled, when capturing custom exceptions. (and you can't do this via import, this needs to be set on the window when autocapture is enabled)

The 2.5kB still seems a bit surprising, that's effectively one page of text. Could you check if this goes down if you don't import errorPropertiesFromError and just inline it?

@daibhin
Copy link
Contributor Author

daibhin commented Aug 28, 2024

@neilkakkar yep, inlining is a big win. Down to 329 B (from 2.5kB)

Copy link
Collaborator

@neilkakkar neilkakkar left a comment

Choose a reason for hiding this comment

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

nicely done! 🚀

expect(captures[2].properties.$exception_personURL).to.match(
/http:\/\/localhost:\d+\/project\/test_token\/person\/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/
)
expect(captures[2].properties.$exception_source).to.eql(undefined)
Copy link
Collaborator

Choose a reason for hiding this comment

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

minor nit: check extra_prop is set too?

cy.wait(1500)

cy.phCaptures({ full: true }).then((captures) => {
expect(captures[2].properties.$exception_stack_trace_raw).to.exist
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: confirm this is also wat even am i and not some other autocaptured exception (since all of those will have stack traces too)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bump minor Bump minor version when this PR gets merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants