Skip to content

Commit 6a4f929

Browse files
authored
Merge pull request #159 from hotwired/mb/custom_logger
Allow clients to provide a custom logger instance
2 parents 75d91a6 + 584c133 commit 6a4f929

29 files changed

Lines changed: 174 additions & 136 deletions

core/src/main/kotlin/dev/hotwire/core/bridge/Bridge.kt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ package dev.hotwire.core.bridge
33
import android.webkit.JavascriptInterface
44
import android.webkit.WebView
55
import androidx.annotation.VisibleForTesting
6-
import dev.hotwire.core.logging.logEvent
6+
import dev.hotwire.core.logging.logDebug
7+
import dev.hotwire.core.logging.logVerbose
78
import kotlinx.serialization.json.JsonElement
89
import java.lang.ref.WeakReference
910

@@ -30,37 +31,37 @@ class Bridge internal constructor(webView: WebView) {
3031
}
3132

3233
internal fun register(component: String) {
33-
logEvent("bridgeWillRegisterComponent", component)
34+
logDebug("bridgeWillRegisterComponent", component)
3435
val javascript = generateJavaScript("register", component.toJsonElement())
3536
evaluate(javascript)
3637
}
3738

3839
internal fun register(components: List<String>) {
39-
logEvent("bridgeWillRegisterComponents", components.joinToString())
40+
logDebug("bridgeWillRegisterComponents", components.joinToString())
4041
val javascript = generateJavaScript("register", components.toJsonElement())
4142
evaluate(javascript)
4243
}
4344

4445
internal fun unregister(component: String) {
45-
logEvent("bridgeWillUnregisterComponent", component)
46+
logDebug("bridgeWillUnregisterComponent", component)
4647
val javascript = generateJavaScript("unregister", component.toJsonElement())
4748
evaluate(javascript)
4849
}
4950

5051
internal fun replyWith(message: Message) {
51-
logEvent("bridgeWillReplyWithMessage", message.toString())
52+
logDebug("bridgeWillReplyWithMessage", message.toString())
5253
val internalMessage = InternalMessage.fromMessage(message)
5354
val javascript = generateJavaScript("replyWith", internalMessage.toJson().toJsonElement())
5455
evaluate(javascript)
5556
}
5657

5758
internal fun load() {
58-
logEvent("bridgeWillLoad")
59+
logDebug("bridgeWillLoad")
5960
evaluate(userScript())
6061
}
6162

6263
internal fun reset() {
63-
logEvent("bridgeDidReset")
64+
logDebug("bridgeDidReset")
6465
componentsAreRegistered = false
6566
}
6667

