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

[Question] Best practices for throttling outgoing data? #2322

Closed
mmeluch opened this issue Apr 8, 2024 · 4 comments
Closed

[Question] Best practices for throttling outgoing data? #2322

mmeluch opened this issue Apr 8, 2024 · 4 comments

Comments

@mmeluch
Copy link

mmeluch commented Apr 8, 2024

Description/Screenshot
Recently, we've run into an issue where a very small percentage of users produced an excessive amount of logs due to a code error on our side - a 3rd party dependency was triggering a logged (trace) callback thousands of times per second.

Obviously, we should fix the issue on our side first, however, it made us think about avoiding such cases in the future. The most straightforward solution seems to be throttling of the outgoing user data, however, I am not sure how to approach this. Ideally, we want to keep the data complete for all non-abusive users, so no sampling (a critical message might get sampled out and we wouldn't be able to track down a technical issue on the customer's end).

My setup:

"@microsoft/applicationinsights-common": "^2.7.3",
"@microsoft/applicationinsights-react-js": "^3.2.3",
"@microsoft/applicationinsights-web": "^2.7.3"
"react": "^17.0.2",
"react-dom": "^17.0.2"

config: {
  instrumentationKey,
  eventsLimitInMem: 2000,
  isStorageUseDisabled: true,
  enableSessionStorageBuffer: false,
  maxBatchInterval: 10000,
  extensions: [this.reactPlugin],
  extensionConfig: {[this.reactPlugin.identifier]: { history: browserHistory }},
  enableUnhandledPromiseRejectionTracking: true
}

Additional Context
I am currently aware of the following settings related to data throttling:

  • eventsLimitInMem: The number of events that can be kept in memory before the SDK starts to drop events. By default, this is 10,000.
  • maxBatchInterval: How long to batch telemetry for before sending (milliseconds)
  • Throttle Manager: I don't fully understand the settings here, but I might be able to achieve what I want with a reasonable combination of maxSendNumber (e.g. 1000) and dayInterval (e.g. 1/24 - hourly telemetry dispatches)?

I was thinking about lowering eventsLimitInMem, however, it still doesn't prevent our users from dispatching dozens/hundreds of individual tracking requests per second. I had no luck with maxBatchInterval either - it seems to act only as a guard against accumulating excessive data on the user's end (e.g. if the network is slow) and does not trigger between individual tracking calls if the user is online.

What seems to be missing here is something like a lodash throttle - a time-based interval which would allow users to only dispatch a limited amount of data once per a defined time interval (e.g. hourly or every minute or so).

  • Can something like this be achieved with the currently available settings?
  • Is the Throttle Manager component compatible with the other settings (eventsLimitInMem, maxBatchInterval)?
  • Does the Throttle Manager configuration support intervals (dayInterval) shorter than 1 day? (e.g. 1/24 - an hourly rate)
@mmeluch
Copy link
Author

mmeluch commented Apr 8, 2024

It is possible that the duplicates are caused by #2205 or #2195 instead of our code. My original question is still relevant I think, though - as a defense mechanism against such cases in the future:

image

@MSNev
Copy link
Collaborator

MSNev commented Apr 8, 2024

It is possible that the duplicates are caused by #2205 or #2195 instead of our code. My original question is still relevant I think, though - as a defense mechanism against such cases in the future:

Since your using "@microsoft/applicationinsights-web": "^2.7.3" No, these issues where introduced in the v3.x code bases.

We currently don't provide any "out of the box" throttling from the client side as you point out that generally throttling on the client side may cause something critical to get dropped, and if your entire set of client users drop the event you could be missing something critical -- and as this would probably depend on your application the throttling rules could get complex. And of course once the page reloads all previous knowledge is lost (unless persisted in Session / Local storage / IndexedDb)

We do have a "limit" on the total number of "dependency" requests that would be sent for a single page load maxAjaxCallsPerView which just blocks all events after reaching this limit.

You can implement your own "throttling" logic via a Telemetry Initializer, while it's primary use-case is to allow decorating / modifying the event before it gets batched, if you return false (explicit not just something falsely like 0 or undefined) then the event will be dropped and never batched / sent.

eventsLimitInMem - This is generally used to limit the amount of memory consumed within the SDK, so it's not really designed as a throttling mechanism to stop the SDK from crashing the browser if for some reason there are excessive events or it can't send the events out the door.

maxBatchInterval - This is just the amount of time it "waits" after batching the first event before it sends out the batched events.

And the Throttle Manager is really about allowing the throttling of specific generated messages (currently by the SDK) so rather than sending out an event for every user / every page load it's configurable to allow a lower percentage of events (so only send out a event once per month and only on a monday -- this is one of the configurable throttling) -- but this doesn't apply to "normal" automatic events. If your firing custom events, then yes you could configure and use this yourself -- but I'm guessing that's not really what your asking.

Can something like this be achieved with the currently available settings?

Not by default, but you could use a telemetry initializer fairly simply to duplicate this behavor.

Is the Throttle Manager component compatible with the other settings (eventsLimitInMem, maxBatchInterval)?

There are different, in that you would manually "ask" the throttle manager whether it can send an event and if you do it's batched with the other configs.

Does the Throttle Manager configuration support intervals (dayInterval) shorter than 1 day? (e.g. 1/24 - an hourly rate)

Tagging @Karlie-777, this sounds like a possible enhancement that we could consider, can you please create a GitHub enhancement issue (tagging this one) so that we can keep it on our backlog, rather than just tagging this one as this issue will probably have more discussion than just providing the ability for limiting hourly / minute -- or we may create a new specific Client side event throttler.

@Karlie-777
Copy link
Contributor

Karlie-777 commented Apr 8, 2024 via email

@mmeluch
Copy link
Author

mmeluch commented Apr 9, 2024

@MSNev thanks for the elaborate answer, it clarified many things which I initially misunderstood from the docs.

I think I should be able to implement my own client-side throttling now or at least utilize some kind of network-level brute-force protection by routing the the telemetry via our own servers first (endpointUrl).

@mmeluch mmeluch closed this as completed Apr 9, 2024
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

No branches or pull requests

3 participants