Skip to content

Commit b194059

Browse files
committed
chore(logging): add header to exported log with device info; filter out RPC Request/Responses
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 5bb47ba commit b194059

7 files changed

Lines changed: 89 additions & 14 deletions

File tree

apps/flipcash/features/onramp/src/main/kotlin/com/flipcash/app/onramp/internal/OnRampViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ internal class OnRampViewModel @Inject constructor(
341341
val token = stateFlow.value.token
342342
?: return@flatMapResult Result.failure(IllegalStateException("No token"))
343343
val amount = stateFlow.value.amountEntryState.selectedAmount
344-
println("attempting buy of $amount of ${token.symbol} with $txHash")
344+
345345
transactionController.buy(
346346
owner = owner,
347347
amount = amount,

apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampWebview.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ package com.flipcash.app.onramp
33
import android.annotation.SuppressLint
44
import android.webkit.JavascriptInterface
55
import android.webkit.WebChromeClient
6-
import android.webkit.WebSettings
76
import android.webkit.WebResourceError
87
import android.webkit.WebResourceRequest
8+
import android.webkit.WebSettings
99
import android.webkit.WebView
1010
import android.webkit.WebViewClient
1111
import androidx.compose.foundation.layout.fillMaxSize
1212
import androidx.compose.runtime.Composable
13-
import androidx.compose.runtime.remember
1413
import androidx.compose.ui.Modifier
1514
import androidx.compose.ui.draw.alpha
16-
import androidx.compose.ui.viewinterop.AndroidView
1715
import androidx.webkit.WebSettingsCompat
1816
import androidx.webkit.WebViewCompat
1917
import androidx.webkit.WebViewFeature

apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/OnRampController.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import com.getcode.opencode.model.financial.CurrencyCode
2020
import com.getcode.opencode.model.financial.Fiat
2121
import com.getcode.opencode.model.financial.Token
2222
import com.getcode.opencode.model.financial.usdf
23-
import com.getcode.solana.keys.Mint
2423
import com.getcode.solana.keys.base58
2524
import com.getcode.utils.base64
2625
import kotlinx.serialization.Serializable

libs/logging/src/main/kotlin/com/getcode/utils/FileTree.kt

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package com.getcode.utils
22

33
import android.content.Context
4+
import android.content.pm.PackageManager
5+
import android.os.Build
46
import android.util.Log
7+
import com.bugsnag.android.Bugsnag
58
import timber.log.Timber
69
import java.io.File
710
import java.io.FileOutputStream
811
import java.io.OutputStreamWriter
912
import java.time.Instant
1013
import java.time.ZoneId
1114
import java.time.format.DateTimeFormatter
15+
import java.util.Locale
16+
import java.util.TimeZone
1217

1318
class FileTree(
1419
context: Context,
@@ -17,7 +22,9 @@ class FileTree(
1722

1823
private val traceDir = File(context.filesDir, "traces").apply { mkdirs() }
1924
private val logFile = File(traceDir, "trace.log")
25+
private val exportFile = File(traceDir, "trace_export.log")
2026
private val lock = Any()
27+
private val appContext: Context = context.applicationContext
2128

2229
private val formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME
2330
.withZone(ZoneId.systemDefault())
@@ -65,11 +72,58 @@ class FileTree(
6572
}
6673
}
6774

68-
fun getLogFile(): File? = if (logFile.exists() && logFile.length() > 0) logFile else null
75+
fun getLogFile(): File? {
76+
if (!logFile.exists() || logFile.length() == 0L) return null
77+
synchronized(lock) {
78+
exportFile.delete()
79+
exportFile.writeText(buildDeviceHeader(appContext))
80+
logFile.inputStream().use { input ->
81+
FileOutputStream(exportFile, true).use { output ->
82+
input.copyTo(output)
83+
}
84+
}
85+
}
86+
return exportFile
87+
}
6988

7089
fun clearLogs() {
7190
synchronized(lock) {
7291
logFile.delete()
92+
exportFile.delete()
7393
}
7494
}
7595
}
96+
97+
@Suppress("DEPRECATION")
98+
private fun buildDeviceHeader(context: Context): String {
99+
val packageInfo = try {
100+
context.packageManager.getPackageInfo(context.packageName, 0)
101+
} catch (_: PackageManager.NameNotFoundException) {
102+
null
103+
}
104+
105+
val versionName = packageInfo?.versionName ?: "unknown"
106+
val versionCode = packageInfo?.let {
107+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) it.longVersionCode else it.versionCode.toLong()
108+
} ?: -1
109+
110+
val userId = if (Bugsnag.isStarted()) Bugsnag.getUser().id else null
111+
112+
return buildString {
113+
appendLine("=".repeat(60))
114+
appendLine("DEVICE & APP INFO")
115+
appendLine("=".repeat(60))
116+
appendLine("App Version: $versionName ($versionCode)")
117+
appendLine("Package: ${context.packageName}")
118+
appendLine("User ID: ${userId ?: "not set"}")
119+
appendLine("Device: ${Build.MANUFACTURER} ${Build.MODEL}")
120+
appendLine("Android: ${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})")
121+
appendLine("Build: ${Build.DISPLAY}")
122+
appendLine("ABI: ${Build.SUPPORTED_ABIS.joinToString()}")
123+
appendLine("Locale: ${Locale.getDefault()}")
124+
appendLine("Timezone: ${TimeZone.getDefault().id}")
125+
appendLine("Exported: ${Instant.now()}")
126+
appendLine("=".repeat(60))
127+
appendLine()
128+
}
129+
}

libs/logging/src/main/kotlin/com/getcode/utils/Logging.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ object TraceManager {
8585
val tree = FileTree(context, plugins = { plugins })
8686
fileTree = tree
8787
addPlugin(PiiMaskingPlugin())
88+
addPlugin(RpcBodyFilterPlugin())
8889
Timber.plant(tree)
8990
}
9091

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.getcode.utils
2+
3+
class RpcBodyFilterPlugin : TraceLogPlugin {
4+
override fun process(line: String): String? {
5+
if ("[RpcLogging]" !in line) return line
6+
if ("Request:" in line || "Response:" in line) return null
7+
return line
8+
}
9+
}

libs/logging/src/test/kotlin/com/getcode/utils/FileTreeTest.kt

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@ class FileTreeTest {
8282
Timber.d("second")
8383
Timber.d("third")
8484

85-
val lines = fileTree.getLogFile()!!.readLines().filter { it.isNotBlank() }
86-
assertEquals(3, lines.size)
85+
val content = fileTree.getLogFile()!!.readText()
86+
val logLines = content.lines().filter { it.startsWith("[") }
87+
assertEquals(3, logLines.size)
8788
}
8889

8990
@Test
@@ -200,8 +201,9 @@ class FileTreeTest {
200201
latch.await()
201202
executor.shutdown()
202203

203-
val lines = fileTree.getLogFile()!!.readLines().filter { it.isNotBlank() }
204-
assertEquals(threadCount * linesPerThread, lines.size)
204+
val content = fileTree.getLogFile()!!.readText()
205+
val logLines = content.lines().filter { it.startsWith("[") }
206+
assertEquals(threadCount * linesPerThread, logLines.size)
205207
}
206208

207209
@Test
@@ -237,16 +239,28 @@ class FileTreeTest {
237239
Timber.d("contains SECRET data")
238240
Timber.d("another normal message")
239241

240-
val lines = tree.getLogFile()!!.readLines().filter { it.isNotBlank() }
241-
assertEquals(2, lines.size)
242-
assertTrue(lines.all { !it.contains("SECRET") })
242+
val content = tree.getLogFile()!!.readText()
243+
val logLines = content.lines().filter { it.startsWith("[") }
244+
assertEquals(2, logLines.size)
245+
assertTrue(logLines.all { !it.contains("SECRET") })
243246
}
244247

245248
@Test
246249
fun `log file path is inside traces directory`() {
247250
Timber.d("path check")
248251
val file = fileTree.getLogFile()!!
249-
assertEquals("trace.log", file.name)
252+
assertEquals("trace_export.log", file.name)
250253
assertEquals("traces", file.parentFile?.name)
251254
}
255+
256+
@Test
257+
fun `exported log file includes device header`() {
258+
Timber.d("header check")
259+
val content = fileTree.getLogFile()!!.readText()
260+
assertTrue(content.contains("DEVICE & APP INFO"))
261+
assertTrue(content.contains("App Version:"))
262+
assertTrue(content.contains("Device:"))
263+
assertTrue(content.contains("Android:"))
264+
assertTrue(content.contains("Exported:"))
265+
}
252266
}

0 commit comments

Comments
 (0)