-
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
[RUM-8652] Allow definition of custom implementations of specific SR methods #2516
base: develop
Are you sure you want to change the base?
[RUM-8652] Allow definition of custom implementations of specific SR methods #2516
Conversation
data class SessionReplayCustomCallbacks( | ||
val getCurrentWindows: (() -> List<Window>)? = null | ||
) |
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.
Note
Why did you chose to make it a data class instead of an interface?
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.
The general idea was to make a simple configuration object we could add to the configuration builder that holds optional callbacks, allowing clients to set only the ones they needed. But here both would work.
8d1bb14
to
fdb1b74
Compare
I think we shouldn't go this way (by exposing it in the public API along with other methods), it should be an internal API accessible from the proxy. |
*/ | ||
@InternalApi | ||
@Suppress( | ||
"UndocumentedPublicClass", |
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 class has been documented above, why do we still need this Suppression here?
import android.view.Window | ||
|
||
data class SessionReplayCustomCallbacks( | ||
val getCurrentWindows: (() -> List<Window>)? = null |
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 think instead of having a data class
with only one callback inside, you can just make it as an interface
@NoOpImplementation
interface SessionReplayCustomCallback{
fun getCurrentWindows() : List<Window>
}
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'm still not sure how many callbacks there will be for sure, for now it's just one, if it turns out to be just this one, we will likely not even need this and I'll change this then.
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.
Instead of having several callbacks feature, is that possible to have only one callback but with more functions in it?
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.
Not sure what that means, can you explain it a bit more or give an example ? Just for context, all these functions we need to override from RN or other project can all be unrelated to each other and can affect different parts of the sdk.
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.
If I understand correctly, what you intent to do should be like:
data class SessionReplayCustomCallbacks(
val getCurrentWindows: (() -> List<Window>)? = null
val doSomethingElseA: ((SomeInputA) -> SomeOutputA)? = null
val doSomethingElseB: ((SomeInputB) -> List<SomeOutputB>)? = null
)
Instead of doing that, you can do :
@NoOpImplementation
interface SessionReplayCustomCallback{
fun getCurrentWindows() : List<Window>
fun doSomethingElseA(input: SomeInputA) : SomeOutputA
fun doSomethingElseA(input: SomeInputB) : SomeOutputB
}
In that case you will have only one callback but can be called in different placesto serve for your need.
/** | ||
* Specifies callbacks functions to override standard behaviours in Session Replay | ||
* that need to behave differently depending on the platform. | ||
*/ |
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.
While reading this documentation, I would expect to understand what's the exact behaviours it will override. can you elaborate it?
@@ -73,6 +75,7 @@ data class SessionReplayConfiguration internal constructor( | |||
private var extensionSupportSet: MutableSet<ExtensionSupport> = mutableSetOf() | |||
private var dynamicOptimizationEnabled = true | |||
private var systemRequirementsConfiguration = SystemRequirementsConfiguration.NONE | |||
private var customCallbacks: SessionReplayCustomCallbacks = SessionReplayCustomCallbacks() |
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.
is it expected that the class name and field name are all pluriel?
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 say in this case yes, but what would you suggest ?
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.
usually we keep class name singular to represent a single instance of an object, unless the class itself presents a pluriel collection such as data class Users(val users: List<User>)
, and for the field name it should be like:
private var customCallback : SessionReplayCustomCallback = SessionReplayCustomCallback()
// or
private var customCallbacks : List<SessionReplayCustomCallback> = SessionReplayCustomCallback()
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 don't mind changing the name, but having something called SessionReplayCustomCallback, will be incorrect as soon as another callback is added no ?
Please ignore my comment above, I had an old version of this PR opened. I will review a new one. |
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 left few suggestions, but nothing blocking. LGTM.
import android.view.Window | ||
|
||
data class SessionReplayCustomCallbacks( | ||
val getCurrentWindows: (() -> List<Window>)? = null |
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: there is no need to use get
prefix for val
property, it can be just val currentWindows
logger = internalLogger, | ||
resourceResolver = resourceResolver, | ||
logger = internalLogger, resourceResolver = resourceResolver, |
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.
to be reverted
data class SessionReplayCustomCallbacks( | ||
val getCurrentWindows: (() -> List<Window>)? = null |
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.
maybe some explanation/docs here will be useful
"ClassNaming", | ||
"VariableNaming" | ||
) | ||
class _SessionReplayInternalProxy { |
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.
_SessionReplayInternalProxy.setCustomCallbacks(builder, customCallbacks)
_SessionReplayInternalProxy(builder).setCustomCallbacks(customCallbacks)
… builder - have the option to override `getCurrentWindows` in order to improve cross-platform support - make `setInternalCallback`to be available only through internal proxy
504b964
to
83f6f78
Compare
What does this PR do?
Exposes a new SessionReplayConfigutation option to allow clients to pass their own implementations of specific methods used in the Session Replay SDK.
Updates the SDK code to use the overriden function if provided and falling back to the original implementation otherwise.
( Currently only
getCurrentWIndows
is allowed to be redefined, but there's a high likelihood that more will be needed )Motivation
What inspired you to submit this pull request?
Certain parts of the session replay SDK don't work as intended when ran in a react-native environment, leading to broken replays. In order to keep platform specific code out of the android SDK, the goal is to allow each client to add their own implementations of the parts that don't work.
Additional Notes
We keep the
setCustomCallbacks
only accessible through a internal proxy in order to not expose internal config options. In practice it would look something like this:Review checklist (to be filled by reviewers)