#Instrumenting a user action with debounce (Angular, Browser JS SDK)

13 messages · Page 1 of 1 (latest)

stable gate
#

Howdy 👋 I just happened to come on here at the right time to ask my question so, great timing 😅

We have a screen where we recalculate and re-render a report when the user changes a form value.
I want to measure the user waiting time, meaning between the user typing (as close to keystroke as possible) to the report being rendered. And there's API calls in the middle of this so ideally I use tracing rather than metrics to capture them underneath.

However we have debounce logic (500ms), so that if a user is making changes in quick succession, we don't fire off several requests.
I'm trying to figure out the best approach here. I could

  1. start my span after the debounce, but then I'm missing the 500ms after their last change.
  2. start my span before the debounce, but if for example the user spends, 2000ms typing every 400ms, we are capturing 2000ms extra time they weren't actually waiting
    3.start the span before the debounce, but update the start time somehow** (is this possible?)**
  3. start the span before the debounce, but discard and create a new span if the user makes another action (is this possible?)
  4. I am trying too hard and should approach this problem differently
balmy patio
#

Hi @stable gate as you've correctly identified we don't automatic instrumentation for a scenario like this.

Options 3 or 4 would probably be correct. The issue is that they have different caveats.

For example in option 3 you need to keep track of the timestamp of whenever the debounce logic runs for the last time, and keep it up to date. then when you finsih the transaction (after the request cycle finishes) you need update the start time of the transaction.

For option 4, you need to start a new transaction and then place it on the scope (replacing the old transaction) every time the debounce logic runs. This might cause a little overhead, but it shouldn't be too much for the client. This prevents you from needing to do anything other than manually finish the transaction, when the request is complete.

stable gate
#

Thanks @balmy patio , the code I'm hooking into already has an observable stream so it should be easy to tap into to do either 3 or 4. But it's more about if it's actually possible. I don't know how to modify the start time, or how to discard the current span via the SDK!

balmy patio
#

It was possible but it looks like the methods used to update the start timestamp of a span are not avaialble in v8 (coming soon). I suppose option 4 is the correct method then

stable gate
#

ah okay, it did feel dodgy anyway to retrospectively widen the time anyway 😅
how would I do 4?

balmy patio
#

start a root span as you normally would and place it on the scope, then when the debounce the logic runs again start a new root span and then replace the span on the scope

stable gate
#

Sorry do you have an example of that? I'm not familiar with where the 'replacing' would happen, I've so far just been using Sentry.startSpanManual

balmy patio
#

ah I see. so in this case you can assign the span to a variable and then replace the reference. This might meen let vs const

balmy patio
#

we used to have a better way of doing this under the old span operations let me just check with engineering what the new method is

stable gate
#

okay thanks, still slightly lost but will wait for that before a follow up, it's evening for me now anyway 🥱 . thanks for the help!

balmy patio
#

so the issue you'll potentially see with starting a span and then restarting it is that if there are any child spans you might be interested in they'll get clobbered when you restart it.

We talked about this and we all think that the most relevant thing to measure is the request at the end of the timeout because the timeout will always be 500ms no matter how many times you debounce the request

maybe theres important context here but we think you should call start spanManual in the callback but before the request

stable gate