Skip to content

Commit 01547c5

Browse files
natiginfogithub-actions[bot]
authored andcommitted
[maps-android] use LogThrottler for MapboxRenderThread (#10035)
GitOrigin-RevId: 5282cf4666ee8fa232bf5ee932596133056bce78
1 parent eed1273 commit 01547c5

7 files changed

Lines changed: 102 additions & 10 deletions

File tree

maps-sdk/src/main/java/com/mapbox/maps/renderer/MapboxRenderThread.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import androidx.annotation.AnyThread
1010
import androidx.annotation.RestrictTo
1111
import androidx.annotation.UiThread
1212
import androidx.annotation.VisibleForTesting
13+
import com.mapbox.common.LogThrottler
1314
import com.mapbox.common.MapboxTracing
1415
import com.mapbox.common.MapboxTracing.MAPBOX_TRACE_ID
1516
import com.mapbox.maps.MapboxExperimental
@@ -110,6 +111,11 @@ internal abstract class MapboxRenderThread : Choreographer.FrameCallback {
110111
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
111112
internal var surface: Surface? = null
112113

114+
/**
115+
* Throttler for high-frequency render thread logs to prevent logcat spam.
116+
*/
117+
private val logThrottler = LogThrottler(LOG_THROTTLE_INTERVAL_MS)
118+
113119
@RenderThread
114120
private var width: Int = 0
115121
@RenderThread
@@ -629,7 +635,11 @@ internal abstract class MapboxRenderThread : Choreographer.FrameCallback {
629635
}
630636
}
631637
} else if (!paused) {
632-
logI(TAG, "renderThreadPrepared=false and Android surface is not valid (isValid=${surface?.isValid}). Waiting for new one.")
638+
logI(
639+
TAG,
640+
"renderThreadPrepared=false and Android surface is not valid (isValid=${surface?.isValid}). Waiting for new one.",
641+
logThrottler
642+
)
633643
}
634644
}
635645

