Skip to content

Commit

Permalink
Merge pull request #8 from amank22/predict_type
Browse files Browse the repository at this point in the history
Log event type predict
  • Loading branch information
amank22 committed Jan 5, 2022
2 parents 8cfc78a + 97f0486 commit 9ebfe39
Show file tree
Hide file tree
Showing 30 changed files with 493 additions and 116 deletions.
6 changes: 3 additions & 3 deletions src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import ui.components.BodyPanel
import ui.components.IntroDialog
import ui.components.SideNavigation
import utils.APP_NAME
import utils.AppLog
import utils.Helpers
import utils.Log
import java.awt.Desktop

@Composable
Expand Down Expand Up @@ -67,7 +67,7 @@ private fun RemainingItems(state: LazyListState, lastIndex: Int) {
val fVIOfState = state.firstVisibleItemIndex
if (lastIndex - fVIOfState < 3) {
val firstVisibleItemIndex = fVIOfState - state.layoutInfo.visibleItemsInfo.size
Log.d("firstVisibleItemIndex", "${lastIndex - firstVisibleItemIndex}")
AppLog.d("firstVisibleItemIndex", "${lastIndex - firstVisibleItemIndex}")
}
}

Expand All @@ -85,7 +85,7 @@ private fun ParameterList(list: List<String>, modifier: Modifier) {
@OptIn(ExperimentalComposeUiApi::class)
fun main() = application(false) {
fun onClose(source: String) {
Log.d("QuitHandler", "Quiting : $source")
AppLog.d("QuitHandler", "Quiting : $source")
AdbHelper.close()
Db.close()
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/models/ItemSource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package models

import java.io.Serializable

sealed class ItemSource(val type: String) : Serializable {
sealed class ItemSource(val type: String, val icon: String) : Serializable {
companion object {
private const val serialVersionUID = 1L
}
}

object SourceFA : ItemSource("Firebase")
object SourceInternalContent : ItemSource("Content")
object SourceFA : ItemSource("Firebase", "icons/firebaseLogo.webp")
object SourceInternalContent : ItemSource("Content", "")
48 changes: 37 additions & 11 deletions src/main/kotlin/models/LogItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import processor.attribute
import utils.Helpers
import utils.hashMapEntityOf
import java.io.Serializable
import java.util.*
import javax.annotation.concurrent.GuardedBy

data class LogItem(
val source: ItemSource,
val eventName: String,
val properties: HashMap<String, Any> = hashMapEntityOf(),
val localTime: Long = System.currentTimeMillis(),
val internalContent: InternalContent? = null
val internalContent: InternalContent? = null,
) : Serializable {
companion object {
private const val serialVersionUID = 1L
Expand All @@ -23,26 +24,51 @@ data class LogItem(
fun errorContent(error: String) = LogItem(SourceInternalContent, "Error", internalContent = ErrorContent(error))
}

private val id: String = buildKey()

@Transient
var _propertiesAString: AnnotatedString? = null

@Transient
var _predictedEventType: PredictedEventType? = null

/**
* This is a predicted event type and there is no guarantee of it's accuracy
*/
fun predictedEventType(): PredictedEventType {
if (_predictedEventType == null) {
synchronized(lock) {
if (_predictedEventType == null) {
_predictedEventType = Helpers.predictEventType(this)
}
}
}
return _predictedEventType!!
}

@Transient
private val lock = true

val propertiesAString: AnnotatedString
@GuardedBy("lock")
get() {
if (_propertiesAString == null) {
synchronized(lock) {
if (_propertiesAString == null) {
_propertiesAString = Helpers.createAnnotatedString(properties)
}
@GuardedBy("lock")
fun propertiesAString(): AnnotatedString {
if (_propertiesAString == null) {
synchronized(lock) {
if (_propertiesAString == null) {
_propertiesAString = Helpers.createAnnotatedString(properties)
}
}
return _propertiesAString!!
}
return _propertiesAString!!
}

@Transient
var isSelected: Boolean = false

fun key() = "${source.type}_${eventName}_${localTime}_${properties.hashCode()}"
fun buildKey() = "${iKey()}_${localTime}"
fun key() = id

private fun iKey(): String {
val k = "${source.type}_${eventName}_${properties.hashCode()}"
return k + UUID.randomUUID().toString()
}
}
83 changes: 83 additions & 0 deletions src/main/kotlin/models/PredictedEventType.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package models

import java.io.Serializable

sealed class PredictedEventType(val displayMsg: String, val iconResource: String) : Serializable {
companion object {
private const val serialVersionUID = 1L
}
}

object EventTypeClick : PredictedEventType("Click", "icons/mouse-pointer-click.svg")
object EventTypeView : PredictedEventType("View", "icons/eye.svg")
object EventTypeInteraction : PredictedEventType("Interaction", "icons/activity.svg")
object EventTypeQuery : PredictedEventType("Search", "icons/ico-search.svg")
object EventTypeLoad : PredictedEventType("Load", "icons/loader.svg")
object EventTypeCheckout : PredictedEventType("Checkout", "icons/shopping-cart.svg")
object EventTypePurchase : PredictedEventType("Purchase", "icons/shopping-bag.svg")
object EventTypeReward : PredictedEventType("Reward", "icons/gift.svg")
object EventTypeBug : PredictedEventType("Bug/Exception", "icons/bug.svg")
object EventTypeDelete : PredictedEventType("Delete/Remove", "icons/trash-2.svg")
object EventTypeNotification : PredictedEventType("Notification", "icons/bell.svg")
object EventTypeLogIn : PredictedEventType("LogIn", "icons/log-in.svg")
object EventTypeLogOut : PredictedEventType("LogOut", "icons/log-out.svg")
object EventTypeNotSure : PredictedEventType("Other", "icons/activity.svg")


val predictionPropertiesMap = hashMapOf<String, PredictedEventType>().apply {
put("clicked", EventTypeClick)
put(" click", EventTypeClick)
put("openScreen", EventTypeView)
put("screenView", EventTypeView)
put("screenLoad", EventTypeLoad)
put("viewed", EventTypeView)
put("cardView", EventTypeView)
put("itemView", EventTypeView)
put("action", EventTypeInteraction)
put("loaded", EventTypeLoad)
put("loading", EventTypeLoad)
put("cardLoad", EventTypeLoad)
put("itemLoad", EventTypeLoad)
put("rendered", EventTypeView)
put("queried", EventTypeQuery)
put("searched", EventTypeQuery)
put("interaction", EventTypeInteraction)
put("impression", EventTypeInteraction)
put("checkout", EventTypeCheckout)
put("purchase", EventTypePurchase)
put("rewarded", EventTypeReward)
put("exception", EventTypeBug)
put("notification_", EventTypeNotification)
put("deleted", EventTypeDelete)
put("removed", EventTypeDelete)
}

val predictionEventNameMap = hashMapOf<String, PredictedEventType>().apply {
put("clicked", EventTypeClick)
put("openScreen", EventTypeView)
put("viewed", EventTypeView)
put("screenView", EventTypeView)
put("screenLoad", EventTypeLoad)
put("itemView", EventTypeView)
put("cardView", EventTypeView)
put("loaded", EventTypeLoad)
put("loading", EventTypeLoad)
put("queried", EventTypeQuery)
put("searched", EventTypeQuery)
put("interaction", EventTypeInteraction)
put("impression", EventTypeInteraction)
put("rendered", EventTypeView)
put("checkout", EventTypeCheckout)
put("purchase", EventTypePurchase)
put("rewarded", EventTypeReward)
put("exception", EventTypeBug)
put("notification_", EventTypeNotification)
put("loggedIn", EventTypeLogIn)
put("loggedOut", EventTypeLogOut)
put("signIn", EventTypeLogIn)
put("logIn", EventTypeLogIn)
put("logOut", EventTypeLogOut)
put("signOut", EventTypeLogOut)
put("deleted", EventTypeDelete)
put("removed", EventTypeDelete)
}
11 changes: 7 additions & 4 deletions src/main/kotlin/processor/MainProcessor.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package processor

import com.android.ddmlib.Log
import inputs.adb.AndroidLogStreamer
import inputs.adb.LogCatErrors
import inputs.adb.LogErrorNoSession
Expand All @@ -10,8 +11,8 @@ import kotlinx.coroutines.withContext
import models.LogItem
import models.SessionInfo
import storage.Db
import utils.AppLog
import utils.Helpers
import utils.Log
import utils.failureOrNull
import utils.getOrNull

Expand Down Expand Up @@ -83,7 +84,8 @@ class MainProcessor {
.filterNotNull()
.mapNotNull { logCatMessage2s ->
logCatMessage2s.filter {
Helpers.validateFALogString(it.message) && it.header.logLevel != com.android.ddmlib.Log.LogLevel.ERROR
Helpers.validateFALogString(it.message) &&
it.header.logLevel != Log.LogLevel.ERROR
}.map {
Helpers.parseFALogs(it)
}
Expand Down Expand Up @@ -115,7 +117,8 @@ class MainProcessor {
val fQuery = filterQuery?.trim()
logItemStream.collect { list ->
val filterResult = if (fQuery.isNullOrBlank() || fQuery == QUERY_PREFIX) {
filterLogs(indexedCollection, list, parser, "Select * from logs")
registerPropertiesInParser(list, parser)
list
} else {
try {
filterLogs(indexedCollection, list, parser, fQuery)
Expand All @@ -136,7 +139,7 @@ class MainProcessor {
try {
streamer.stop()
} catch (e: Exception) {
Log.d("unnecessary", "keeping exception for now in pause")
AppLog.d("unnecessary", "keeping exception for now in pause")
}
}
}
13 changes: 9 additions & 4 deletions src/main/kotlin/processor/QueryHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.googlecode.cqengine.index.radixinverted.InvertedRadixTreeIndex
import com.googlecode.cqengine.index.radixreversed.ReversedRadixTreeIndex
import com.googlecode.cqengine.query.parser.sql.SQLParser
import models.LogItem
import utils.Log
import utils.AppLog
import kotlin.reflect.KProperty1
import kotlin.time.ExperimentalTime
import kotlin.time.measureTimedValue
Expand Down Expand Up @@ -47,11 +47,16 @@ fun filterLogs(
val filterResult = measureTimedValue {
parser.retrieve(indexedCollection, filterQuery)
}
Log.d("filtering", "Time taken: ${filterResult.duration} , Retrieval Cost: ${filterResult.value.retrievalCost}")
if (filterResult.duration.inWholeSeconds > 2) {
AppLog.d(
"filtering", "Time taken: ${filterResult.duration} , " +
"Retrieval Cost: ${filterResult.value.retrievalCost}"
)
}
return filterResult.value.toList().sortedBy { it.localTime }
}

private fun registerPropertiesInParser(
fun registerPropertiesInParser(
list: List<LogItem>,
parser: SQLParser<LogItem>
) {
Expand All @@ -77,7 +82,7 @@ private fun registerMapPropertiesInParser(
parser, "$parentKey$k."
)
} else {
println("Attribute : ${att.attributeName} with first value = $v and v class = ${v.javaClass.name}")
// println("Attribute : ${att.attributeName} with first value = $v and v class = ${v.javaClass.name}")
parser.registerAttribute(att)
propertySet.add(k)
}
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/ui/components/ActionBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ private fun ButtonContent(

sealed class ActionMenu(val text: String, val isPrimary: Boolean, val icon: String = "") {
companion object {
val DefaultList = arrayListOf(ActionStart, ActionExport, ActionFeedback)
val PauseList = arrayListOf(ActionPause, ActionExport, ActionFeedback)
val DefaultList = arrayListOf(ActionStart, ActionExport)
val PauseList = arrayListOf(ActionPause, ActionExport)
}
}

// TODO: Add enable flag to disable button when maybe device is not connected or there is no data to export
object ActionStart : ActionMenu("Start", isPrimary = true, icon = "icons/ico_play.svg")
object ActionPause : ActionMenu("Pause", isPrimary = true, icon = "icons/ico_pause.svg")
object ActionStart : ActionMenu("Capture logs", isPrimary = true, icon = "icons/ico_play.svg")
object ActionPause : ActionMenu("Pause capturing", isPrimary = true, icon = "icons/ico_pause.svg")
object ActionExport : ActionMenu("Export Session Data", isPrimary = false, icon = "icons/ico-share.svg")
object ActionFeedback : ActionMenu("Feedback", isPrimary = false, icon = "icons/ico-email.svg")
//object ActionFeedback : ActionMenu("Feedback", isPrimary = false, icon = "icons/ico-email.svg")
29 changes: 19 additions & 10 deletions src/main/kotlin/ui/components/BodyPanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import models.LogItem
import models.SourceInternalContent
import processor.MainProcessor
import ui.CustomTheme
import utils.AppSettings

@Composable
fun BodyPanel(
Expand All @@ -36,18 +37,31 @@ fun BodyPanel(
) {
val logItems = remember(sessionId) { mutableStateListOf<LogItem>() }
var streamRunning by remember(sessionId) { mutableStateOf(false) }
Column(modifier) {
val scope = rememberCoroutineScope()
val state = rememberSaveable(saver = LazyListState.Saver, key = sessionId) {
LazyListState()
val scope = rememberCoroutineScope()
val state = rememberSaveable(saver = LazyListState.Saver, key = sessionId) {
LazyListState()
}

fun scrollToTop() {
if (logItems.isNotEmpty()) {
scope.launch {
state.scrollToItem((logItems.size - 1).coerceAtLeast(0))
}
}
}

Column(modifier) {
var actionMenuItems by remember(sessionId) { mutableStateOf(ActionMenu.DefaultList) }
val currentDevice by Devices.currentDeviceFlow.collectAsState()
var errorString by remember(currentDevice) {
mutableStateOf(if (currentDevice == null) "No device is connected" else "")
}
val onNewMessage: (msg: List<LogItem>) -> Unit = { msg ->
logItems.addAll(msg)
// AppLog.d("Got Message", msg.toString())
if (AppSettings.getFlagOr(AppSettings.AUTO_SCROLL, true)) {
scrollToTop()
}
}
val onError: (logError: LogCatErrors) -> Unit = {
actionMenuItems = ActionMenu.DefaultList
Expand Down Expand Up @@ -77,11 +91,7 @@ fun BodyPanel(
fun oldStreamFun(filterQuery: String? = null) {
fetchOldData(processor, scope, filterQuery) {
onNewMessage(it)
if (logItems.isNotEmpty()) {
scope.launch {
state.scrollToItem((logItems.size - 1).coerceAtLeast(0))
}
}
scrollToTop()
}
}
BodyHeader(
Expand Down Expand Up @@ -268,7 +278,6 @@ private fun streamData(
) {
scope.launch {
processor.observeNewStream(onError) { msg ->
// Log.d("Got Message" , msg)
onMessage(msg)
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/main/kotlin/ui/components/Chip.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import ui.CustomTheme
import ui.LocalCustomColors
Expand All @@ -20,6 +22,7 @@ fun Chip(
bgColor: Color = LocalCustomColors.current.componentBackground,
textColor: Color = LocalCustomColors.current.highContrast,
addBorder: Boolean = false,
textStyle: TextStyle = LocalCustomTypography.current.bodySmall,
icon: @Composable (() -> Unit)? = null,
) {
var modifier1 = modifier.background(bgColor, CustomTheme.shapes.small)
Expand All @@ -32,7 +35,7 @@ fun Chip(
modifier1, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(text, color = textColor, style = LocalCustomTypography.current.bodySmall)
Text(text, color = textColor, style = textStyle, textAlign = TextAlign.Center, maxLines = 1)
if (icon != null) {
Box(Modifier.size(18.dp)) {
icon()
Expand Down

0 comments on commit 9ebfe39

Please sign in to comment.