Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ internal abstract class BaseWebView(context: Context, attributeSet: AttributeSet
}

companion object {
private const val LOG_TAG = "BaseWebView"
internal const val ECP_LOG_TAG = "CheckoutECP"
private const val LOG_TAG = "base_web_view"
internal const val ECP_LOG_TAG = "ecp"
}
}

Expand All @@ -210,7 +210,7 @@ internal abstract class BaseWebView(context: Context, attributeSet: AttributeSet
internal fun BaseWebView.removeFromParent() {
val parent = this.parent
if (parent is ViewGroup) {
log.d("BaseWebView", "Existing parent found for WebView, removing.")
log.d("base_web_view", "Existing parent found for WebView, removing.")
parent.removeView(this)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,6 @@ internal class CheckoutDialog(
resources.configuration.uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES

companion object {
private const val LOG_TAG = "CheckoutDialog"
private const val LOG_TAG = "checkout_dialog"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,6 @@ internal class CheckoutWebView(context: Context, attributeSet: AttributeSet? = n
}

companion object {
private const val LOG_TAG = "CheckoutWebView"
private const val LOG_TAG = "checkout_web_view"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,39 @@ package com.shopify.checkoutkit

import android.util.Log

private const val LOG_TAG = "checkout_kit"
private const val DEFAULT_LOG_SCOPE = "sdk"

/**
* Wrap Log class static methods to allow testing and/or disabling debug logs
*/
public class LogWrapper {
public fun d(tag: String, msg: String) {
if (ShopifyCheckoutKit.configuration.logLevel == LogLevel.DEBUG) {
Log.d(tag, msg)
Log.d(LOG_TAG, formatMessage(tag, msg))
}
}

public fun w(tag: String, msg: String) {
if (listOf(LogLevel.DEBUG, LogLevel.WARN).contains(ShopifyCheckoutKit.configuration.logLevel)) {
Log.w(tag, msg)
Log.w(LOG_TAG, formatMessage(tag, msg))
}
}

public fun e(tag: String, msg: String) {
Log.e(tag, msg)
Log.e(LOG_TAG, formatMessage(tag, msg))
}

public fun e(tag: String, msg: String, throwable: Throwable) {
Log.e(tag, msg, throwable)
Log.e(LOG_TAG, formatMessage(tag, msg), throwable)
}

private fun formatMessage(tag: String, msg: String): String = "[$LOG_TAG:${tag.toLogScope()}] $msg"

private fun String.toLogScope(): String = when (this) {
"ShopifyCheckoutKit", "checkout_kit" -> DEFAULT_LOG_SCOPE
"ShopifyAcceleratedCheckouts" -> "accelerated_checkout"
"CheckoutECP" -> "ecp"
else -> this
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,22 @@ public object ShopifyCheckoutKit {
checkoutListener: T,
communicationClient: CheckoutCommunicationClient? = null,
): CheckoutKitDialog? {
log.d("ShopifyCheckoutKit", "Present called with checkoutUrl $checkoutUrl.")
log.d("sdk", "Present called with checkoutUrl $checkoutUrl.")
if (context.isDestroyed || context.isFinishing) {
log.d("ShopifyCheckoutKit", "Context is destroyed or finishing, returning null.")
log.d("sdk", "Context is destroyed or finishing, returning null.")
return null
}
log.d("ShopifyCheckoutKit", "Constructing Dialog")
log.d("sdk", "Constructing Dialog")
val dialog = CheckoutDialog(checkoutUrl, checkoutListener, context, communicationClient)
context.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onDestroy(owner: LifecycleOwner) {
log.d("ShopifyCheckoutKit", "Context is being destroyed, dismissing dialog.")
log.d("sdk", "Context is being destroyed, dismissing dialog.")
dialog.dismiss()
super.onDestroy(owner)
}
})

log.d("ShopifyCheckoutKit", "Starting Dialog.")
log.d("sdk", "Starting Dialog.")
dialog.start(context)
return CheckoutKitDialog { dialog.dismiss() }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ class LogWrapperTest {
it.logLevel = LogLevel.DEBUG
}

log.d("TAG", "Debug message")
log.d("tag", "Debug message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.DEBUG && it.tag == "TAG" && it.msg == "Debug message"
it.type == Log.DEBUG && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Debug message"
}
).isTrue()
}
Expand All @@ -48,10 +48,10 @@ class LogWrapperTest {
it.logLevel = LogLevel.WARN
}

log.d("TAG", "Debug message")
log.d("tag", "Debug message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.DEBUG && it.tag == "TAG" && it.msg == "Debug message"
it.type == Log.DEBUG && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Debug message"
}
).isFalse()
}
Expand All @@ -62,10 +62,10 @@ class LogWrapperTest {
it.logLevel = LogLevel.WARN
}

log.d("TAG", "Debug message")
log.d("tag", "Debug message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.DEBUG && it.tag == "TAG" && it.msg == "Debug message"
it.type == Log.DEBUG && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Debug message"
}
).isFalse()
}
Expand All @@ -76,10 +76,10 @@ class LogWrapperTest {
it.logLevel = LogLevel.DEBUG
}

log.w("TAG", "Warn message")
log.w("tag", "Warn message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.WARN && it.tag == "TAG" && it.msg == "Warn message"
it.type == Log.WARN && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Warn message"
}
).isTrue()
}
Expand All @@ -90,10 +90,10 @@ class LogWrapperTest {
it.logLevel = LogLevel.WARN
}

