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

Move active session down to SessionHandler #94

Merged
merged 1 commit into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ internal class EmbraceSessionService(
const val SESSION_CACHING_INTERVAL = 2
}

/**
* The currently active session.
*/
@Volatile
internal var activeSession: Session? = null

init {
if (!this.processStateService.isInBackground) {
// If the app goes to foreground before the SDK finishes its startup,
Expand All @@ -57,7 +51,7 @@ internal class EmbraceSessionService(
}

// Send any sessions that were cached and not yet sent.
deliveryService.sendCachedSessions(isNdkEnabled, ndkService, activeSession?.sessionId)
deliveryService.sendCachedSessions(isNdkEnabled, ndkService, sessionHandler.getSessionId())
}

override fun startSession(coldStart: Boolean, startType: Session.SessionLifeEventType, startTime: Long) {
Expand All @@ -80,23 +74,17 @@ internal class EmbraceSessionService(

if (sessionMessage != null) {
logger.logDeveloper(TAG, "Session Message is created")
activeSession = sessionMessage.session
logger.logDeveloper(TAG, "Active session: " + activeSession?.sessionId)
} else {
logger.logDeveloper(TAG, "Session Message is NULL")
}
}

override fun handleCrash(crashId: String) {
logger.logDeveloper(TAG, "Attempt to handle crash id: $crashId")

activeSession?.also {
sessionHandler.onCrash(
it,
crashId,
spansService.flushSpans(EmbraceAttributes.AppTerminationCause.CRASH)
)
} ?: logger.logDeveloper(TAG, "Active session is NULL")
sessionHandler.onCrash(
crashId,
spansService.flushSpans(EmbraceAttributes.AppTerminationCause.CRASH)
)
}

/**
Expand All @@ -105,11 +93,7 @@ internal class EmbraceSessionService(

fun onPeriodicCacheActiveSession() {
try {
val session = activeSession ?: return
sessionHandler.onPeriodicCacheActiveSession(
session,
spansService.completedSpans()
)
sessionHandler.onPeriodicCacheActiveSession(spansService.completedSpans())
} catch (ex: Exception) {
logger.logDebug("Error while caching active session", ex)
}
Expand Down Expand Up @@ -163,16 +147,11 @@ internal class EmbraceSessionService(
*/
private fun endSession(endType: Session.SessionLifeEventType, endTime: Long) {
logger.logDebug("Will try to end session.")
val session = activeSession ?: return
sessionHandler.onSessionEnded(
endType,
session,
endTime,
spansService.flushSpans()
)

// clear active session
activeSession = null
logger.logDeveloper(TAG, "Active session cleared")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ internal class SessionHandler(
private val sessionPeriodicCacheExecutorService: ScheduledExecutorService
) : Closeable {

/**
* The currently active session.
*/
@Volatile
private var activeSession: Session? = null

internal fun getSessionId(): String? = activeSession?.sessionId

var scheduledFuture: ScheduledFuture<*>? = null

/**
Expand Down Expand Up @@ -86,6 +94,7 @@ internal class SessionHandler(
userService.loadUserInfoFromDisk(),
sessionProperties.get()
)
activeSession = session
logDeveloper("SessionHandler", "SessionId = ${session.sessionId}")

// Record the connection type at the start of the session.
Expand Down Expand Up @@ -114,15 +123,16 @@ internal class SessionHandler(
*/
fun onSessionEnded(
endType: SessionLifeEventType,
originSession: Session,
endTime: Long,
completedSpans: List<EmbraceSpanData>? = null
) {
synchronized(lock) {
val session = activeSession ?: return

logger.logDebug("Will try to run end session full.")
val fullEndSessionMessage = createSessionSnapshot(
SessionSnapshotType.NORMAL_END,
originSession,
session,
sessionProperties,
completedSpans,
endType,
Expand All @@ -131,11 +141,14 @@ internal class SessionHandler(

// Clean every collection of those services which have collections in memory.
memoryCleanerService.cleanServicesCollections(exceptionService)
metadataService.removeActiveSessionId(originSession.sessionId)
metadataService.removeActiveSessionId(session.sessionId)
logger.logDebug("Services collections successfully cleaned.")
sessionProperties.clearTemporary()
logger.logDebug("Session properties successfully temporary cleared.")
deliveryService.sendSession(fullEndSessionMessage, SessionMessageState.END)

// clear active session
activeSession = null
}
}

Expand All @@ -144,15 +157,15 @@ internal class SessionHandler(
* and send it to our servers.
*/
fun onCrash(
originSession: Session,
crashId: String,
completedSpans: List<EmbraceSpanData>? = null
) {
synchronized(lock) {
val session = activeSession ?: return
logger.logDebug("Will try to run end session for crash.")
val fullEndSessionMessage = createSessionSnapshot(
SessionSnapshotType.JVM_CRASH,
originSession,
session,
sessionProperties,
completedSpans,
SessionLifeEventType.STATE,
Expand All @@ -170,21 +183,19 @@ internal class SessionHandler(
* Note that the session message will not be sent to our servers.
*/
fun onPeriodicCacheActiveSession(
activeSession: Session?,
completedSpans: List<EmbraceSpanData>? = null
): SessionMessage? {
synchronized(lock) {
val msg = activeSession?.let {
logger.logDebug("Will try to run end session for caching.")
createSessionSnapshot(
SessionSnapshotType.PERIODIC_CACHE,
activeSession,
sessionProperties,
completedSpans,
SessionLifeEventType.STATE,
clock.now()
)
}
logger.logDebug("Will try to run end session for caching.")
val session = activeSession ?: return null
val msg = createSessionSnapshot(
SessionSnapshotType.PERIODIC_CACHE,
session,
sessionProperties,
completedSpans,
SessionLifeEventType.STATE,
clock.now()
)
msg?.let(deliveryService::saveSession)
return msg
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import io.embrace.android.embracesdk.ndk.NdkService
import io.embrace.android.embracesdk.payload.Session
import io.embrace.android.embracesdk.payload.Session.SessionLifeEventType
import io.embrace.android.embracesdk.payload.SessionMessage
import io.mockk.Called
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.mockk
Expand All @@ -24,6 +23,7 @@ import org.junit.AfterClass
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
Expand Down Expand Up @@ -93,68 +93,6 @@ internal class EmbraceSessionServiceTest {
}
}

@Test
fun `start session successfully`() {
initializeSessionService()
val coldStart = /* same for false */ true
val type = /* could be any type */ SessionLifeEventType.STATE
every {
mockSessionHandler.onSessionStarted(
coldStart,
type,
any(),
any(),
any()
)
} returns mockSessionMessage

val startTime = clock.now()

service.startSession(coldStart, type, startTime)

assertEquals(mockSession, service.activeSession)
verify {
mockSessionHandler.onSessionStarted(
coldStart,
type,
startTime,
any(),
any()
)
}
assertEquals(mockSession, service.activeSession)
}

@Test
fun `start session if not allowed then session handler will return a null session`() {
initializeSessionService()
val coldStart = /* same for false */ true
val type = /* could be any type */ SessionLifeEventType.STATE
every {
mockSessionHandler.onSessionStarted(
coldStart,
type,
any(),
any(),
any()
)
} returns null

val startTime = clock.now()
service.startSession(coldStart, type, startTime)

assertNull(service.activeSession)
verify {
mockSessionHandler.onSessionStarted(
coldStart,
type,
startTime,
any(),
any()
)
}
}

@Test
fun `handle crash successfully`() {
initializeSessionService()
Expand All @@ -174,7 +112,7 @@ internal class EmbraceSessionServiceTest {

service.handleCrash(crashId)

verify { mockSessionHandler.onCrash(mockSession, crashId) }
verify { mockSessionHandler.onCrash(crashId) }
}

@Test
Expand All @@ -184,7 +122,7 @@ internal class EmbraceSessionServiceTest {
val startTime = 123L

service.onForeground(coldStart, startTime, 456)
assertNull(deliveryService.lastSentCachedSession)
assertEquals("", deliveryService.lastSentCachedSession)

// verify that a STATE session is started
verify {
Expand Down Expand Up @@ -218,26 +156,6 @@ internal class EmbraceSessionServiceTest {
}
}

@Test
fun `on background ends a state session for a previously existing session`() {
initializeSessionService()
// let's start session first so we have an active session
startDefaultSession()

service.onBackground(456)

// verify session is ended
verify {
mockSessionHandler.onSessionEnded(
SessionLifeEventType.STATE,
mockSession,
456
)
}
// verify active session has been reset
assertNull(service.activeSession)
}

@Test
fun `trigger stateless end session successfully for activity in background`() {
initializeSessionService()
Expand All @@ -250,7 +168,6 @@ internal class EmbraceSessionServiceTest {
verify {
mockSessionHandler.onSessionEnded(
SessionLifeEventType.MANUAL,
mockSession,
0,
any()
)
Expand All @@ -267,7 +184,7 @@ internal class EmbraceSessionServiceTest {
service.triggerStatelessSessionEnd(endType)

// verify session is ended
verify { mockSessionHandler.onSessionEnded(endType, mockSession, 0, any()) }
verify { mockSessionHandler.onSessionEnded(endType, 0, any()) }
// verify that a MANUAL session is started
verify {
mockSessionHandler.onSessionStarted(
Expand All @@ -284,8 +201,7 @@ internal class EmbraceSessionServiceTest {
fun `trigger stateless end session for a STATE session end type should not do anything`() {
initializeSessionService()
service.triggerStatelessSessionEnd(SessionLifeEventType.STATE)

verify { mockSessionHandler wasNot Called }
assertTrue(deliveryService.lastSentSessions.isEmpty())
}

@Test
Expand Down Expand Up @@ -324,7 +240,6 @@ internal class EmbraceSessionServiceTest {
verify {
mockSessionHandler.onSessionEnded(
endType = any(),
originSession = any(),
endTime = any(),
completedSpans = match {
it.size == 2
Expand All @@ -348,7 +263,6 @@ internal class EmbraceSessionServiceTest {
verify {
mockSessionHandler.onSessionEnded(
endType = any(),
originSession = any(),
endTime = any(),
completedSpans = match {
it.size == 2
Expand All @@ -371,7 +285,6 @@ internal class EmbraceSessionServiceTest {
// expect 2 spans to be flushed: session span and sdk init span
verify {
mockSessionHandler.onCrash(
originSession = any(),
crashId = any(),
completedSpans = match {
it.size == 2
Expand Down
Loading