-
Notifications
You must be signed in to change notification settings - Fork 63
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-2355 Add Session Replay lifecycle callbacks #993
RUMM-2355 Add Session Replay lifecycle callbacks #993
Conversation
2a27976
to
19ef3d2
Compare
94205c2
to
6d80acd
Compare
cf87ff5
to
808031a
Compare
// region Internal | ||
|
||
private fun registerCallback(context: Context) { | ||
if (context is Application) { |
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.
we can declare context
as Application
type directly and avoid this check
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.
Yeah but it doesn't follow the pattern for all the other features. If we do this it will make sense to change this also for RumFeature
, LogsFeature
, etc.
|
||
// Then | ||
verify(mockSessionReplayLifecycleCallback) | ||
.register(appContext.mockInstance) |
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 we verify unregister
here?
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.
damn yes
// Then | ||
countDownLatch.await(5, TimeUnit.SECONDS) | ||
verify(mockSessionReplayLifecycleCallback) | ||
.register(appContext.mockInstance) |
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.
seems like verification of unregister
is missing
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.
yup, copy pasted from the first one :)
|
||
// Then | ||
verify(mockSessionReplayLifecycleCallback) | ||
.register(appContext.mockInstance) |
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.
also we need to check that unregister
was called once.
// When | ||
repeat(3) { | ||
Thread { | ||
testedFeature.stopRecording() |
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.
test says startRecording
, but stopRecording
is called here
) : ViewTreeObserver | ||
.OnDrawListener { |
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.
) : ViewTreeObserver | |
.OnDrawListener { | |
) : ViewTreeObserver.OnDrawListener { |
) : ViewTreeObserver | ||
.OnDrawListener { | ||
private var currentOrientation = Configuration.ORIENTATION_UNDEFINED | ||
private val trackedActivity: WeakReference<Activity> = WeakReference(activity) |
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.
why do we need to use WeakReference
if we know activity lifecycle and can just release trackedActivity
property when activity goes into a destroyed state?
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 but I want to be better safe than sorry. I want to totally avoid keeping those references and it will not be too costly to just use WeakRefs
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 problem with weak references is that they can be collected at some point and everything will stop working all of the sudden, recording will just stop, it is very hard to debug such things.
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 way I know is that they will never be destroyed if they still have a strong reference from somewhere in the process. @xgouchet I really want also your input here, should we keep WeakRefs or just go with direct reference and hope that will never go into trouble.
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.
ok, I refreshed my knowledge (didn't use WeakReference
for a long time) and that is true: they are cleared only when referent is weakly reachable.
So I guess we can keep them. But still, I'm curious why do we need it when we have a complete access to the lifecycle.
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.
Yup, we can debate this, waiting for @xgouchet's opinion also.
Application.ActivityLifecycleCallbacks { | ||
|
||
internal var recorder: Recorder = ScreenRecorder(SnapshotProcessor()) | ||
internal val resumedActivities: WeakHashMap<Activity, Any?> = WeakHashMap() |
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.
Why we use WeakHashMap
if we can properly control the reference to the activity by listening to the lifecycle?
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.
Same as above
} | ||
|
||
@Test | ||
fun `M stop recording all resumed activities W W unregisterAndStopRecorders()`() { |
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.
fun `M stop recording all resumed activities W W unregisterAndStopRecorders()`() { | |
fun `M stop recording all resumed activities W unregisterAndStopRecorders()`() { |
lateinit var mockActivity: Activity | ||
lateinit var mockDecorView: View | ||
lateinit var mockWindow: Window | ||
lateinit var mockResources: Resources | ||
lateinit var configuration: Configuration |
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.
we can also use Mock
annotation here directly?
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 I use that but whenever I want to stub a method inside I use mock { }
Codecov Report
@@ Coverage Diff @@
## feature/session-replay-vo #993 +/- ##
=============================================================
+ Coverage 82.85% 82.94% +0.09%
=============================================================
Files 298 306 +8
Lines 9772 9853 +81
Branches 1595 1616 +21
=============================================================
+ Hits 8096 8172 +76
+ Misses 1194 1184 -10
- Partials 482 497 +15
|
209a40a
to
b7158ed
Compare
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.
lgtm!
b7158ed
to
0ca3a80
Compare
What does this PR do?
In this PR we are adding the Session Replay application lifecycle callbacks which will be controlled from the
SessionReplayFeature
level through the Public API.We are also adding the base Recorder - Processor architecture, preparing the steps for the next PR where we're going to capture the screen snapshot and send it to the processor.
Motivation
What inspired you to submit this pull request?
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)