Skip to content
Merged
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
16 changes: 16 additions & 0 deletions sdk/src/main/java/cloud/mindbox/mobile_sdk/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ import androidx.annotation.IdRes
import cloud.mindbox.mobile_sdk.inapp.domain.models.InAppType
import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl
import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler
import com.android.volley.VolleyError
import com.android.volley.toolbox.HttpHeaderParser
import org.threeten.bp.Instant
import org.threeten.bp.LocalDateTime
import org.threeten.bp.ZoneOffset
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.format.DateTimeFormatter
import java.nio.charset.Charset
import java.util.Queue
import kotlin.math.roundToInt

Expand Down Expand Up @@ -182,4 +185,17 @@ internal fun PackageManager.getPackageInfoCompat(context: Context, flags: Int):
} else {
getPackageInfo(context.packageName, flags)
}
}

internal fun VolleyError.getErrorResponseBodyData(): String {
return this.networkResponse?.data
?.takeIf { it.isNotEmpty() }
?.toString(
Charset.forName(
HttpHeaderParser.parseCharset(
this.networkResponse?.headers ?: emptyMap()
)
)
)
?: ""
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
package cloud.mindbox.mobile_sdk.inapp.domain

import cloud.mindbox.mobile_sdk.getErrorResponseBodyData
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.InAppContentFetcher
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.InAppChoosingManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.repositories.InAppGeoRepository
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.repositories.InAppSegmentationRepository
import cloud.mindbox.mobile_sdk.inapp.domain.models.*
import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl
import cloud.mindbox.mobile_sdk.logger.mindboxLogD
import cloud.mindbox.mobile_sdk.logger.mindboxLogI
import cloud.mindbox.mobile_sdk.logger.mindboxLogW
import cloud.mindbox.mobile_sdk.models.InAppEventType
import com.android.volley.VolleyError
import kotlinx.coroutines.*

internal class InAppChoosingManagerImpl(
private val inAppGeoRepository: InAppGeoRepository,
private val inAppSegmentationRepository: InAppSegmentationRepository,
private val inAppContentFetcher: InAppContentFetcher
) :
InAppChoosingManager {
) : InAppChoosingManager {

companion object {
private const val RESPONSE_STATUS_CUSTOMER_SEGMENTS_REQUIRE_CUSTOMER =
"CheckCustomerSegments requires customer"
}
override suspend fun chooseInAppToShow(
inApps: List<InApp>,
triggerEvent: InAppEventType,
Expand Down Expand Up @@ -66,11 +73,7 @@ internal class InAppChoosingManagerImpl(
inAppSegmentationRepository.setCustomerSegmentationStatus(
CustomerSegmentationFetchStatus.SEGMENTATION_FETCH_ERROR
)
MindboxLoggerImpl.e(
this,
"Error fetching customer segmentations",
throwable
)
handleCustomerSegmentationErrorLog(throwable)
}

else -> {
Expand Down Expand Up @@ -124,6 +127,19 @@ internal class InAppChoosingManagerImpl(
)
}

private fun handleCustomerSegmentationErrorLog(error: CustomerSegmentationError) {
val volleyError = error.cause as? VolleyError
volleyError?.let { error ->
if ((error.networkResponse?.statusCode == 400) && (error.getErrorResponseBodyData()
.contains(RESPONSE_STATUS_CUSTOMER_SEGMENTS_REQUIRE_CUSTOMER))
) {
mindboxLogI("Cannot check customer segment. It's a new customer")
return
}
}
mindboxLogW("Error fetching customer segmentations", error)
}

private class TargetingDataWrapper(
override val triggerEventName: String,
override val operationBody: String? = null,
Expand Down
54 changes: 31 additions & 23 deletions sdk/src/main/java/cloud/mindbox/mobile_sdk/models/Requests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package cloud.mindbox.mobile_sdk.models

import android.os.Build
import cloud.mindbox.mobile_sdk.BuildConfig
import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl
import cloud.mindbox.mobile_sdk.getErrorResponseBodyData
import cloud.mindbox.mobile_sdk.logger.mindboxLogI
import cloud.mindbox.mobile_sdk.logger.mindboxLogW
import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler
import com.android.volley.NetworkResponse
import com.android.volley.ParseError
Expand Down Expand Up @@ -108,25 +110,16 @@ internal data class MindboxRequest(
//Logging error responses
override fun parseNetworkError(volleyError: VolleyError): VolleyError {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.e(
this,
"<--- Error ${volleyError.networkResponse?.statusCode} $fullUrl TimeMls:${volleyError.networkTimeMs}; ",
)
try {
volleyError.networkResponse?.allHeaders?.joinToString (
val json = volleyError.getErrorResponseBodyData()

logResponseResult(volleyError, json)

volleyError.networkResponse?.allHeaders?.joinToString(
separator = System.getProperty("line.separator") ?: "\n"
) { header ->
"${header.name}: ${header.value}"
}?.let { MindboxLoggerImpl.d(this, it) }

val json = String(
volleyError.networkResponse?.data ?: ByteArray(0),
Charset.forName(
HttpHeaderParser.parseCharset(
volleyError.networkResponse?.headers ?: emptyMap()
)
)
)
}?.let { mindboxLogI(it) }

logBodyResponse(json)
} catch (e: Exception) {
Expand All @@ -142,32 +135,47 @@ internal data class MindboxRequest(

private fun logResponse(response: NetworkResponse?) {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.d(this, "<--- ${response?.statusCode} $fullUrl")
mindboxLogI("<--- ${response?.statusCode} $fullUrl")

response?.allHeaders?.joinToString (
response?.allHeaders?.joinToString(
separator = System.getProperty("line.separator") ?: "\n"
) { header ->
"${header.name}: ${header.value}"
}?.let { MindboxLoggerImpl.d(this, it) }
}?.let { mindboxLogI(it) }
}
}

private fun logBodyResponse(json: String?) {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.d(this, "$json")
mindboxLogI("$json")
}
}

private fun logError(e: Exception) {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.d(this, e.message ?: "Empty message")
MindboxLoggerImpl.d(this, e.stackTraceToString())
mindboxLogW(e.message ?: "Empty message")
mindboxLogW(e.stackTraceToString())
}
}

private fun logEndResponse() {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.d(this, "<--- End of response")
mindboxLogI("<--- End of response")
}
}

private fun logResponseResult(volleyError: VolleyError?, json: String?) {
LoggingExceptionHandler.runCatching {
val logMessage = buildString {
append("<--- ")
append(if (json?.contains("\"status\": \"Success\"") == true) "Success" else "Error")
append(" ${volleyError?.networkResponse?.statusCode} $fullUrl TimeMls:${volleyError?.networkTimeMs}; ")
}
if (json?.contains("{\"status\": \"Success\"}") == true) {
mindboxLogI(logMessage)
} else {
mindboxLogW(logMessage)
}
}
}

Expand Down
29 changes: 25 additions & 4 deletions sdk/src/test/java/cloud/mindbox/mobile_sdk/ExtensionsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package cloud.mindbox.mobile_sdk

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.android.volley.NetworkResponse
import com.android.volley.VolleyError
import com.jakewharton.threetenabp.AndroidThreeTen
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.*
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
Expand All @@ -30,7 +30,8 @@ internal class ExtensionsTest {
@Test
fun `converting zoned date time to string`() {
val time: ZonedDateTime = ZonedDateTime.now()
val expectedResult = time.withZoneSameInstant(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"))
val expectedResult = time.withZoneSameInstant(ZoneId.systemDefault())
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"))
val actualResult = time.convertToString()
assertEquals(expectedResult, actualResult)
}
Expand Down Expand Up @@ -125,4 +126,24 @@ internal class ExtensionsTest {
assertTrue(linkedList.contains("tE5t4"))
assertEquals(3, linkedList.size)
}

@Test
fun `should return empty string if error has no network response data`() {
val error = VolleyError()
assertEquals("", error.getErrorResponseBodyData())
}

@Test
fun `should return response body data`() {
val responseBodyData = "test string"
val networkResponse = NetworkResponse(
400,
responseBodyData.toByteArray(),
true,
200,
emptyList()
)
val error = VolleyError(networkResponse)
assertEquals(responseBodyData, error.getErrorResponseBodyData())
}
}