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

Add frame filtering functionality #23

Merged

Conversation

prskr
Copy link
Contributor

@prskr prskr commented Jan 3, 2022

In scenarios when zapsentry is used with zap and go-logr the existing frame filtering mechanism does not skip frames of the go-logr adapter.

This PR adds an interface FrameFilter allowing any user to filter frames just like they want to.
I refactored the existing two filters to some default filter types that might come in handy for most users.

While reading the docs regarding the Sentry SDK I also stumbled upon a deprecation notice of sentry.Event.Extra and that sentry.Scope should be used instead.
I adopted this change in the API, too, but I could also split both changes into two PRs if preferred?

Copy link
Collaborator

@grongor grongor left a comment

Choose a reason for hiding this comment

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

Overall I like these changes :) Good work! 👍

disclaimer: I'm not a maintainer, but a mere contributor :)

core.go Outdated
event.Threads = []sentry.Thread{{Stacktrace: stacktrace, Current: true}}
}
}

_ = c.client.CaptureEvent(event, nil, c.scope())
s := c.scope()
s.SetContext("fields", clone.fields)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I wouldn't merge this within "Add frame filtering functionality" (and other changes related to the Extra/Context). I think you should split this into two PRs.

core.go Outdated
@@ -286,18 +327,19 @@ func (l *LevelEnabler) Enabled(lvl zapcore.Level) bool {
// follow same logic with sentry-go to filter unnecessary frames
// ref:
// https://github.com/getsentry/sentry-go/blob/362a80dcc41f9ad11c8df556104db3efa27a419e/stacktrace.go#L256-L280
func filterFrames(frames []sentry.Frame) []sentry.Frame {
func filterFrames(frames []sentry.Frame, filters FrameFilters) []sentry.Frame {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd refactor this as a method of the core so that we don't have to pass the filters here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And it would be great to have a test for this. Just a bonus :)

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'll look into it

core.go Outdated
}

func (ff FrameFilters) AnyMatch(frame sentry.Frame) bool {
for idx := range ff {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd stick with the well-known i variable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

can do if you really prefer it that way - I tend to use something like idx because IMHO i is rather difficult to spot/search but of course I'll adopt to the existing code style of the existing code base

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not my repo, not my place to say...but i and j are, I would dare to say, universally understood and standard in most of the languages and projects. I wouldn't mind having index variable here if you really wanted to be verbose (I actually prefer this naming style with most other variables), but having a weird hybrid (not short and not verbose) just doesn't make sense to me :D

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'll change it to either index or i can't promise now what it'll be, I tend to index to avoid another round of hide and seek 😄 you're right that they are well known and understood but depending on the font personally I've issues to find them

core.go Outdated
strings.HasPrefix(frames[i].Function, "go.uber.org/zap")) &&
!strings.HasSuffix(frames[i].Module, "_test") {
return frames[0:i]
for idx := 0; idx < len(frames); {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd stick with well-known i variable

core.go Outdated
copy(frames[idx:], frames[idx+1:])
}
frames = frames[:len(frames)-1]
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please refactor this to "return early" (replace else with continue in the other branch). And also, adding empty lines after the end of a block improves readability IMO, but that is just my opinion.

example_logger_test.go Show resolved Hide resolved
core.go Outdated

type (
FrameFilter interface {
SkipFrame(f sentry.Frame) bool
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't like this name ... I think I'd prefer Filters or something similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tbh I don't like Filters either 😅 how about:

type FrameSkipper interface {
    Skip(f sentry.Frame) bool
}

to honor the interface name <-> function name similarity 'pattern' but Filters doesn't really fit, does it?

Copy link
Collaborator

@grongor grongor Feb 3, 2022

Choose a reason for hiding this comment

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

Well, I don't like that either, and let me tell you why: when I look at just the interface, I would guess that the implementation is expected to skip the frame (somehow, whatever that means) and return the result of such operation. Which obviously isn't what we want implementations to do here.

But hey, maybe it's just me. I'm also not a native English speaker, so that might influence my feeling about it a bit too...

edit: here are some examples which I would expect here: ShouldSkip, ShouldFilter, Skips, Filters, Match, Matches

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now I get your point...not to get too Java alike but taking your suggestion into account, would you approve:

type FrameSkipPredicate Interface {
    Matches(frame sentry.Frame) bool
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

I actually don't see a problem with being "java-like", because many Java patterns are good (and many are, of course, horrible). I actually tend to write Go more like I would write PHP, Java and other similar languages and it works quite well. I don't like the Go philosophy to try to write every single variable name as short as possible :D

The FrameSkipPredicate truly sounds like a java port 🤣 But yeah, I would approve that as it IMO can't be mistaken for anything else, and it covers the functionality perfectly. FrameMatcher or FrameFilterMatcher would be more in line with Go style though. Anyway, now I'm just being too pedantic :D What matters most is that the functionality makes sense and is a good addition :-)

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 actually already thought of something like a Matcher but I used that term so often in the last time that I figured something else would be nice 😄 but I guess it just makes sense most so I'll take that and update the code tomorrow.

Thanks for the input and the patience! 😊

core.go Outdated
return strings.HasPrefix(frame.Function, string(f))
}

func (ff FrameFilters) AnyMatch(frame sentry.Frame) bool {
Copy link
Collaborator

@grongor grongor Feb 3, 2022

Choose a reason for hiding this comment

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

I think that a better design would be to have FrameFilters implement the FrameFilter interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right, I'll update this

@prskr prskr force-pushed the use-context-instead-of-extra branch from 5b72cb4 to 32b95d2 Compare February 21, 2022 08:58
@prskr
Copy link
Contributor Author

prskr commented Feb 21, 2022

@grongor I finally had some time to apply your suggestions 🙈
I hope I didn't miss anything - if you spot anything else to refine, do not hesitate to let me know 😊

@TheZeroSlave
Copy link
Owner

hey guys, sorry for big delay. im trying to look it in a couple of days

@vadimlarionov
Copy link

Hey guys! @TheZeroSlave, this PR looks good and useful. Could you check it and merge, if it's ok?

@prskr
Copy link
Contributor Author

prskr commented May 4, 2023

Haven't heard anything and left the company I originally implemented this PR (don't know if they're still using my fork 😅 @farodin91 ) but could rebase and resolve conflicts probably in 2 week's or so if there's still interest

@vadimlarionov
Copy link

From my point of view, yes, it is. The PR is useful to exclude frames from wrappers. So, it would be nice

@TheZeroSlave
Copy link
Owner

@baez90 hi, if you rebase it, i will merge it )

@farodin91
Copy link

@TheZeroSlave I cloud recreate the PR and rebase it.

@TheZeroSlave
Copy link
Owner

TheZeroSlave commented Jun 23, 2023

@TheZeroSlave I cloud recreate the PR and rebase it.

@farodin91 yeah, that's good idea, thanks!

@prskr
Copy link
Contributor Author

prskr commented Jun 23, 2023

@farodin91 no worries I'll rebase it on Sunday :)

@prskr prskr force-pushed the use-context-instead-of-extra branch from 32b95d2 to 9ef5ead Compare June 24, 2023 10:16
This allows to remove any kind of frame from the stacktrace sent to Sentry e.g. if zap is used in combination with go-logr.
@prskr prskr force-pushed the use-context-instead-of-extra branch from 9ef5ead to 6bd19be Compare June 24, 2023 10:21
@prskr
Copy link
Contributor Author

prskr commented Jun 24, 2023

Finished rebasing, let me know if there are any further change requests 😄

@TheZeroSlave
Copy link
Owner

Finished rebasing, let me know if there are any further change requests 😄

thnx, im watching it.

@TheZeroSlave TheZeroSlave merged commit dde0fb2 into TheZeroSlave:master Jun 26, 2023
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.

5 participants