@@ -70,15 +71,15 @@ class Bridge internal constructor(webView: WebView) {
7071

7172
@JavascriptInterface
7273
fun bridgeDidInitialize() {
73-
logEvent("bridgeDidInitialize", "success")
74+
logDebug("bridgeDidInitialize", "success")
7475
runOnUiThread {
7576
delegate?.bridgeDidInitialize()
7677
}
7778
}
7879

7980
@JavascriptInterface
8081
fun bridgeDidUpdateSupportedComponents() {
81-
logEvent("bridgeDidUpdateSupportedComponents", "success")
82+
logDebug("bridgeDidUpdateSupportedComponents", "success")
8283
componentsAreRegistered = true
8384
}
8485

@@ -99,7 +100,7 @@ class Bridge internal constructor(webView: WebView) {
99100
}
100101

101102
internal fun evaluate(javascript: String) {
102-
logEvent("evaluatingJavascript", javascript)
103+
logVerbose("evaluatingJavascript", javascript)
103104
webView?.evaluateJavascript(javascript) {}
104105
}
105106

core/src/main/kotlin/dev/hotwire/core/bridge/BridgeComponentJsonConverter.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package dev.hotwire.core.bridge
22

33
import dev.hotwire.core.config.Hotwire
44
import dev.hotwire.core.logging.logError
5-
import kotlinx.serialization.encodeToString
65
import kotlinx.serialization.json.Json
76

87
abstract class BridgeComponentJsonConverter {

core/src/main/kotlin/dev/hotwire/core/bridge/BridgeDelegate.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dev.hotwire.core.bridge
33
import android.webkit.WebView
44
import androidx.lifecycle.DefaultLifecycleObserver
55
import androidx.lifecycle.LifecycleOwner
6-
import dev.hotwire.core.logging.logEvent
6+
import dev.hotwire.core.logging.logDebug
77
import dev.hotwire.core.logging.logWarning
88

99
@Suppress("unused")
@@ -63,7 +63,7 @@ class BridgeDelegate<D : BridgeDestination>(
6363

6464
internal fun bridgeDidReceiveMessage(message: Message): Boolean {
6565
return if (destinationIsActive && resolvedLocation == message.metadata?.url) {
66-
logEvent("bridgeDidReceiveMessage", message.toString())
66+
logDebug("bridgeDidReceiveMessage", message.toString())
6767
getOrCreateComponent(message.component)?.didReceive(message)
6868
true
6969
} else {
@@ -79,20 +79,20 @@ class BridgeDelegate<D : BridgeDestination>(
7979
// Lifecycle events
8080

8181
override fun onStart(owner: LifecycleOwner) {
82-
logEvent("bridgeDestinationDidStart", resolvedLocation)
82+
logDebug("bridgeDestinationDidStart", resolvedLocation)
8383
destinationIsActive = true
8484
activeComponents.forEach { it.didStart() }
8585
}
8686

8787
override fun onStop(owner: LifecycleOwner) {
8888
activeComponents.forEach { it.didStop() }
8989
destinationIsActive = false
90-
logEvent("bridgeDestinationDidStop", resolvedLocation)
90+
logDebug("bridgeDestinationDidStop", resolvedLocation)
9191
}
9292

9393
override fun onDestroy(owner: LifecycleOwner) {
9494
destinationIsActive = false
95-
logEvent("bridgeDestinationDidDestroy", resolvedLocation)
95+
logDebug("bridgeDestinationDidDestroy", resolvedLocation)
9696
}
9797

9898
// Retrieve component(s) by type

core/src/main/kotlin/dev/hotwire/core/bridge/JsonExtensions.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package dev.hotwire.core.bridge
22

33
import dev.hotwire.core.logging.logError
4-
import kotlinx.serialization.encodeToString
54
import kotlinx.serialization.json.Json
65
import kotlinx.serialization.json.JsonElement
76
import kotlinx.serialization.json.decodeFromJsonElement

core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import android.webkit.WebView
55
import dev.hotwire.core.bridge.BridgeComponent
66
import dev.hotwire.core.bridge.BridgeComponentFactory
77
import dev.hotwire.core.bridge.BridgeComponentJsonConverter
8+
import dev.hotwire.core.logging.DefaultHotwireLogger
9+
import dev.hotwire.core.logging.HotwireLogger
810
import dev.hotwire.core.turbo.config.PathConfiguration
9-
import dev.hotwire.core.turbo.http.HotwireHttpClient
1011
import dev.hotwire.core.turbo.offline.OfflineRequestHandler
1112
import dev.hotwire.core.turbo.webview.HotwireWebView
1213

@@ -32,16 +33,12 @@ class HotwireConfig internal constructor() {
3233
var offlineRequestHandler: OfflineRequestHandler? = null
3334

3435
/**
35-
* Enables/disables debug logging. This should be disabled in production environments.
36-
* Disabled by default.
36+
* Set a custom logger instance to handle library log messages in your app.
3737
*
38-
* Important: You should not enable debug logging in production release builds.
38+
* The default logger is [DefaultHotwireLogger] which prints logs to Logcat.
39+
* If you'd like to change this behavior, provide your own implementation of [HotwireLogger].
3940
*/
40-
var debugLoggingEnabled = false
41-
set(value) {
42-
field = value
43-
HotwireHttpClient.reset()
44-
}
41+
var logger: HotwireLogger = DefaultHotwireLogger
4542

4643
/**
4744
* Enables/disables debugging of web contents loaded into WebViews.

core/src/main/kotlin/dev/hotwire/core/files/delegates/FileChooserDelegate.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import android.webkit.ValueCallback
88
import android.webkit.WebChromeClient.FileChooserParams
99
import androidx.activity.result.ActivityResult
1010
import dev.hotwire.core.R
11-
import dev.hotwire.core.logging.logError
12-
import dev.hotwire.core.turbo.session.Session
1311
import dev.hotwire.core.files.util.HOTWIRE_REQUEST_CODE_FILES
1412
import dev.hotwire.core.files.util.HotwireFileProvider
13+
import dev.hotwire.core.logging.logError
14+
import dev.hotwire.core.turbo.session.Session
1515
import dev.hotwire.core.turbo.util.dispatcherProvider
1616
import kotlinx.coroutines.CoroutineScope
1717
import kotlinx.coroutines.Job
Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,47 @@
11
package dev.hotwire.core.logging
22

3-
import android.util.Log
43
import dev.hotwire.core.config.Hotwire
4+
import okhttp3.logging.HttpLoggingInterceptor
55

6-
internal object CoreLog {
7-
private const val DEFAULT_TAG = "Hotwire-Core"
8-
9-
private val debugEnabled get() = Hotwire.config.debugLoggingEnabled
10-
11-
internal fun d(msg: String) = log(Log.DEBUG, msg)
12-
13-
internal fun w(msg: String) = log(Log.WARN, msg)
14-
15-
internal fun e(msg: String) = log(Log.ERROR, msg)
6+
private const val DEFAULT_TAG = "Hotwire-Core"
7+
private const val PAD_END_LENGTH = 35
168

17-
private fun log(logLevel: Int, msg: String) {
18-
when (logLevel) {
19-
Log.DEBUG -> if (debugEnabled) Log.d(DEFAULT_TAG, msg)
20-
Log.WARN -> Log.w(DEFAULT_TAG, msg)
21-
Log.ERROR -> Log.e(DEFAULT_TAG, msg)
22-
}
9+
internal class HotwireHttpLogger : HttpLoggingInterceptor.Logger {
10+
override fun log(message: String) {
11+
Hotwire.config.logger.d(DEFAULT_TAG) { message }
2312
}
2413
}
2514

26-
private const val PAD_END_LENGTH = 35
15+
internal fun logVerbose(event: String, details: String = "") {
16+
Hotwire.config.logger.v(DEFAULT_TAG) {
17+
"${"$event ".padEnd(PAD_END_LENGTH, '.')} [$details]"
18+
}
19+
}
2720

28-
internal fun logEvent(event: String, details: String = "") {
29-
CoreLog.d("$event ".padEnd(PAD_END_LENGTH, '.') + " [$details]")
21+
internal fun logDebug(event: String, details: String = "") {
22+
Hotwire.config.logger.d(DEFAULT_TAG) {
23+
"${"$event ".padEnd(PAD_END_LENGTH, '.')} [$details]"
24+
}
3025
}
3126

32-
internal fun logEvent(event: String, attributes: List<Pair<String, Any>>) {
33-
val description = attributes.joinToString(prefix = "[", postfix = "]", separator = ", ") {
34-
"${it.first}: ${it.second}"
27+
internal fun logDebug(event: String, attributes: List<Pair<String, Any>>) {
28+
Hotwire.config.logger.d(DEFAULT_TAG) {
29+
val description = attributes.joinToString(prefix = "[", postfix = "]", separator = ", ") {
30+
"${it.first}: ${it.second}"
31+
}
32+
33+
"${"$event ".padEnd(PAD_END_LENGTH, '.')} $description"
3534
}
36-
CoreLog.d("$event ".padEnd(PAD_END_LENGTH, '.') + " $description")
3735
}
3836

3937
internal fun logWarning(event: String, details: String) {
40-
CoreLog.w("$event ".padEnd(PAD_END_LENGTH, '.') + " [$details]")
38+
Hotwire.config.logger.w(DEFAULT_TAG) {
39+
"${"$event ".padEnd(PAD_END_LENGTH, '.')} [$details]"
40+
}
4141
}
4242

43-
internal fun logError(event: String, error: Exception) {
44-
CoreLog.e("$event: ${error.stackTraceToString()}")
45-
}
43+
internal fun logError(event: String, throwable: Throwable) {
44+
Hotwire.config.logger.e(DEFAULT_TAG, throwable) {
45+
"$event: ${throwable.stackTraceToString()}"
46+
}
47+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package dev.hotwire.core.logging
2+
3+
import android.util.Log
4+
5+
internal object DefaultHotwireLogger : HotwireLogger {
6+
override var logLevel = HotwireLogLevel.NONE
7+
8+
override fun v(tag: String, msg: () -> String) {
9+
if (logLevel.priority <= HotwireLogLevel.VERBOSE.priority) {
10+
Log.v(tag, msg())
11+
}
12+
}
13+
14+
override fun d(tag: String, msg: () -> String) {
15+
if (logLevel.priority <= HotwireLogLevel.DEBUG.priority) {
16+
Log.d(tag, msg())
17+
}
18+
}
19+
20+
override fun i(tag: String, msg: () -> String) {
21+
if (logLevel.priority <= HotwireLogLevel.INFO.priority) {
22+
Log.i(tag, msg())
23+
}
24+
}
25+
26+
override fun w(tag: String, msg: () -> String) {
27+
if (logLevel.priority <= HotwireLogLevel.WARN.priority) {
28+
Log.w(tag, msg())
29+
}
30+
}
31+
32+
override fun e(tag: String, throwable: Throwable?, msg: () -> String) {
33+
if (logLevel.priority <= HotwireLogLevel.ERROR.priority) {
34+
Log.e(tag, msg(), throwable)
35+
}
36+
}
37+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package dev.hotwire.core.logging
2+
3+
enum class HotwireLogLevel(val priority: Int) {
4+
VERBOSE(0),
5+
DEBUG(1),
6+
INFO(2),
7+
WARN(3),
8+
ERROR(4),
9+
NONE(5)
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package dev.hotwire.core.logging
2+
3+
interface HotwireLogger {
4+
var logLevel: HotwireLogLevel
5+
fun v(tag: String, msg: () -> String)
6+
fun d(tag: String, msg: () -> String)
7+
fun i(tag: String, msg: () -> String)
8+
fun w(tag: String, msg: () -> String)
9+
fun e(tag: String, throwable: Throwable?, msg: () -> String)
10+
}

0 commit comments

Comments
 (0)