log.w("TAG", "Warn message")
log.w("tag", "Warn message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.WARN && it.tag == "TAG" && it.msg == "Warn message"
it.type == Log.WARN && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Warn message"
}
).isTrue()
}
Expand All @@ -104,10 +104,10 @@ class LogWrapperTest {
it.logLevel = LogLevel.ERROR
}

log.w("TAG", "Warn message")
log.w("tag", "Warn message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.WARN && it.tag == "TAG" && it.msg == "Warn message"
it.type == Log.WARN && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Warn message"
}
).isFalse()
}
Expand All @@ -118,10 +118,10 @@ class LogWrapperTest {
it.logLevel = LogLevel.DEBUG
}

log.e("TAG", "Error message")
log.e("tag", "Error message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.ERROR && it.tag == "TAG" && it.msg == "Error message"
it.type == Log.ERROR && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Error message"
}
).isTrue()
}
Expand All @@ -132,10 +132,10 @@ class LogWrapperTest {
it.logLevel = LogLevel.WARN
}

log.e("TAG", "Error message")
log.e("tag", "Error message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.ERROR && it.tag == "TAG" && it.msg == "Error message"
it.type == Log.ERROR && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Error message"
}
).isTrue()
}
Expand All @@ -146,11 +146,41 @@ class LogWrapperTest {
it.logLevel = LogLevel.ERROR
}

log.e("TAG", "Error message")
log.e("tag", "Error message")
assertThat(
ShadowLog.getLogs().any {
it.type == Log.ERROR && it.tag == "TAG" && it.msg == "Error message"
it.type == Log.ERROR && it.tag == "checkout_kit" && it.msg == "[checkout_kit:tag] Error message"
}
).isTrue()
}