@@ -761,6 +771,10 @@ internal abstract class MapboxRenderThread : Choreographer.FrameCallback {
761771
* rescheduling configuration with that delay in order not to overflood handler thread message queue.
762772
*/
763773
internal const val RETRY_DELAY_MS = 50L
774+
/**
775+
* Interval for throttling high-frequency render thread logs (in milliseconds).
776+
*/
777+
private const val LOG_THROTTLE_INTERVAL_MS = 300L
764778
/**
765779
* Delay before calling resetThreadServiceType() on resume to ensure CPU affinity is properly set.
766780
* This delay helps address timing issues where CPU affinity might not be set immediately

maps-sdk/src/test/java/com/mapbox/maps/renderer/GLMapboxRenderThreadTest.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,29 @@ import com.mapbox.maps.logW
1212
import com.mapbox.maps.renderer.MapboxRenderThread.Companion.RETRY_DELAY_MS
1313
import com.mapbox.maps.renderer.egl.EGLCore
1414
import com.mapbox.maps.renderer.gl.TextureRenderer
15+
import com.mapbox.maps.shadows.ShadowLogThrottler
1516
import com.mapbox.maps.viewannotation.ViewAnnotationUpdateMode
1617
import com.mapbox.verifyNo
1718
import com.mapbox.verifyOnce
1819
import com.mapbox.waitZeroCounter
19-
import io.mockk.*
20+
import io.mockk.Runs
21+
import io.mockk.every
22+
import io.mockk.just
23+
import io.mockk.mockk
24+
import io.mockk.mockkStatic
25+
import io.mockk.spyk
26+
import io.mockk.unmockkAll
27+
import io.mockk.unmockkStatic
28+
import io.mockk.verify
29+
import io.mockk.verifyOrder
2030
import org.junit.After
2131
import org.junit.Assert.assertEquals
2232
import org.junit.Assert.assertFalse
2333
import org.junit.Test
2434
import org.junit.runner.RunWith
2535
import org.robolectric.RobolectricTestRunner
2636
import org.robolectric.Shadows
37+
import org.robolectric.annotation.Config
2738
import org.robolectric.annotation.LooperMode
2839
import org.robolectric.shadows.ShadowChoreographer
2940
import org.robolectric.shadows.ShadowLog
@@ -34,6 +45,11 @@ import java.util.concurrent.locks.Condition
3445
import java.util.concurrent.locks.ReentrantLock
3546

3647
@RunWith(RobolectricTestRunner::class)
48+
@Config(
49+
shadows = [
50+
ShadowLogThrottler::class
51+
]
52+
)
3753
@LooperMode(LooperMode.Mode.PAUSED)
3854
class GLMapboxRenderThreadTest {
3955

@@ -74,6 +90,7 @@ class GLMapboxRenderThreadTest {
7490
every { logE(any(), any()) } answers { Log.e(firstArg(), secondArg()) }
7591
every { logW(any(), any()) } answers { Log.e(firstArg(), secondArg()) }
7692
every { logI(any(), any()) } answers { Log.i(firstArg(), secondArg()) }
93+
every { logI(any(), any(), any()) } answers { Log.i(firstArg(), secondArg()) }
7794
}
7895

7996
private fun mockSurface() {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.mapbox.maps.shadows
2+
3+
import com.mapbox.common.LogThrottler
4+
import org.robolectric.annotation.Implements
5+
6+
@Implements(LogThrottler::class)
7+
public class ShadowLogThrottler

sdk-base/api/Release/metalava.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,14 @@ package com.mapbox.maps {
133133
public final class MapboxLogger {
134134
method public static boolean isLoggableD();
135135
method public static void logD(String tag, String message);
136+
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static void logD(String tag, String message, com.mapbox.common.LogThrottler? logThrottler);
136137
method public static inline void logD(String tag, kotlin.jvm.functions.Function0<java.lang.String> message);
137138
method public static void logE(String tag, String message);
139+
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static void logE(String tag, String message, com.mapbox.common.LogThrottler? logThrottler);
138140
method public static void logI(String tag, String message);
141+
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static void logI(String tag, String message, com.mapbox.common.LogThrottler? logThrottler);
139142
method public static void logW(String tag, String message);
143+
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static void logW(String tag, String message, com.mapbox.common.LogThrottler? logThrottler);
140144
}
141145

142146
public final class MapboxMapException extends java.lang.RuntimeException {

sdk-base/api/sdk-base.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,14 @@ public final class com/mapbox/maps/MapboxLocationComponentException : java/lang/
157157
public final class com/mapbox/maps/MapboxLogger {
158158
public static final fun isLoggableD ()Z
159159
public static final fun logD (Ljava/lang/String;Ljava/lang/String;)V
160+
public static final fun logD (Ljava/lang/String;Ljava/lang/String;Lcom/mapbox/common/LogThrottler;)V
160161
public static final fun logD (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
161162
public static final fun logE (Ljava/lang/String;Ljava/lang/String;)V
163+
public static final fun logE (Ljava/lang/String;Ljava/lang/String;Lcom/mapbox/common/LogThrottler;)V
162164
public static final fun logI (Ljava/lang/String;Ljava/lang/String;)V
165+
public static final fun logI (Ljava/lang/String;Ljava/lang/String;Lcom/mapbox/common/LogThrottler;)V
163166
public static final fun logW (Ljava/lang/String;Ljava/lang/String;)V
167+
public static final fun logW (Ljava/lang/String;Ljava/lang/String;Lcom/mapbox/common/LogThrottler;)V
164168
}
165169

166170
public final class com/mapbox/maps/MapboxMapException : java/lang/RuntimeException {

sdk-base/src/main/java/com/mapbox/common/MapboxMapsAndroidLogger.kt

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,49 @@ internal object MapboxMapsAndroidLogger {
1414
}
1515
}
1616

17-
internal fun internalLogE(tag: String, message: String) {
17+
internal fun internalLogE(tag: String, message: String, logThrottler: LogThrottler? = null) {
1818
try {
19-
Log.error(message, "$SDK_IDENTIFIER\\$tag")
19+
logThrottler?.let {
20+
Log.error(message, "$SDK_IDENTIFIER\\$tag", logThrottler)
21+
} ?: run {
22+
Log.error(message, "$SDK_IDENTIFIER\\$tag")
23+
}
2024
} catch (e: UnsatisfiedLinkError) {
2125
android.util.Log.e("$SDK_IDENTIFIER\\$tag", message)
2226
}
2327
}
2428

25-
internal fun internalLogW(tag: String, message: String) {
29+
internal fun internalLogW(tag: String, message: String, logThrottler: LogThrottler? = null) {
2630
try {
27-
Log.warning(message, "$SDK_IDENTIFIER\\$tag")
31+
logThrottler?.let {
32+
Log.warning(message, "$SDK_IDENTIFIER\\$tag", logThrottler)
33+
} ?: run {
34+
Log.warning(message, "$SDK_IDENTIFIER\\$tag")
35+
}
2836
} catch (e: UnsatisfiedLinkError) {
2937
android.util.Log.w("$SDK_IDENTIFIER\\$tag", message)
3038
}
3139
}
3240

33-
internal fun internalLogI(tag: String, message: String) {
41+
internal fun internalLogI(tag: String, message: String, logThrottler: LogThrottler? = null) {
3442
try {
35-
Log.info(message, "$SDK_IDENTIFIER\\$tag")
43+
logThrottler?.let {
44+
Log.info(message, "$SDK_IDENTIFIER\\$tag", logThrottler)
45+
} ?: run {
46+
Log.info(message, "$SDK_IDENTIFIER\\$tag")
47+
}
3648
} catch (e: UnsatisfiedLinkError) {
3749
android.util.Log.i("$SDK_IDENTIFIER\\$tag", message)
3850
}
3951
}
4052

41-
internal fun internalLogD(tag: String, message: String) {
53+
internal fun internalLogD(tag: String, message: String, logThrottler: LogThrottler? = null) {
4254
try {
43-
Log.debug(message, "$SDK_IDENTIFIER\\$tag")
55+
logThrottler?.let {
56+
Log.debug(message, "$SDK_IDENTIFIER\\$tag", logThrottler)
57+
} ?: run {
58+
Log.debug(message, "$SDK_IDENTIFIER\\$tag")
59+
}
4460
} catch (e: UnsatisfiedLinkError) {
4561
android.util.Log.d("$SDK_IDENTIFIER\\$tag", message)
4662
}

sdk-base/src/main/java/com/mapbox/maps/MapboxLogger.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
package com.mapbox.maps
44

5+
import androidx.annotation.RestrictTo
6+
import com.mapbox.common.LogThrottler
57
import com.mapbox.common.MapboxMapsAndroidLogger.SDK_IDENTIFIER
68
import com.mapbox.common.MapboxMapsAndroidLogger.internalIsLoggableD
79
import com.mapbox.common.MapboxMapsAndroidLogger.internalLogD
@@ -14,21 +16,49 @@ import com.mapbox.common.MapboxMapsAndroidLogger.internalLogW
1416
*/
1517
fun logE(tag: String, message: String) = internalLogE(tag, message)
1618

19+
/**
20+
* Log Android error entry in the following format: E/Mapbox: [[SDK_IDENTIFIER]\ [tag]] [message]
21+
* Internal version with optional log throttling support.
22+
*/
23+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
24+
fun logE(tag: String, message: String, logThrottler: LogThrottler?) = internalLogE(tag, message, logThrottler)
25+
1726
/**
1827
* Log Android warning entry in the following format: W/Mapbox: [[SDK_IDENTIFIER]\ [tag]] [message]
1928
*/
2029
fun logW(tag: String, message: String) = internalLogW(tag, message)
2130

31+
/**
32+
* Log Android warning entry in the following format: W/Mapbox: [[SDK_IDENTIFIER]\ [tag]] [message]
33+
* Internal version with optional log throttling support.
34+
*/
35+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
36+
fun logW(tag: String, message: String, logThrottler: LogThrottler?) = internalLogW(tag, message, logThrottler)
37+
2238
/**
2339
* Log Android info entry in the following format: I/Mapbox: [[SDK_IDENTIFIER]\ [tag]] [message]
2440
*/
2541
fun logI(tag: String, message: String) = internalLogI(tag, message)
2642

43+
/**
44+
* Log Android info entry in the following format: I/Mapbox: [[SDK_IDENTIFIER]\ [tag]] [message]
45+
* Internal version with optional log throttling support.
46+
*/
47+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
48+
fun logI(tag: String, message: String, logThrottler: LogThrottler?) = internalLogI(tag, message, logThrottler)
49+
2750
/**
2851
* Log Android debug entry in the following format: D/Mapbox: [[SDK_IDENTIFIER]\ [tag]] [message]
2952
*/
3053
fun logD(tag: String, message: String) = internalLogD(tag, message)
3154

55+
/**
56+
* Log Android debug entry in the following format: D/Mapbox: [[SDK_IDENTIFIER]\ [tag]] [message]
57+
* Internal version with optional log throttling support.
58+
*/
59+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
60+
fun logD(tag: String, message: String, logThrottler: LogThrottler?) = internalLogD(tag, message, logThrottler)
61+
3262
/**
3363
* Log Android debug entry in the following format: D/Mapbox: [[SDK_IDENTIFIER]\ [tag]] [message]
3464
* `message` lambda is only evaluated if the `debug` priority is enabled.

0 commit comments

Comments
 (0)