NTP-9213 | Event metric code cleanup (#260)

This commit is contained in:
Sayed Owais Ali
2024-10-25 14:35:06 +05:30
committed by GitHub
parent b0c493a87d
commit 029be724de
14 changed files with 2 additions and 352 deletions

View File

@@ -21,7 +21,6 @@ import androidx.appcompat.widget.AppCompatTextView
import com.navi.alfred.db.AlfredDatabase
import com.navi.alfred.db.AlfredDatabaseHelper
import com.navi.alfred.db.dao.AnalyticsDAO
import com.navi.alfred.db.dao.ApiMetricDao
import com.navi.alfred.db.dao.FailureEventDao
import com.navi.alfred.db.dao.NegativeCaseDao
import com.navi.alfred.db.dao.ScreenShotDao
@@ -36,11 +35,8 @@ import com.navi.alfred.network.AlfredRetrofitProvider
import com.navi.alfred.network.model.CruiseResponse
import com.navi.alfred.repository.ComposeMaskingRepoImpl
import com.navi.alfred.utils.AlfredConstants
import com.navi.alfred.utils.AlfredConstants.API_METRICS
import com.navi.alfred.utils.AlfredConstants.CODE_API_SUCCESS
import com.navi.alfred.utils.AlfredConstants.THIRD_PARTY_MODULE
import com.navi.alfred.utils.ScreenShotStorageHelper
import com.navi.alfred.utils.buildAppPerformanceEvent
import com.navi.alfred.utils.buildEvent
import com.navi.alfred.utils.buildNegativeCaseEvent
import com.navi.alfred.utils.captureScreen
@@ -58,7 +54,6 @@ import com.navi.alfred.utils.measureInflatedView
import com.navi.alfred.utils.startAnrCrashZipUpload
import com.navi.alfred.utils.startSyncEvents
import com.navi.alfred.worker.AddEventTask
import com.navi.alfred.worker.AddMetricTask
import com.navi.alfred.worker.AddNegativeCase
import java.lang.ref.WeakReference
import java.util.Timer
@@ -67,8 +62,6 @@ import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import okhttp3.Request
import okhttp3.Response
object AlfredManager {
@@ -101,7 +94,6 @@ object AlfredManager {
internal lateinit var alfredDataBase: AlfredDatabase
internal lateinit var screenShotDao: ScreenShotDao
internal lateinit var zipDetailsDao: ZipDetailsDao
internal lateinit var apiMetricDao: ApiMetricDao
internal lateinit var analyticsDao: AnalyticsDAO
internal lateinit var negativeCaseDao: NegativeCaseDao
internal lateinit var failureEventDao: FailureEventDao
@@ -305,7 +297,6 @@ object AlfredManager {
analyticsDao = alfredDataBase.analyticsDao()
screenShotDao = alfredDataBase.screenShotDao()
zipDetailsDao = alfredDataBase.zipDetailsDao()
apiMetricDao = alfredDataBase.apiMetricDao()
negativeCaseDao = alfredDataBase.negativeCaseDao()
failureEventDao = alfredDataBase.failureEventDao()
sensitiveComposeRepository = ComposeMaskingRepoImpl()
@@ -334,57 +325,6 @@ object AlfredManager {
reactBottomSheetView?.clear()
}
fun saveApiLog(
byteReceived: Long,
byteSent: Long,
request: Request,
response: Response,
startTime: Long,
endTime: Long
) {
if (
config.getAlfredStatus() &&
config.getMetricsApiEnableStatus() &&
config.getAlfredSessionId().isNotEmpty() &&
isAppInBackground.not() &&
isActivityResumed &&
hasRecordingStarted
) {
coroutineDispatcher.executor.execute {
val duration: Long = endTime - startTime
val errorType: String? = null
val errorMessage: String? =
if (response.code != CODE_API_SUCCESS) {
response.message
} else {
null
}
val attributes =
hashMapOf<String, Any>().apply {
this[AlfredConstants.URL] = request.url.toString()
this[AlfredConstants.METHOD] = request.method
this[AlfredConstants.RESPONSE_CODE] = response.code
this[AlfredConstants.ERROR_MESSAGE] = errorMessage.toString()
this[AlfredConstants.ERROR_TYPE] = errorType.toString()
this[AlfredConstants.START_TIME] = startTime
this[AlfredConstants.END_TIME] = endTime
this[AlfredConstants.DURATION_IN_MS] = duration.toDouble()
this[AlfredConstants.BYTES_RECEIVED] = byteReceived
this[AlfredConstants.BYTES_SENT] = byteSent
}
val appPerformanceEvent =
buildAppPerformanceEvent(
AlfredConstants.API_METRIC_EVENT_NAME,
API_METRICS,
attributes
)
AlfredDispatcher.addTaskToQueue(
AddMetricTask(appPerformanceEvent, applicationContext)
)
}
}
}
fun handleTouchEvent(
currentTouchEvent: MotionEvent?,
screenName: String? = null,

View File

@@ -10,13 +10,11 @@ package com.navi.alfred.db
import androidx.room.Database
import androidx.room.RoomDatabase
import com.navi.alfred.db.dao.AnalyticsDAO
import com.navi.alfred.db.dao.ApiMetricDao
import com.navi.alfred.db.dao.FailureEventDao
import com.navi.alfred.db.dao.NegativeCaseDao
import com.navi.alfred.db.dao.ScreenShotDao
import com.navi.alfred.db.dao.ZipDetailsDao
import com.navi.alfred.db.model.AnalyticsEvent
import com.navi.alfred.db.model.ApiMetricHelper
import com.navi.alfred.db.model.FailureEvent
import com.navi.alfred.db.model.NegativeCase
import com.navi.alfred.db.model.ScreenShotPathHelper
@@ -28,7 +26,6 @@ import com.navi.alfred.db.model.ZipDetailsHelper
AnalyticsEvent::class,
ScreenShotPathHelper::class,
ZipDetailsHelper::class,
ApiMetricHelper::class,
NegativeCase::class,
FailureEvent::class
],
@@ -42,8 +39,6 @@ abstract class AlfredDatabase : RoomDatabase() {
abstract fun zipDetailsDao(): ZipDetailsDao
abstract fun apiMetricDao(): ApiMetricDao
abstract fun negativeCaseDao(): NegativeCaseDao
abstract fun failureEventDao(): FailureEventDao

View File

@@ -12,7 +12,6 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.navi.alfred.db.model.AnalyticsEvent
import com.navi.alfred.db.model.ApiMetricHelper
import com.navi.alfred.db.model.FailureEvent
import com.navi.alfred.db.model.NegativeCase
import com.navi.alfred.db.model.ScreenShotPathHelper
@@ -83,20 +82,6 @@ interface ZipDetailsDao {
fun updateZipUploadStatus(zipFileName: String, status: Boolean)
}
@Dao
interface ApiMetricDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(data: ApiMetricHelper)
@Query("SELECT count(*) FROM ApiMetricHelper") fun getApiMetricCount(): Int
@Query("SELECT * FROM ApiMetricHelper ORDER BY time ASC LIMIT :thresholdValue")
fun fetchApiMetric(thresholdValue: Int): List<ApiMetricHelper>
@Query("DELETE FROM ApiMetricHelper WHERE id IN (:idList)")
fun deleteApiMetric(idList: List<Int>)
}
@Dao
interface NegativeCaseDao {
@Insert fun insertNegativeCase(negativeCase: NegativeCase)

View File

@@ -40,14 +40,6 @@ data class ZipDetailsHelper(
@PrimaryKey(autoGenerate = true) var id: Int = 0
}
@Entity
data class ApiMetricHelper(
@ColumnInfo(name = "time") val time: Long?,
@ColumnInfo(name = "metric") val metric: String?
) {
@PrimaryKey(autoGenerate = true) var id: Int = 0
}
@Entity
data class NegativeCase(
@ColumnInfo(name = "time") val time: Long?,

View File

@@ -1,27 +0,0 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.deserializer
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.navi.alfred.model.EventMetricRequest
import java.lang.reflect.Type
class MetricsDataDeserializer : JsonDeserializer<EventMetricRequest> {
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): EventMetricRequest? {
json?.let {
return context?.deserialize(json, EventMetricRequest::class.java)
}
return null
}
}

View File

@@ -10,7 +10,6 @@ package com.navi.alfred.deserializer
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.navi.alfred.model.EventMetricRequest
import com.navi.alfred.model.SessionRequest
import java.lang.reflect.Type
@@ -21,7 +20,7 @@ class SessionDataDeserializer : JsonDeserializer<SessionRequest> {
context: JsonDeserializationContext?
): SessionRequest? {
json?.let {
return context?.deserialize(json, EventMetricRequest::class.java)
return context?.deserialize(json, SessionRequest::class.java)
}
return null
}

View File

@@ -1,26 +0,0 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.model
import com.google.gson.annotations.SerializedName
data class EventMetricRequest(
@SerializedName("base_attributes") val baseAttribute: BaseAttribute,
@SerializedName("metrics_attributes") val metricsAttribute: List<MetricAttribute>
)
data class MetricAttribute(
@SerializedName("event_id") val eventId: String? = null,
@SerializedName("event_name") val eventName: String? = null,
@SerializedName("session_id") val sessionId: String? = null,
@SerializedName("event_type") val eventType: String? = null,
@SerializedName("screen_name") val screenName: String? = null,
@SerializedName("module_name") val moduleName: String? = null,
@SerializedName("attributes") val attributes: HashMap<String, Any>? = null,
@SerializedName("fragment_list") val fragmentList: List<String>? = null
)

View File

@@ -9,7 +9,6 @@ package com.navi.alfred.network
import com.navi.alfred.model.AnalyticsRequest
import com.navi.alfred.model.CruiseAttributes
import com.navi.alfred.model.EventMetricRequest
import com.navi.alfred.model.FailureRequest
import com.navi.alfred.model.SessionRequest
import com.navi.alfred.network.model.CruiseResponse
@@ -63,15 +62,6 @@ class AlfredNetworkRepository {
return AlfredRetrofitProvider.getApiService().uploadToS3(preSignedUrl, request, ALFRED)
}
suspend fun eventMetric(
url: String,
apiKey: String,
metricRequestBody: EventMetricRequest
): Response<Unit> {
return AlfredRetrofitProvider.getApiService()
.sendMetric(url, ALFRED, apiKey, "application/json", metricRequestBody)
}
suspend fun cruiseConfig(
url: String,
appVersionName: String,

View File

@@ -14,9 +14,7 @@ import com.google.gson.GsonBuilder
import com.navi.alfred.AlfredManager
import com.navi.alfred.BuildConfig
import com.navi.alfred.deserializer.AnalyticsDataDeserializer
import com.navi.alfred.deserializer.MetricsDataDeserializer
import com.navi.alfred.deserializer.SessionDataDeserializer
import com.navi.alfred.model.EventMetricRequest
import com.navi.alfred.model.SessionRequest
import com.navi.alfred.utils.AlfredConstants
import com.navi.alfred.utils.ApiConstants
@@ -114,7 +112,6 @@ object AlfredRetrofitProvider {
AnalyticsDataDeserializer()
)
.registerTypeAdapter(SessionRequest::class.java, SessionDataDeserializer())
.registerTypeAdapter(EventMetricRequest::class.java, MetricsDataDeserializer())
.create()
return Retrofit.Builder()
.baseUrl(baseUrl)

View File

@@ -8,7 +8,6 @@
package com.navi.alfred.network
import com.navi.alfred.model.AnalyticsRequest
import com.navi.alfred.model.EventMetricRequest
import com.navi.alfred.model.FailureRequest
import com.navi.alfred.model.SessionRequest
import com.navi.alfred.network.model.CruiseResponse
@@ -62,15 +61,6 @@ interface AlfredRetrofitService {
@Body sessionRequest: SessionRequest
): Response<Unit>
@POST
suspend fun sendMetric(
@Url url: String,
@Header(X_TARGET) target: String,
@Header(X_API_KEY) apiKey: String,
@Header(CONTENT_TYPE) contentType: String,
@Body metricRequestBody: EventMetricRequest
): Response<Unit>
@GET
suspend fun getCruiseConfig(
@Url url: String,

View File

@@ -12,7 +12,6 @@ import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.navi.alfred.AlfredManager
import com.navi.alfred.db.model.AnalyticsEvent
import com.navi.alfred.db.model.ApiMetricHelper
import com.navi.alfred.db.model.FailureEvent
import com.navi.alfred.db.model.NegativeCase
import com.navi.alfred.db.model.ZipDetailsHelper
@@ -21,27 +20,22 @@ import com.navi.alfred.model.AnalyticsRequest
import com.navi.alfred.model.BaseAttribute
import com.navi.alfred.model.DeviceAttributes
import com.navi.alfred.model.EventAttribute
import com.navi.alfred.model.EventMetricRequest
import com.navi.alfred.model.Failure
import com.navi.alfred.model.FailureAttributes
import com.navi.alfred.model.FailureRequest
import com.navi.alfred.model.MetricAttribute
import com.navi.alfred.model.SessionEventAttribute
import com.navi.alfred.model.SessionRequest
import com.navi.alfred.utils.AlfredConstants.API_ERROR
import com.navi.alfred.utils.AlfredConstants.DEFAULT_INGEST_METRIC_URL
import com.navi.alfred.utils.AlfredConstants.DEFAULT_SEND_CRASH_URL
import com.navi.alfred.utils.AlfredConstants.DEFAULT_SEND_EVENT_POST_URL
import com.navi.alfred.utils.AlfredConstants.DEFAULT_SEND_FAILURE_POST_URL
import com.navi.alfred.utils.AlfredConstants.DEFAULT_SEND_SESSION_POST_URL
import com.navi.alfred.utils.AlfredConstants.INGEST_CRASH_FAILURE
import com.navi.alfred.utils.AlfredConstants.INGEST_EVENT_FAILURE
import com.navi.alfred.utils.AlfredConstants.INGEST_METRIC_FAILURE
import com.navi.alfred.utils.AlfredConstants.INGEST_SESSION_FAILURE
import com.navi.alfred.utils.AlfredConstants.POST_METHOD
import com.navi.alfred.worker.AddEventTask
import com.navi.alfred.worker.AddFailureTask
import com.navi.alfred.worker.AddMetricTask
import com.navi.alfred.worker.AddNegativeCase
import java.lang.reflect.Type
import java.util.UUID
@@ -393,102 +387,6 @@ internal fun sendAlfredSessionEvent(zipFileDetails: ZipDetailsHelper, dumpFlow:
return
}
internal suspend fun sendIngestMetric(
clientTs: Long? = null,
snapshotPerSecond: Int? = null,
workManagerFlow: Boolean? = false
): Boolean {
if (
(workManagerFlow == true) ||
(AlfredManager.config.getAlfredStatus() &&
AlfredManager.config.getEnableRecordingStatus())
) {
try {
var baseAttributes = BaseAttribute()
if (workManagerFlow == true) {
baseAttributes =
BaseAttribute(clientTs = clientTs, snapshotPerSecond = snapshotPerSecond)
AlfredManager.apiMetricDao = AlfredManager.alfredDataBase.apiMetricDao()
}
AlfredManager.mutex.withLock {
val metricEventList =
AlfredManager.apiMetricDao.fetchApiMetric(
AlfredManager.config.getEventBatchSize()
)
if (metricEventList.isNotEmpty()) {
try {
val detailsList = metricEventList.map { it.metric }
val listType: Type =
object : TypeToken<ArrayList<MetricAttribute?>?>() {}.type
val events: ArrayList<MetricAttribute> =
Gson().fromJson(detailsList.toString(), listType)
if (events.size > 0) {
val request =
EventMetricRequest(
baseAttribute = baseAttributes,
metricsAttribute = events
)
val response =
AlfredManager.networkRepository.eventMetric(
DEFAULT_INGEST_METRIC_URL,
AlfredManager.config.getApiKey(),
metricRequestBody = request
)
return if (
response.isSuccessful &&
response.code() == AlfredConstants.CODE_API_SUCCESS
) {
AlfredManager.apiMetricDao.deleteApiMetric(
metricEventList.map { it.id }
)
true
} else {
if (
!isNoInternetResponse(response.code()) &&
!isCriticalJourneyResponse(response.code())
) {
val failureEvent =
buildFailureEvent(
errorType = API_ERROR,
requestUrl = DEFAULT_INGEST_METRIC_URL,
requestMethod = POST_METHOD,
errorStatusCode = response.code().toLong(),
errorMessage = response.message(),
errorName = INGEST_METRIC_FAILURE
)
AlfredDispatcher.addTaskToQueue(
AddFailureTask(
failureEvent,
context = AlfredManager.applicationContext
)
)
}
if (response.code() == AlfredConstants.CODE_API_BAD_REQUEST) {
AlfredManager.apiMetricDao.deleteApiMetric(
metricEventList.map { it.id }
)
true
} else {
false
}
}
}
} catch (e: Exception) {
return false
}
} else {
return false
}
}
} catch (e: Exception) {
e.log()
return false
}
return false
}
return false
}
internal fun startSyncEvents() {
AlfredManager.timer =
fixedRateTimer(
@@ -498,8 +396,6 @@ internal fun startSyncEvents() {
AlfredManager.config.getEventsDelayInMilliseconds()
) {
AlfredManager.coroutineScope.launch {
AddMetricTask.resetEventCount()
sendIngestMetric()
AddEventTask.resetEventCount()
sendEventsToServer()
AddNegativeCase.resetEventCount()
@@ -586,24 +482,3 @@ internal fun buildFailureEvent(
)
return FailureEvent(timeStamp, Gson().toJson(eventData))
}
@WorkerThread
internal fun buildAppPerformanceEvent(
eventName: String,
eventType: String,
attribute: HashMap<String, Any>? = null
): ApiMetricHelper {
val timeStamp = AlfredManager.config.getAlfredCurrentTimeMillis()
val metricData =
MetricAttribute(
eventId = AlfredManager.config.getAlfredEventId(),
eventName = eventName,
eventType = eventType,
sessionId = AlfredManager.config.getAlfredSessionId(),
attributes = attribute,
screenName = AlfredManager.currentScreenName,
moduleName = AlfredManager.currentModuleName,
fragmentList = getFragmentList()
)
return ApiMetricHelper(timeStamp, Gson().toJson(metricData))
}

View File

@@ -1,53 +0,0 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.worker
import android.content.Context
import androidx.annotation.WorkerThread
import com.navi.alfred.AlfredManager
import com.navi.alfred.db.AlfredDatabaseHelper
import com.navi.alfred.db.model.ApiMetricHelper
import com.navi.alfred.dispatcher.AlfredDispatcher
import com.navi.alfred.utils.AlfredConstants
import java.util.concurrent.atomic.AtomicInteger
class AddMetricTask(private val event: ApiMetricHelper, private val context: Context) :
AnalyticsTask {
companion object {
private var eventCount: AtomicInteger = AtomicInteger(0)
fun resetEventCount() {
eventCount = AtomicInteger(0)
}
}
@WorkerThread
override suspend fun execute(): Boolean {
val db = AlfredDatabaseHelper.getAnalyticsDatabase(context)
val analyticsDao = db.apiMetricDao()
return try {
analyticsDao.insert(event)
eventCount.incrementAndGet()
checkIfSyncIsNeeded()
true
} catch (e: Exception) {
false
}
}
private fun checkIfSyncIsNeeded() {
if (eventCount.get() >= AlfredManager.config.getEventBatchSize()) {
resetEventCount()
AlfredDispatcher.executeInNewThread(SyncDataTask())
}
}
override fun getTaskName(): String {
return AlfredConstants.ADD_API_METRIC_TASK
}
}

View File

@@ -10,12 +10,11 @@ package com.navi.alfred.worker
import androidx.annotation.WorkerThread
import com.navi.alfred.utils.AlfredConstants.SYNC_EVENT_TASK
import com.navi.alfred.utils.sendEventsToServer
import com.navi.alfred.utils.sendIngestMetric
class SyncDataTask() : AnalyticsTask {
@WorkerThread
override suspend fun execute(): Boolean {
return sendEventsToServer() && sendIngestMetric()
return sendEventsToServer()
}
override fun getTaskName(): String {

View File

@@ -15,7 +15,6 @@ import com.navi.alfred.db.AlfredDatabaseHelper
import com.navi.alfred.utils.AlfredConstants
import com.navi.alfred.utils.sendEventsToServer
import com.navi.alfred.utils.sendFailureEventsToServer
import com.navi.alfred.utils.sendIngestMetric
import com.navi.alfred.utils.sendNegativeCaseToServer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -39,11 +38,6 @@ class UploadEventsWorker(context: Context, workerParams: WorkerParameters) :
snapshotPerSecond = snapshotPerSecond,
workManagerFlow = true
)
sendIngestMetric(
clientTs = clientTs,
snapshotPerSecond = snapshotPerSecond,
workManagerFlow = true
)
sendNegativeCaseToServer(
clientTs = clientTs,
snapshotPerSecond = snapshotPerSecond,