@Test
fun `should normalize log scopes consistently`() {
ShopifyCheckoutKit.configure {
it.logLevel = LogLevel.ERROR
}

val cases = mapOf(
"ShopifyCheckoutKit" to "sdk",
"checkout_kit" to "sdk",
"sdk" to "sdk",
"ShopifyAcceleratedCheckouts" to "accelerated_checkout",
"CheckoutECP" to "ecp",
"accelerated_checkout" to "accelerated_checkout",
)

cases.forEach { (tag, scope) ->
ShadowLog.clear()

log.e(tag, "Error message")

assertThat(
ShadowLog.getLogs().any {
it.type == Log.ERROR &&
it.tag == "checkout_kit" &&
it.msg == "[checkout_kit:$scope] Error message"
}
).isTrue()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import timber.log.Timber
import timber.log.Timber.DebugTree

class MainActivity : ComponentActivity() {
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
Expand All @@ -38,7 +37,7 @@ class MainActivity : ComponentActivity() {

// Setup logging in debug build
if (BuildConfig.DEBUG) {
Timber.plant(DebugTree())
Timber.plant(CheckoutKitDebugTree())
}

setContent {
Expand Down Expand Up @@ -100,3 +99,10 @@ class MainActivity : ComponentActivity() {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
}

private class CheckoutKitDebugTree : Timber.DebugTree() {
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
val scope = tag ?: "mobile_buy_integration"
super.log(priority, "mobile_buy_integration", "[mobile_buy_integration:$scope] $message", t)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Logger(
insert(
LogLine(
type = LogType.STANDARD,
message = message,
message = formatMessage(message),
)
)
}
Expand All @@ -26,7 +26,7 @@ class Logger(
insert(
LogLine(
type = LogType.CHECKOUT_COMPLETED,
message = "Checkout completed: ${checkout.order?.id ?: "unknown"}",
message = formatMessage("Checkout completed: ${checkout.order?.id ?: "unknown"}"),
checkoutCompletedPayload = Json.encodeToString(checkout),
)
)
Expand All @@ -38,7 +38,7 @@ class Logger(
id = UUID.randomUUID(),
type = LogType.ERROR,
createdAt = Date().time,
message = message,
message = formatMessage(message),
errorDetails = ErrorDetails(
message = e.message ?: "No message on error",
type = "${e::class.java}"
Expand All @@ -50,4 +50,6 @@ class Logger(
private fun insert(logLine: LogLine) = coroutineScope.launch {
logDb.logDao().insert(logLine)
}

private fun formatMessage(message: String): String = "[mobile_buy_integration:app] $message"
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import java.util.Map;

public class CustomCheckoutListener extends DefaultCheckoutListener {
private static final String TAG = "ShopifyCheckoutKit";
private static final String TAG = "checkout_kit";
private static final String LOG_PREFIX = "checkout_kit";
private static final String LOG_SCOPE = "sdk";

private final ObjectMapper mapper = new ObjectMapper();

Expand Down Expand Up @@ -69,7 +71,7 @@ public void onGeolocationPermissionsShowPrompt(@NonNull String origin,
// Multi-shot geolocation requests can in principle arrive after a
// terminal event or explicit dismiss has released the dispatcher. Log
// so the silence is observable rather than mystifying.
Log.w(TAG, "Dropping geolocationRequest — dispatcher already released.");
Log.w(TAG, formatLogMessage("Dropping geolocationRequest — dispatcher already released."));
return;
}

Expand All @@ -81,7 +83,7 @@ public void onGeolocationPermissionsShowPrompt(@NonNull String origin,
payload.put("origin", origin);
dispatch.invoke(buildEnvelope(DispatchEventTypes.GEOLOCATION_REQUEST, payload));
} catch (IOException e) {
Log.e(TAG, "Error emitting \"geolocationRequest\" event", e);
Log.e(TAG, formatLogMessage("Error emitting \"geolocationRequest\" event"), e);
}
}

Expand All @@ -101,7 +103,7 @@ public void onCheckoutFailed(CheckoutException checkoutError) {
try {
dispatch.invoke(buildEnvelope(DispatchEventTypes.FAIL, populateErrorDetails(checkoutError)));
} catch (IOException e) {
Log.e(TAG, "Error processing checkout failed event", e);
Log.e(TAG, formatLogMessage("Error processing checkout failed event"), e);
} finally {
release();
}
Expand All @@ -115,7 +117,7 @@ public void onCheckoutCanceled() {
try {
dispatch.invoke(buildEnvelope(DispatchEventTypes.CLOSE, null));
} catch (IOException e) {
Log.e(TAG, "Error processing checkout canceled event", e);
Log.e(TAG, formatLogMessage("Error processing checkout canceled event"), e);
} finally {
release();
}
Expand All @@ -132,6 +134,10 @@ private String buildEnvelope(String type, @Nullable Object payload) throws IOExc
return mapper.writeValueAsString(envelope);
}

private String formatLogMessage(String message) {
return "[" + LOG_PREFIX + ":" + LOG_SCOPE + "] " + message;
}

private Map<String, Object> populateErrorDetails(CheckoutException checkoutError) {
Map<String, Object> errorMap = new HashMap();
errorMap.put("__typename", getErrorTypeName(checkoutError));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

private const val TAG = "ShopifyCheckoutKit"
private const val TAG = "checkout_kit"
private const val LOG_PREFIX = "checkout_kit"
private const val LOG_SCOPE = "sdk"

fun interface DispatchCallback {
fun invoke(json: String)
Expand Down Expand Up @@ -79,7 +81,7 @@ object ProtocolRelay {
val envelopeJson = json.encodeToString(DispatchEnvelope(type, payload))
dispatch.invoke(envelopeJson)
} catch (e: Exception) {
Log.e(TAG, "Error dispatching protocol event \"$type\"", e)
Log.e(TAG, "[$LOG_PREFIX:$LOG_SCOPE] Error dispatching protocol event \"$type\"", e)
}
}
}
Loading
Loading