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

Use remote limit as ceiling for network call limits and apply consistently #78

Merged
merged 2 commits into from
Nov 16, 2023

Conversation

bidetofevil
Copy link
Collaborator

@bidetofevil bidetofevil commented Nov 16, 2023

Goal

There were two problems that were addressed in this PR:

  1. The initial issue was that if a remote config is not defined for network behaviour, the local settings on network call limits will be used as is, which means customers can set the limit to whatever they want, which sort of defeats the purpose of having a limit to prevent runaway payload size.
  2. The second that I found while working on this is that we are clearing the limits prematurely, every time we cache a session. This means the window in which the limit will be applied before resetting was impossibly short.

This PR addresses both issues by using the default limits in the remote config (or defaults implied by the absence of a config) to act as the ceiling to whatever is set locally. This make the local setting a way of further limit what is set on the remote, and won't allow the overriding of it. I also removed the erroneous limit clearing, which ironically is probably the source of the original customer issue anyway, just obscured by what I found with the local limits

Testing

Added more test cases to verify the fixed behaviour as well as corner cases not covered previously

Release Notes

WHAT:

Properly enforce network call per session limit and use the remote limit as a ceiling for any local limits set.
WHY:

Limiting the number of session calls recorded prevents session payloads from growing to an unhealthy size.

Copy link
Collaborator Author

Current dependencies on/for this PR:

This stack of pull requests is managed by Graphite.

Copy link

codecov bot commented Nov 16, 2023

Codecov Report

Merging #78 (010968e) into master (4c5ff31) will increase coverage by 0.10%.
Report is 2 commits behind head on master.
The diff coverage is 85.71%.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #78      +/-   ##
==========================================
+ Coverage   75.92%   76.03%   +0.10%     
==========================================
  Files         313      313              
  Lines       10114    10097      -17     
  Branches     1461     1455       -6     
==========================================
- Hits         7679     7677       -2     
+ Misses       1843     1832      -11     
+ Partials      592      588       -4     
Files Coverage Δ
...roid/embracesdk/config/behavior/NetworkBehavior.kt 83.33% <83.33%> (+8.33%) ⬆️
...dk/network/logging/EmbraceNetworkLoggingService.kt 87.60% <86.66%> (+0.68%) ⬆️

... and 1 file with indirect coverage changes

@bidetofevil bidetofevil marked this pull request as ready for review November 16, 2023 16:27
@bidetofevil bidetofevil requested a review from a team as a code owner November 16, 2023 16:27
for (domain in local?.networking?.domains ?: return null) {
if (domain.domain != null && domain.limit != null) {
mergedLimits[domain.domain] = domain.limit
val limitCeiling = getLimitCeiling()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The algo is:

  • Use the remote settings as a base
  • For domains where there is both a local and remote entry, apply the local setting per domain if the local limit is smaller than the remote one
  • For domains with only a local entry, apply the local setting or the ceiling as defined by the default limit set on the remote, which ever is smaller.

Copy link
Contributor

Choose a reason for hiding this comment

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

Consider leaving as a comment in the code?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good idea


private val untrackedNetworkCallCount = AtomicInteger(0)

private var defaultPerDomainCallLimit = configService.networkBehavior.getNetworkCaptureLimit()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We want to maintain the same limits for each session, so we get it at init time, and update when we reset the service when the session ends. Previously, this is pulled every time at run time, and we can get into inconsistent states in the middle of a session if new remote limits are fetched.

}
return
} else if (!domainSetting.containsKey(domain)) {
createLimitForDomain(domain)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added the fetching of the domain limits here to run before we record a network request. It was doing it after and I have no idea why.

logger.logDeveloper("EmbraceNetworkLoggingService", "no domain settings")
storeNetworkCall(callId, networkCall)
// Not sure how this is possible, but in case it is, limit logged logs where we can't figure out the settings to apply
if (untrackedNetworkCallCount.getAndIncrement() < defaultPerDomainCallLimit) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This should never happen so I don't know how to test it, but I've added code to catch and limit this in case it happens - it wasn't limiting that before.

Another option is just to ditch it like if we can't find a domain (which probably prevents this block from every running tbh), but this seems safer and who knows what funny refactoring in the future will bring. Safety first I guess.

)
}
}
}

private fun storeSettings(url: String) {
private fun createLimitForDomain(domain: String) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The old implementation is really wasteful in that it rebuild the domain limits map at every call, often unnecessarily. So we build and cache it for reuse at init time and redo it when the session ends instead.

@@ -68,8 +74,6 @@
logger.logError(msg, IllegalStateException(msg), true)
}

// clear calls per domain and session network calls lists before be used by the next session
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Lol is one line is probably the most important change in the PR. We were resetting this every time a session payload is built, which effectively nerfs the limit.

Copy link
Contributor

Choose a reason for hiding this comment

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

Periodic session caching strikes again 💥

Copy link
Contributor

@fractalwrench fractalwrench left a comment

Choose a reason for hiding this comment

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

LGTM

for (domain in local?.networking?.domains ?: return null) {
if (domain.domain != null && domain.limit != null) {
mergedLimits[domain.domain] = domain.limit
val limitCeiling = getLimitCeiling()
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider leaving as a comment in the code?

@@ -68,8 +74,6 @@
logger.logError(msg, IllegalStateException(msg), true)
}

// clear calls per domain and session network calls lists before be used by the next session
Copy link
Contributor

Choose a reason for hiding this comment

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

Periodic session caching strikes again 💥

@bidetofevil bidetofevil merged commit 989dbf2 into master Nov 16, 2023
4 checks passed
@bidetofevil bidetofevil deleted the hho/network-logging-limits branch November 16, 2023 18:35
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.

None yet

2 participants