Skip to content

Commit

Permalink
Merge pull request #287 from hotwired/log-cleanup
Browse files Browse the repository at this point in the history
Improve how debug logging is enabled and how exceptions are logged
  • Loading branch information
jayohms authored Sep 7, 2023
2 parents 00ec73a + 0536200 commit f40d830
Show file tree
Hide file tree
Showing 14 changed files with 80 additions and 51 deletions.
11 changes: 11 additions & 0 deletions demo/src/main/kotlin/dev/hotwire/turbo/demo/main/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package dev.hotwire.turbo.demo.main

import android.os.Bundle
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
import dev.hotwire.turbo.BuildConfig
import dev.hotwire.turbo.activities.TurboActivity
import dev.hotwire.turbo.config.Turbo
import dev.hotwire.turbo.delegates.TurboActivityDelegate
import dev.hotwire.turbo.demo.R

Expand All @@ -14,5 +17,13 @@ class MainActivity : AppCompatActivity(), TurboActivity {
setContentView(R.layout.activity_main)

delegate = TurboActivityDelegate(this, R.id.main_nav_host)
configApp()
}

private fun configApp() {
if (BuildConfig.DEBUG) {
Turbo.config.debugLoggingEnabled = true
WebView.setWebContentsDebuggingEnabled(true)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package dev.hotwire.turbo.demo.main

import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import dev.hotwire.turbo.BuildConfig
import dev.hotwire.turbo.config.TurboPathConfiguration
import dev.hotwire.turbo.demo.features.imageviewer.ImageViewerFragment
import dev.hotwire.turbo.demo.features.numbers.NumberBottomSheetFragment
Expand All @@ -13,6 +11,7 @@ import dev.hotwire.turbo.demo.features.web.WebFragment
import dev.hotwire.turbo.demo.features.web.WebHomeFragment
import dev.hotwire.turbo.demo.features.web.WebModalFragment
import dev.hotwire.turbo.demo.util.HOME_URL
import dev.hotwire.turbo.demo.util.customUserAgent
import dev.hotwire.turbo.demo.util.initDayNightTheme
import dev.hotwire.turbo.session.TurboSessionNavHostFragment
import kotlin.reflect.KClass
Expand Down Expand Up @@ -44,16 +43,7 @@ class MainSessionNavHostFragment : TurboSessionNavHostFragment() {

override fun onSessionCreated() {
super.onSessionCreated()
session.webView.settings.userAgentString = customUserAgent(session.webView)
session.webView.settings.userAgentString = session.webView.customUserAgent
session.webView.initDayNightTheme()

if (BuildConfig.DEBUG) {
session.setDebugLoggingEnabled(true)
WebView.setWebContentsDebuggingEnabled(true)
}
}

private fun customUserAgent(webView: WebView): String {
return "Turbo Native Android ${webView.settings.userAgentString}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature
import dev.hotwire.turbo.config.Turbo
import dev.hotwire.turbo.config.TurboPathConfigurationProperties
import dev.hotwire.turbo.demo.R

Expand All @@ -34,6 +35,12 @@ fun WebView.initDayNightTheme() {
}
}

val WebView.customUserAgent: String
get() {
val turboSubstring = Turbo.userAgentSubstring()
return "$turboSubstring; ${settings.userAgentString}"
}

private fun isNightModeEnabled(context: Context): Boolean {
val currentNightMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
return currentNightMode == Configuration.UI_MODE_NIGHT_YES
Expand Down
15 changes: 3 additions & 12 deletions docs/ADVANCED-OPTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,11 @@ You may encounter situations where a truly single-`Activity` app may not be feas
In such cases, you need to create an additional `Activity` that also implements the `TurboActivity` interface. You will need to be sure to register each `Activity` by calling [`TurboSessionNavHostFragment.registeredActivities()`](../turbo/src/main/kotlin/dev/hotwire/turbo/session/TurboSessionNavHostFragment.kt) so that you can navigate between them.

## Enable Debug Logging
During development, you may want to see what `turbo-android` is doing behind the scenes. To enable debug logging, override the `onSessionCreated()` method in your `NavHostFragment` and call `session.setDebugLoggingEnabled(true)`. Debug logging should always be disabled in your production app. For example:
During development, you may want to see what `turbo-android` is doing behind the scenes. To enable debug logging, call `Turbo.config.debugLoggingEnabled = true`. Debug logging should always be disabled in your production app. For example:

```kotlin
class MainSessionNavHostFragment : TurboSessionNavHostFragment() {

// ...

override open fun onSessionCreated() {
super.onSessionCreated()

if (BuildConfig.DEBUG) {
session.setDebugLoggingEnabled(true)
}
}
if (BuildConfig.DEBUG) {
Turbo.config.debugLoggingEnabled = true
}
```

Expand Down
13 changes: 13 additions & 0 deletions turbo/src/main/kotlin/dev/hotwire/turbo/config/Turbo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dev.hotwire.turbo.config

object Turbo {
val config: TurboConfig = TurboConfig()

/**
* Provides a standard substring to be included in your WebView's user agent
* to identify itself as a Turbo Native app.
*/
fun userAgentSubstring(): String {
return "Turbo Native Android"
}
}
16 changes: 16 additions & 0 deletions turbo/src/main/kotlin/dev/hotwire/turbo/config/TurboConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.hotwire.turbo.config

import dev.hotwire.turbo.http.TurboHttpClient

class TurboConfig internal constructor() {
/**
* Enables/disables debug logging. This should be disabled in production environments.
* Disabled by default.
*
*/
var debugLoggingEnabled = false
set(value) {
field = value
TurboHttpClient.reset()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dev.hotwire.turbo.config
import dev.hotwire.turbo.BuildConfig
import dev.hotwire.turbo.util.TurboLog
import com.google.gson.annotations.SerializedName
import dev.hotwire.turbo.util.logError
import java.util.regex.PatternSyntaxException

internal data class TurboPathConfigurationRule(
Expand All @@ -17,7 +18,7 @@ internal data class TurboPathConfigurationRule(
private fun numberOfMatches(path: String, patternRegex: String): Int = try {
Regex(patternRegex, RegexOption.IGNORE_CASE).find(path)?.groups?.size ?: 0
} catch (e: PatternSyntaxException) {
TurboLog.e("PathConfiguration pattern error: ${e.description}")
logError("pathConfigurationPatternError", e)
if (BuildConfig.DEBUG) throw e else 0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.provider.MediaStore
import android.webkit.WebChromeClient.FileChooserParams
import dev.hotwire.turbo.util.TurboFileProvider
import dev.hotwire.turbo.util.TurboLog
import dev.hotwire.turbo.util.logError
import java.io.File
import java.io.IOException

Expand Down Expand Up @@ -48,7 +49,7 @@ internal class TurboCameraCaptureDelegate(val context: Context) {
val directory: File = TurboFileProvider.directory(context)
return File.createTempFile("Capture_", ".jpg", directory)
} catch (e: IOException) {
TurboLog.e("${e.message}")
logError("createTempFileError", e)
null
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import dev.hotwire.turbo.util.TURBO_REQUEST_CODE_FILES
import dev.hotwire.turbo.util.TurboFileProvider
import dev.hotwire.turbo.util.TurboLog
import dev.hotwire.turbo.util.dispatcherProvider
import dev.hotwire.turbo.util.logError
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -72,7 +73,7 @@ internal class TurboFileChooserDelegate(val session: TurboSession) : CoroutineSc
destination.activityResultLauncher(TURBO_REQUEST_CODE_FILES)?.launch(intent)
true
} catch (e: Exception) {
TurboLog.e("${e.message}")
logError("startIntentError", e)
false
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package dev.hotwire.turbo.http

import android.content.Context
import dev.hotwire.turbo.config.Turbo
import dev.hotwire.turbo.util.TurboLog
import dev.hotwire.turbo.util.logError
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
Expand All @@ -28,7 +30,7 @@ object TurboHttpClient {
try {
cache?.evictAll()
} catch (e: IOException) {
TurboLog.e(e.toString())
logError("invalidateCacheError", e)
}
}

Expand Down Expand Up @@ -56,7 +58,7 @@ object TurboHttpClient {
builder.cache(it)
}

if (TurboLog.enableDebugLogging) {
if (Turbo.config.debugLoggingEnabled) {
builder.addInterceptor(loggingInterceptor)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import dev.hotwire.turbo.util.TurboLog
import dev.hotwire.turbo.util.dispatcherProvider
import dev.hotwire.turbo.util.logError
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Semaphore
Expand Down Expand Up @@ -105,7 +106,7 @@ internal class TurboHttpRepository(private val coroutineScope: CoroutineScope) {
} catch (e: IOException) {
throw e
} catch (e: Exception) {
TurboLog.e("Request error: ${e.message}")
logError("httpRequestError", e)
null
}
}
Expand Down Expand Up @@ -211,7 +212,7 @@ internal class TurboHttpRepository(private val coroutineScope: CoroutineScope) {
return try {
response?.body?.byteStream()
} catch (e: Exception) {
TurboLog.e("Byte stream error: ${e.message}")
logError("byteStreamError", e)
null
}
}
Expand Down
11 changes: 0 additions & 11 deletions turbo/src/main/kotlin/dev/hotwire/turbo/session/TurboSession.kt
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,6 @@ class TurboSession internal constructor(
isColdBooting = false
}

/**
* Enables/disables debug logging. This should be disabled in production environments.
* Disabled by default.
*
* @param enabled Whether to enable debug logging.
*/
fun setDebugLoggingEnabled(enabled: Boolean) {
TurboLog.enableDebugLogging = enabled
TurboHttpClient.reset()
}

// Internal

internal fun visit(visit: TurboVisit) {
Expand Down
18 changes: 12 additions & 6 deletions turbo/src/main/kotlin/dev/hotwire/turbo/util/TurboLog.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package dev.hotwire.turbo.util

import android.util.Log
import dev.hotwire.turbo.config.Turbo

internal object TurboLog {
private const val DEFAULT_TAG = "TurboLog"
internal var enableDebugLogging = false

fun d(msg: String) = log(Log.DEBUG, DEFAULT_TAG, msg)
private val debugEnabled get() = Turbo.config.debugLoggingEnabled

fun e(msg: String) = log(Log.ERROR, DEFAULT_TAG, msg)
internal fun d(msg: String) = log(Log.DEBUG, msg)

private fun log(logLevel: Int, tag: String, msg: String) {
internal fun e(msg: String) = log(Log.ERROR, msg)

private fun log(logLevel: Int, msg: String) {
when (logLevel) {
Log.DEBUG -> if (enableDebugLogging) Log.d(tag, msg)
Log.ERROR -> Log.e(tag, msg)
Log.DEBUG -> if (debugEnabled) Log.d(DEFAULT_TAG, msg)
Log.ERROR -> Log.e(DEFAULT_TAG, msg)
}
}
}
Expand All @@ -24,3 +26,7 @@ internal fun logEvent(event: String, attributes: List<Pair<String, Any>>) {
}
TurboLog.d("$event ".padEnd(35, '.') + " $description")
}

internal fun logError(event: String, error: Exception) {
TurboLog.e("$event: ${error.stackTraceToString()}")
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ internal class TurboUriHelper(val context: Context) {
}
file
} catch (e: Exception) {
TurboLog.e("${e.message}")
logError("writeFileError", e)
null
}
}
Expand Down Expand Up @@ -123,7 +123,7 @@ internal class TurboUriHelper(val context: Context) {

!outputFilePath.startsWith(destinationDirectoryPath)
} catch (e: Exception) {
TurboLog.e("${e.message}")
logError("canonicalPathError", e)
false
}
}
Expand All @@ -136,7 +136,7 @@ internal class TurboUriHelper(val context: Context) {
return try {
canonicalPath.contains(context.packageName)
} catch (e: IOException) {
TurboLog.e("${e.message}")
logError("canonicalPathError", e)
false
}
}
Expand Down

0 comments on commit f40d830

Please sign in to comment.