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

Extract session message collator #71

Merged
merged 1 commit into from
Nov 15, 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 @@ -6,6 +6,7 @@ import io.embrace.android.embracesdk.session.EmbraceBackgroundActivityService
import io.embrace.android.embracesdk.session.EmbraceSessionProperties
import io.embrace.android.embracesdk.session.EmbraceSessionService
import io.embrace.android.embracesdk.session.SessionHandler
import io.embrace.android.embracesdk.session.SessionMessageCollator
import io.embrace.android.embracesdk.session.SessionService
import io.embrace.android.embracesdk.worker.ExecutorName
import io.embrace.android.embracesdk.worker.WorkerThreadModule
Expand All @@ -14,6 +15,7 @@ internal interface SessionModule {
val sessionHandler: SessionHandler
val sessionService: SessionService
val backgroundActivityService: BackgroundActivityService?
val sessionMessageCollator: SessionMessageCollator
}

internal class SessionModuleImpl(
Expand All @@ -31,6 +33,24 @@ internal class SessionModuleImpl(
workerThreadModule: WorkerThreadModule
) : SessionModule {

override val sessionMessageCollator: SessionMessageCollator by singleton {
SessionMessageCollator(
essentialServiceModule.configService,
essentialServiceModule.metadataService,
dataContainerModule.eventService,
customerLogModule.remoteLogger,
sdkObservabilityModule.exceptionService,
dataContainerModule.performanceInfoService,
dataCaptureServiceModule.webviewService,
dataCaptureServiceModule.activityLifecycleBreadcrumbService,
dataCaptureServiceModule.thermalStatusService,
nativeModule.nativeThreadSamplerService,
dataCaptureServiceModule.breadcrumbService,
essentialServiceModule.userService,
initModule.clock
)
}

override val sessionHandler: SessionHandler by singleton {
SessionHandler(
coreModule.logger,
Expand All @@ -42,16 +62,10 @@ internal class SessionModuleImpl(
dataCaptureServiceModule.breadcrumbService,
essentialServiceModule.activityLifecycleTracker,
nativeModule.ndkService,
dataContainerModule.eventService,
customerLogModule.remoteLogger,
sdkObservabilityModule.exceptionService,
dataContainerModule.performanceInfoService,
essentialServiceModule.memoryCleanerService,
deliveryModule.deliveryService,
dataCaptureServiceModule.webviewService,
dataCaptureServiceModule.activityLifecycleBreadcrumbService,
dataCaptureServiceModule.thermalStatusService,
nativeModule.nativeThreadSamplerService,
sessionMessageCollator,
initModule.clock,
workerThreadModule.scheduledExecutor(ExecutorName.SESSION_CLOSER),
workerThreadModule.scheduledExecutor(ExecutorName.SESSION_CACHING)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
package io.embrace.android.embracesdk.session

import androidx.annotation.VisibleForTesting
import io.embrace.android.embracesdk.anr.ndk.NativeThreadSamplerService
import io.embrace.android.embracesdk.capture.PerformanceInfoService
import io.embrace.android.embracesdk.capture.connectivity.NetworkConnectivityService
import io.embrace.android.embracesdk.capture.crumbs.BreadcrumbService
import io.embrace.android.embracesdk.capture.crumbs.activity.ActivityLifecycleBreadcrumbService
import io.embrace.android.embracesdk.capture.metadata.MetadataService
import io.embrace.android.embracesdk.capture.thermalstate.ThermalStatusService
import io.embrace.android.embracesdk.capture.user.UserService
import io.embrace.android.embracesdk.capture.webview.WebViewService
import io.embrace.android.embracesdk.comms.delivery.DeliveryService
import io.embrace.android.embracesdk.comms.delivery.SessionMessageState
import io.embrace.android.embracesdk.config.ConfigService
import io.embrace.android.embracesdk.event.EmbraceRemoteLogger
import io.embrace.android.embracesdk.event.EventService
import io.embrace.android.embracesdk.internal.MessageType
import io.embrace.android.embracesdk.internal.clock.Clock
import io.embrace.android.embracesdk.internal.spans.EmbraceSpanData
Expand All @@ -23,7 +16,6 @@ import io.embrace.android.embracesdk.logging.EmbraceInternalErrorService
import io.embrace.android.embracesdk.logging.InternalEmbraceLogger
import io.embrace.android.embracesdk.logging.InternalStaticEmbraceLogger.Companion.logDeveloper
import io.embrace.android.embracesdk.ndk.NdkService
import io.embrace.android.embracesdk.payload.BetaFeatures
import io.embrace.android.embracesdk.payload.Session
import io.embrace.android.embracesdk.payload.Session.SessionLifeEventType
import io.embrace.android.embracesdk.payload.SessionMessage
Expand All @@ -46,16 +38,10 @@ internal class SessionHandler(
private val breadcrumbService: BreadcrumbService,
private val activityLifecycleTracker: ActivityTracker,
private val ndkService: NdkService,
private val eventService: EventService,
private val remoteLogger: EmbraceRemoteLogger,
private val exceptionService: EmbraceInternalErrorService,
private val performanceInfoService: PerformanceInfoService,
private val memoryCleanerService: MemoryCleanerService,
private val deliveryService: DeliveryService,
private val webViewService: WebViewService,
private val activityLifecycleBreadcrumbService: ActivityLifecycleBreadcrumbService?,
private val thermalStatusService: ThermalStatusService,
private val nativeThreadSamplerService: NativeThreadSamplerService?,
private val sessionMessageCollator: SessionMessageCollator,
private val clock: Clock,
private val automaticSessionStopper: ScheduledExecutorService,
private val sessionPeriodicCacheExecutorService: ScheduledExecutorService
Expand Down Expand Up @@ -95,7 +81,7 @@ internal class SessionHandler(
// Record the connection type at the start of the session.
networkConnectivityService.networkStatusOnSessionStarted(session.startTime)

val sessionMessage = buildStartSessionMessage(session)
val sessionMessage = sessionMessageCollator.buildStartSessionMessage(session)

metadataService.setActiveSessionId(session.sessionId)

Expand Down Expand Up @@ -245,123 +231,6 @@ internal class SessionHandler(
}
}

@Suppress("ComplexMethod")
private fun buildEndSessionMessage(
originSession: Session,
endedCleanly: Boolean,
forceQuit: Boolean,
crashId: String?,
endType: SessionLifeEventType,
sessionProperties: EmbraceSessionProperties,
sdkStartupDuration: Long,
endTime: Long,
spans: List<EmbraceSpanData>? = null
): SessionMessage {
val startTime: Long = originSession.startTime

// if it's a crash session, then add the stacktrace to the session payload
val crashReportId = when {
!crashId.isNullOrEmpty() -> crashId
else -> null
}
val terminationTime = when {
forceQuit -> endTime
else -> null
}
val receivedTermination = when {
forceQuit -> true
else -> null
}
// We don't set end time for force-quit, as the API interprets this to be a clean
// termination
val endTimeVal = when {
forceQuit -> null
else -> endTime
}

val sdkStartDuration = when (originSession.isColdStart) {
true -> sdkStartupDuration
false -> null
}

val startupEventInfo = eventService.getStartupMomentInfo()

val startupDuration = when (originSession.isColdStart && startupEventInfo != null) {
true -> startupEventInfo.duration
false -> null
}
val startupThreshold = when (originSession.isColdStart && startupEventInfo != null) {
true -> startupEventInfo.threshold
false -> null
}

val betaFeatures = when (configService.sdkModeBehavior.isBetaFeaturesEnabled()) {
false -> null
else -> BetaFeatures(
thermalStates = thermalStatusService.getCapturedData(),
activityLifecycleBreadcrumbs = activityLifecycleBreadcrumbService?.getCapturedData()
)
}

val endSession = originSession.copy(
isEndedCleanly = endedCleanly,
appState = EmbraceSessionService.APPLICATION_STATE_FOREGROUND,
messageType = MESSAGE_TYPE_END,
eventIds = eventService.findEventIdsForSession(startTime, endTime),
infoLogIds = remoteLogger.findInfoLogIds(startTime, endTime),
warningLogIds = remoteLogger.findWarningLogIds(startTime, endTime),
errorLogIds = remoteLogger.findErrorLogIds(startTime, endTime),
networkLogIds = remoteLogger.findNetworkLogIds(startTime, endTime),
infoLogsAttemptedToSend = remoteLogger.getInfoLogsAttemptedToSend(),
warnLogsAttemptedToSend = remoteLogger.getWarnLogsAttemptedToSend(),
errorLogsAttemptedToSend = remoteLogger.getErrorLogsAttemptedToSend(),
lastHeartbeatTime = clock.now(),
properties = sessionProperties.get(),
endType = endType,
unhandledExceptions = remoteLogger.getUnhandledExceptionsSent(),
webViewInfo = webViewService.getCapturedData(),
crashReportId = crashReportId,
terminationTime = terminationTime,
isReceivedTermination = receivedTermination,
endTime = endTimeVal,
sdkStartupDuration = sdkStartDuration,
startupDuration = startupDuration,
startupThreshold = startupThreshold,
user = userService.getUserInfo(),
betaFeatures = betaFeatures,
symbols = nativeThreadSamplerService?.getNativeSymbols()
)

val performanceInfo = performanceInfoService.getSessionPerformanceInfo(
startTime,
endTime,
originSession.isColdStart,
originSession.isReceivedTermination
)

val appInfo = metadataService.getAppInfo()
val deviceInfo = metadataService.getDeviceInfo()
val breadcrumbs = breadcrumbService.getBreadcrumbs(startTime, endTime)

val endSessionWithAllErrors = endSession.copy(exceptionError = exceptionService.currentExceptionError)

return SessionMessage(
session = endSessionWithAllErrors,
userInfo = endSessionWithAllErrors.user,
appInfo = appInfo,
deviceInfo = deviceInfo,
performanceInfo = performanceInfo.copy(),
breadcrumbs = breadcrumbs,
spans = spans
)
}

private fun buildStartSessionMessage(session: Session) = SessionMessage(
session = session,
appInfo = metadataService.getAppInfo(),
deviceInfo = metadataService.getDeviceInfo()
)

/**
* It builds an end active session message, it sanitizes it, it performs all types of memory cleaning,
* it updates cache and it sends it to our servers.
Expand All @@ -387,7 +256,7 @@ internal class SessionHandler(
return
}

val fullEndSessionMessage = buildEndSessionMessage(
val fullEndSessionMessage = sessionMessageCollator.buildEndSessionMessage(
/* we are previously checking in allowSessionToEnd that originSession != null */
originSession!!,
endedCleanly = true,
Expand Down Expand Up @@ -439,7 +308,7 @@ internal class SessionHandler(
// let's not overwrite the crash info with the periodic caching
stopPeriodicSessionCaching()

val fullEndSessionMessage = buildEndSessionMessage(
val fullEndSessionMessage = sessionMessageCollator.buildEndSessionMessage(
originSession,
endedCleanly = false,
forceQuit = false,
Expand Down Expand Up @@ -470,7 +339,7 @@ internal class SessionHandler(
return null
}

val fullEndSessionMessage = buildEndSessionMessage(
val fullEndSessionMessage = sessionMessageCollator.buildEndSessionMessage(
activeSession,
endedCleanly = false,
forceQuit = true,
Expand Down Expand Up @@ -572,13 +441,3 @@ internal class SessionHandler(
}
}
}

/**
* Signals to the API the start of a session.
*/
internal const val MESSAGE_TYPE_START = "st"

/**
* Signals to the API the end of a session.
*/
private const val MESSAGE_TYPE_END = "en"
Loading