-
Notifications
You must be signed in to change notification settings - Fork 64
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
RUMM-2172 Single Storage #932
Conversation
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.
Nicely done! I've added some thoughts/comments, but none of them are blocking for me.
fun currentMetadata(): ByteArray? | ||
|
||
/** | ||
* @param event the event to write |
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.
minor: missing descriptions of the method and newMetadata
arguments
/** | ||
* Holds information about the current local and server time. | ||
* @property deviceTimeNs the current time as known by the System on the device (nanoseconds) | ||
* @property serverTimeNs the current time synchronized with our NTP server(s) (nanoseconds) |
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.
* @property serverTimeNs the current time synchronized with our NTP server(s) (nanoseconds) | |
* @property serverTimeNs the current time synchronized with Datadog NTP server(s) (nanoseconds) |
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.
👍
), | ||
ProcessInfo(forge.aBool(), forge.anInt()), | ||
NetworkInfo(forge.aValueFrom(NetworkInfo.Connectivity::class.java), null), | ||
UserInfo(null, null, null, emptyMap()), |
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.
should have nullable values forged
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.
Yes I know, I'll deal with those in a future PR (when those are actually needed)
assertThat(RumFeature.initialized.get()).isEqualTo(rumEnabled) | ||
assertThat(WebViewLogsFeature.initialized.get()).isEqualTo(logsEnabled) | ||
assertThat(WebViewRumFeature.initialized.get()).isEqualTo(rumEnabled) | ||
// assertThat(CoreFeature.initialized.get()).isTrue() |
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.
I would propose to add a TODO at the beginning of this file and DatadogCoreTest
as well saying we should handle those commented lines (unlikely we will forget, but still)
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.
Yes good point
return | ||
} | ||
|
||
val file = orchestrator.getWritableFile(event.size) |
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.
thought: in this particular case callback is invoked synchronously, but in general API definition says it may be invoked in async manner, meaning that by the time it is invoked we may have other consent -> different orchestrator, not the one we captured for invocation. We need to be aware about that.
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.
(...) by the time it is invoked we may have other consent -> different orchestrator, not the one we captured for invocation
Not sure if I understand this @0xnm 🤔💭. We get the orchestrator based on the immutable datadogContext
passed as an parameter to writeCurrentBatch()
. Then, any time later we receive a callback which provides us API (BatchWriter
) to writing data. The write strategy will respect the consent value from datadogContext
.
From the caller's POV, IMO everything should be consistent with this implementation: the caller orders write for given consent value and it knows that BatchWriter
will respect it. No?
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.
I mean that generally the API contract is that this callback may be invoked in async manner (if I got it right). My point is that what if user changed a consent in the timeframe between the moment we received an orchestrator
and the moment we use it in the BatchWriter
. Then event may be written to the location which belongs to the old consent.
This is quite hypothetical case (and may be quite an edge case), but this gist of it is that imo we need to keep in mind the possible SDK state changes with async invocations.
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.
This is an edge case that is not something we want to dig into. The time frame for such a concurrency issue will on most case something smaller than 500ms, which is totally acceptable.
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.
I get the point now @0xnm 👌. Agree, it's kind of edge case, but it can be clearly visible in such user situation:
// all synchronous, on a single thread:
Datadog.set(trackingConsent: .granted)
logger.info("granted log")
Datadog.set(trackingConsent: .pending)
In such case, the "granted log" should be sent by the SDK. This is however a question on how we will further synchronise things in higher implementation (even higher than Storage
level). The RFC recommends processing all user calls through context thread first (see Threading in DDCore
) to support exactly these edge cases.
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.
Looks very good from the architecture POV 👍. I can see slight differences when comparing to RFC interfaces, but I believe these are Android / Kotlin specifics.
ddf1ba3
to
771eb8a
Compare
What does this PR do?
Provide an implementation of the single storage mechanism for SDK v2
Additional Notes
Unit tests are globally not passing but all tests on the new classes are green ✅