diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt index 0838f4d4ba..648567c568 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt @@ -208,6 +208,9 @@ public class Call( internal var session: RtcSession? = null var sessionId = UUID.randomUUID().toString() + internal var connectedAt: Long? = null + internal var reconnectAt: Pair? = null + internal val mediaManager by lazy { if (testInstanceProvider.mediaManagerCreator != null) { testInstanceProvider.mediaManagerCreator!!.invoke() @@ -463,6 +466,7 @@ public class Call( session = if (testInstanceProvider.rtcSessionCreator != null) { testInstanceProvider.rtcSessionCreator!!.invoke() } else { + connectedAt = System.currentTimeMillis() RtcSession( sessionId = this.sessionId, apiKey = clientImpl.apiKey, @@ -617,6 +621,7 @@ public class Call( subscriptions = subscriptionsInfo, reconnect_attempt = reconnectAttepmts, ) + reconnectAt = Pair(WebsocketReconnectStrategy.WEBSOCKET_RECONNECT_STRATEGY_FAST, System.currentTimeMillis()) session.fastReconnect(reconnectDetails) } else { logger.e { "[reconnect] Disconnecting" } @@ -629,6 +634,7 @@ public class Call( */ suspend fun rejoin() = schedule { logger.d { "[rejoin] Rejoining" } + reconnectAt = Pair(WebsocketReconnectStrategy.WEBSOCKET_RECONNECT_STRATEGY_REJOIN, System.currentTimeMillis()) reconnectAttepmts++ state._connection.value = RealtimeConnection.Reconnecting location?.let { @@ -702,6 +708,7 @@ public class Call( reconnect_attempt = reconnectAttepmts, ) session.prepareRejoin() + reconnectAt = Pair(WebsocketReconnectStrategy.WEBSOCKET_RECONNECT_STRATEGY_MIGRATE, System.currentTimeMillis()) val newSession = RtcSession( clientImpl, powerManager, diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/call/RtcSession.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/call/RtcSession.kt index b84854b00f..dc94f5b1d0 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/call/RtcSession.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/call/RtcSession.kt @@ -137,11 +137,13 @@ import stream.video.sfu.models.WebsocketReconnectStrategy import stream.video.sfu.signal.ICERestartRequest import stream.video.sfu.signal.ICERestartResponse import stream.video.sfu.signal.ICETrickleResponse +import stream.video.sfu.signal.Reconnection import stream.video.sfu.signal.SendAnswerRequest import stream.video.sfu.signal.SendAnswerResponse import stream.video.sfu.signal.SendStatsRequest import stream.video.sfu.signal.SetPublisherRequest import stream.video.sfu.signal.SetPublisherResponse +import stream.video.sfu.signal.Telemetry import stream.video.sfu.signal.TrackMuteState import stream.video.sfu.signal.TrackSubscriptionDetails import stream.video.sfu.signal.UpdateMuteStatesRequest @@ -1631,6 +1633,7 @@ public class RtcSession internal constructor( internal suspend fun sendCallStats(report: CallStatsReport) { val result = wrapAPICall { + val now = System.currentTimeMillis() val androidThermalState = safeCallWithDefault(AndroidThermalState.ANDROID_THERMAL_STATE_UNSPECIFIED) { val thermalState = powerManager?.currentThermalStatus @@ -1663,6 +1666,22 @@ public class RtcSession internal constructor( thermal_state = androidThermalState, is_power_saver_mode = powerSaving, ), + telemetry = safeCallWithDefault(null) { + if (call.connectedAt != null || call.reconnectAt != null) { + Telemetry( + connection_time_seconds = call.connectedAt?.let { (now - it) / 1000 } + ?.toFloat(), + reconnection = call.reconnectAt?.let { + Reconnection( + time_seconds = ((now - it.second) / 1000).toFloat(), + strategy = it.first, + ) + }, + ) + } else { + null + } + }, ), ) }