-
Notifications
You must be signed in to change notification settings - Fork 213
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: Add initial profiling support #626
Conversation
Let us get back to you later today @vaind |
Line numbers are not displayed next to the function name. They are shown in the tooltip. Right now, they are not shown in the tooltip because we don't have a filename in the appropriate field of a frame object. But that's not the reason it appears in several groups. You should look at where those line numbers are coming from and if they are correct. The UI is behaving has expected. |
All frames have a (relative) file name or abs_path. Not sure why this distinction was implemented in sentry-go but I didn't want to touch that. Is this a problem for the profiling product?
The line numbers are correct. You see multiple frames for a single function because these represent different lines in the same function - they all relate to actual code being executed. For example for {"data":{},"function":"findPrimeNumber","in_app":true,"lineno":67,"module":"main","abs_path":"C:/dev/sentry-go/_examples/profiling/main.go"}
{"data":{},"function":"findPrimeNumber","in_app":true,"lineno":68,"module":"main","abs_path":"C:/dev/sentry-go/_examples/profiling/main.go"}
{"data":{},"function":"findPrimeNumber","in_app":true,"lineno":75,"module":"main","abs_path":"C:/dev/sentry-go/_examples/profiling/main.go"}
{"data":{},"function":"findPrimeNumber","in_app":true,"lineno":77,"module":"main","abs_path":"C:/dev/sentry-go/_examples/profiling/main.go"} You can see that these frames refer to lines 67, 68, 75 and 77, and if you look at the function code you can match that exactly to the code being executed: Most languages don't go into this much detail in their stack traces and only give you the leaf function once. This is not true for Go as it gives you actual lines of code being executed at the time the stack trace dump has been captured. |
I don't see frames having a relative filename and yes, it's a "problem" as we'll not show the filename + line number unless we have the filename and the line number. Not sure why the Go SDK doesn't send that. If you want to show filename + line number, the SDK will have to provide us with a relative filename (on top of the
So, that's an issue. We're expecting the line number where the function is called, not the line number executed at the time of capture. So, in this case, we'd expect 49 for We can flag that as a known issue and move on though. |
After checking with the team, it seems the situation is a bit more complicated. I think the idea was to get the data how we describe it but platforms reporting line numbers report them the way Go is. We're discussing what we want to do about this, it seems it's something we haven't paid a lot of attention to. We wouldn't want to merge based on just name though. |
There is filename and line number, it is an absolute path because there's no way resolve it to a relative one in Go. It just just not the
OK, let me know if there's something that should be done here in the Go SDK |
I don't think so right now, I would proceed with this, we know the issue and it's common to the rest of the platforms so let's not consider it as part of this effort. |
Yes, Go is correct to report things that way.
In that case, the Python SDK is not being a "good citizen" since it's reporting the absolute path in the Obviously, reality is different, but I don't think we want to show the absolute path in case the filename is missing. I think for now we should keep the status quo (not showing filename and line numbers) as we're having a lot of discussions around all that. Perhaps we'll start showing the line number directly after the frame name regardless if we have a filename or not. I would proceed with marking that as known issues. |
thanks for the update, just wanted to remark on one bit:
Just to note, this has been discussed many times in the past, also for other SDKs and while I don't know what's the general consensus at the moment, the concern of absolute paths being PII and thus not showing them is void because they're already part of the profile reported to Sentry.io and is also part of the downloadable JSON. |
Yes, I agree, they are not exactly private anyway, I was explaining how we came to not showing the absolute path when we built the UI when we joined Sentry. Now, I think there's still concerns around how long they are but the PII reason tends to fade away. |
As for merging frames, after thinking I wouldn't do that in, at least not in this case - if you think about it, the UI already gets the information for file and line numbers so if it's passed on to the user, they can figure out exactly which line of the function is the slow one, instead of just guessing based on the function name. But there are arguments in the other direction too si it's not a clear win either way. |
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.
Can we create follow-up issues for the TODO comments?
Also, we will require changes to docs and the product itself.
Will you also work on those?
Co-authored-by: Michi Hoffmann <[email protected]>
I think I've done so for the bigger issue of envelope build refactoring. For the smaller internal TODOs, I'll do a follow-up PR directly.
Sure, I can prepare docs. Not sure what you mean about the followups on the product itself. |
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.
🏄
docs PR: getsentry/sentry-docs#7127 |
This brings profiling support based on calling
runtime.Stack()
periodically to capture stack traces for all goroutines. This is also what the "goroutine" profiler does in the pprof package but pprof only allows you to write the profile in full after it has been captured and does so to a string which we would then need to parse, see WriteTo().Implements #630
How this implementation works:
ProfilesSampleRate
which defines a sampling rateruntime.Stack()
unfortunately, it only outputs strings. There's an alternative -runtime.GoroutineProfile()
(which it uses under the hood). But we cannot use it because the returned value from that function doesn't give us any identification of individual goroutines. I've created an issue in the runtime - if that's ever implemented, we should make the switch to reduce profiling overhead (avoid serialization to string & parsing back)As can be seen from the benchmarks results, the profiling itself is very fast, with each collection taking fractions of a millisecond (depends on the number of goroutines). I've prioritized performance while trying to sacrifice readability as little as possible.
Followups:
Event
. This is because there's currently nocaptureEnvelope()
, onlycaptureEvent()
- ideally we should make the refactoring and internally use captureEnvelope() which would allow us to compose any number of items to a single envelope before handing it over to transport