From c4fad0c911a0c35731b6ddc4e274d83703e6af73 Mon Sep 17 00:00:00 2001 From: bidetofevil Date: Fri, 13 Jun 2025 11:24:35 -0700 Subject: [PATCH 1/3] Increase limit for log properties to 100 --- .../internal/utils/PropertyUtils.kt | 2 +- .../internal/utils/PropertyUtilsTest.kt | 6 +-- .../testcases/features/LogFeatureTest.kt | 54 +++++++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/PropertyUtils.kt b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/PropertyUtils.kt index dfcad4a52d..b388c7cc58 100644 --- a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/PropertyUtils.kt +++ b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/PropertyUtils.kt @@ -8,7 +8,7 @@ import java.io.Serializable */ object PropertyUtils { - const val MAX_PROPERTY_SIZE: Int = 10 + const val MAX_PROPERTY_SIZE: Int = 50 fun sanitizeProperties(properties: Map?, bypassPropertyLimit: Boolean = false): Map { return if (properties == null) { diff --git a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/utils/PropertyUtilsTest.kt b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/utils/PropertyUtilsTest.kt index 7aaa593a8e..3eb0f84518 100644 --- a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/utils/PropertyUtilsTest.kt +++ b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/utils/PropertyUtilsTest.kt @@ -16,8 +16,8 @@ internal class PropertyUtilsTest { @Test fun testPropertyLimitExceeded() { - val input = (0..20).associateBy { "$it" } - val expected = (0..9).associateBy { "$it" } + val input = (0..70).associateBy { "$it" } + val expected = (0..49).associateBy { "$it" } assertEquals(expected, sanitizeProperties(input as Map?)) } @@ -44,7 +44,7 @@ internal class PropertyUtilsTest { sourceMap[""] = "Empty key" sourceMap["EmptyValue"] = "" sourceMap["NullValue"] = "" - for (i in 1..9) { + for (i in 1..99) { sourceMap["Key$i"] = "Value$i" } val resultMap = sanitizeProperties(sourceMap) diff --git a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt index c5555cb2bf..83fcbd013a 100644 --- a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt +++ b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt @@ -8,6 +8,8 @@ import io.embrace.android.embracesdk.assertions.getLogOfType import io.embrace.android.embracesdk.assertions.getOtelSeverity import io.embrace.android.embracesdk.fakes.config.FakeEnabledFeatureConfig import io.embrace.android.embracesdk.fakes.config.FakeInstrumentedConfig +import io.embrace.android.embracesdk.internal.capture.session.isSessionPropertyAttributeName +import io.embrace.android.embracesdk.internal.config.remote.RemoteConfig import io.embrace.android.embracesdk.internal.otel.schema.EmbType import io.embrace.android.embracesdk.internal.payload.Envelope import io.embrace.android.embracesdk.internal.payload.LogPayload @@ -421,6 +423,58 @@ internal class LogFeatureTest { ) } + @Test + fun `default maximum number of session and log properties are recorded in log`() { + val props = buildMap { + repeat(50) { + set("prop$it", "val") + } + } + testRule.runTest( + testCaseAction = { + recordSession { + repeat(20) { + embrace.addSessionProperty("session-prop$it", "val", true) + } + embrace.logMessage("test", Severity.INFO, props) + } + }, + assertAction = { + val log = getSingleLogEnvelope().getLogOfType(EmbType.System.Log) + assertEquals(50, log.attributes?.count { it.key?.startsWith("prop") == true }) + }, + otelExportAssertion = { + val logData = awaitLogs(1) { it.severity == io.opentelemetry.api.logs.Severity.INFO }.single() + val totalPropsCount = logData.attributes.asMap().filter { + it.key.key.startsWith("prop") || it.key.key.isSessionPropertyAttributeName() + }.size + + assertEquals(60, totalPropsCount) + } + ) + } + + @Test + fun `exported logs can contain maximum number of session properties`() { + val maxCustomSessionProps = 200 + testRule.runTest( + persistedRemoteConfig = RemoteConfig(maxSessionProperties = maxCustomSessionProps), + testCaseAction = { + recordSession { + repeat(maxCustomSessionProps + 1) { + embrace.addSessionProperty("session-prop$it", "val", true) + } + embrace.logMessage("test", Severity.INFO) + } + }, + otelExportAssertion = { + val logData = awaitLogs(1) { it.severity == io.opentelemetry.api.logs.Severity.INFO }.single() + val totalPropsCount = logData.attributes.asMap().filter { it.key.key.isSessionPropertyAttributeName() }.size + assertEquals(maxCustomSessionProps, totalPropsCount) + } + ) + } + private fun getEmbraceSeverity(severityNumber: Int): Severity { return when (severityNumber) { OtelJavaSeverity.INFO.severityNumber -> Severity.INFO From 073569f1f094f53c3a089ed264118199e8a0461f Mon Sep 17 00:00:00 2001 From: bidetofevil Date: Fri, 18 Jul 2025 15:41:07 -0700 Subject: [PATCH 2/3] WIP Rebase limts change on Kotlin API changes (need version bump) --- .../android/embracesdk/internal/otel/sdk/OtelSdkWrapper.kt | 3 +++ .../android/embracesdk/testcases/features/LogFeatureTest.kt | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/embrace-android-otel/src/main/kotlin/io/embrace/android/embracesdk/internal/otel/sdk/OtelSdkWrapper.kt b/embrace-android-otel/src/main/kotlin/io/embrace/android/embracesdk/internal/otel/sdk/OtelSdkWrapper.kt index 87f6849016..c8cf22200a 100644 --- a/embrace-android-otel/src/main/kotlin/io/embrace/android/embracesdk/internal/otel/sdk/OtelSdkWrapper.kt +++ b/embrace-android-otel/src/main/kotlin/io/embrace/android/embracesdk/internal/otel/sdk/OtelSdkWrapper.kt @@ -64,6 +64,9 @@ class OtelSdkWrapper( addLogRecordProcessor( DefaultLogRecordProcessor(configuration.logRecordExporter) ) + logLimits { + attributeCountLimit = limits.getMaxTotalAttributeCount() + } }, tracerProvider = { resource(configuration.resourceAction) diff --git a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt index 83fcbd013a..265f8c5170 100644 --- a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt +++ b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt @@ -18,12 +18,13 @@ import io.embrace.android.embracesdk.testframework.SdkIntegrationTestRule import io.embrace.opentelemetry.kotlin.ExperimentalApi import io.embrace.opentelemetry.kotlin.aliases.OtelJavaSeverity import io.embrace.opentelemetry.kotlin.logging.model.SeverityNumber -import java.util.LinkedList -import java.util.Queue +import junit.framework.Assert.assertEquals import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import java.util.LinkedList +import java.util.Queue @OptIn(ExperimentalApi::class) @RunWith(AndroidJUnit4::class) From 0be2f5f3e52a1e35ab9d1091373a764964b1b4b9 Mon Sep 17 00:00:00 2001 From: bidetofevil Date: Mon, 21 Jul 2025 22:41:19 -0700 Subject: [PATCH 3/3] Update all attribute/properties limits --- .../session/SessionPropertiesServiceImpl.kt | 15 ++--- .../config/behavior/SessionBehaviorImpl.kt | 6 +- .../internal/logs/EmbraceLogService.kt | 41 +++++++++++- .../internal/utils/PropertyUtils.kt | 29 ++------- .../behavior/SessionBehaviorImplImplTest.kt | 9 ++- .../internal/logs/EmbraceLogServiceTest.kt | 62 ++++++++++++++++++ .../internal/utils/PropertyUtilsTest.kt | 65 ++----------------- .../otel/spans/SpanServiceImplTest.kt | 2 +- .../instrumented/schema/OtelLimitsConfig.kt | 6 +- .../testcases/features/LogFeatureTest.kt | 8 +-- gradle/libs.versions.toml | 2 +- 11 files changed, 138 insertions(+), 107 deletions(-) diff --git a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/session/SessionPropertiesServiceImpl.kt b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/session/SessionPropertiesServiceImpl.kt index b967d4cd74..8ab662de5a 100644 --- a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/session/SessionPropertiesServiceImpl.kt +++ b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/session/SessionPropertiesServiceImpl.kt @@ -4,6 +4,7 @@ import io.embrace.android.embracesdk.internal.arch.destination.SessionSpanWriter import io.embrace.android.embracesdk.internal.config.ConfigService import io.embrace.android.embracesdk.internal.config.behavior.REDACTED_LABEL import io.embrace.android.embracesdk.internal.prefs.PreferencesService +import io.embrace.android.embracesdk.internal.utils.PropertyUtils internal class SessionPropertiesServiceImpl( preferencesService: PreferencesService, @@ -18,7 +19,7 @@ internal class SessionPropertiesServiceImpl( if (!isValidKey(originalKey)) { return false } - val sanitizedKey = enforceLength(originalKey, SESSION_PROPERTY_KEY_LIMIT) + val sanitizedKey = PropertyUtils.truncate(originalKey, SESSION_PROPERTY_KEY_LIMIT) if (!isValidValue(originalValue)) { return false @@ -27,7 +28,7 @@ internal class SessionPropertiesServiceImpl( val sanitizedValue = if (configService.sensitiveKeysBehavior.isSensitiveKey(sanitizedKey)) { REDACTED_LABEL } else { - enforceLength(originalValue, SESSION_PROPERTY_VALUE_LIMIT) + PropertyUtils.truncate(originalValue, SESSION_PROPERTY_VALUE_LIMIT) } val added = props.add(sanitizedKey, sanitizedValue, permanent) @@ -41,7 +42,7 @@ internal class SessionPropertiesServiceImpl( if (!isValidKey(originalKey)) { return false } - val sanitizedKey = enforceLength(originalKey, SESSION_PROPERTY_KEY_LIMIT) + val sanitizedKey = PropertyUtils.truncate(originalKey, SESSION_PROPERTY_KEY_LIMIT) val removed = props.remove(sanitizedKey) if (removed) { @@ -68,14 +69,6 @@ internal class SessionPropertiesServiceImpl( private fun isValidValue(key: String?): Boolean = key != null - private fun enforceLength(value: String, maxLength: Int): String { - if (value.length <= maxLength) { - return value - } - val endChars = "..." - return value.substring(0, maxLength - endChars.length) + endChars - } - private companion object { /** * The maximum number of characters of a session property key diff --git a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/SessionBehaviorImpl.kt b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/SessionBehaviorImpl.kt index b7c44824ea..3e5421f968 100644 --- a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/SessionBehaviorImpl.kt +++ b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/SessionBehaviorImpl.kt @@ -5,6 +5,7 @@ import io.embrace.android.embracesdk.internal.config.instrumented.schema.Session import io.embrace.android.embracesdk.internal.config.remote.RemoteConfig import io.embrace.android.embracesdk.internal.gating.SessionGatingKeys import java.util.Locale +import kotlin.math.min /** * Provides the behavior that functionality relating to sessions should follow. @@ -15,7 +16,8 @@ class SessionBehaviorImpl( ) : SessionBehavior { companion object { - const val SESSION_PROPERTY_LIMIT: Int = 10 + const val SESSION_PROPERTY_LIMIT: Int = 100 + const val SESSION_PROPERTY_MAX_LIMIT: Int = 200 } override val local: SessionConfig = local.session @@ -32,7 +34,7 @@ class SessionBehaviorImpl( override fun isSessionControlEnabled(): Boolean = remote?.sessionConfig?.isEnabled ?: false - override fun getMaxSessionProperties(): Int = remote?.maxSessionProperties ?: SESSION_PROPERTY_LIMIT + override fun getMaxSessionProperties(): Int = min(remote?.maxSessionProperties ?: SESSION_PROPERTY_LIMIT, SESSION_PROPERTY_MAX_LIMIT) override fun shouldGateInfoLog(): Boolean = shouldGateFeature(SessionGatingKeys.LOGS_INFO) diff --git a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/logs/EmbraceLogService.kt b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/logs/EmbraceLogService.kt index 0e2346b380..07c1fae4d2 100644 --- a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/logs/EmbraceLogService.kt +++ b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/logs/EmbraceLogService.kt @@ -1,5 +1,6 @@ package io.embrace.android.embracesdk.internal.logs +import android.os.Parcelable import io.embrace.android.embracesdk.LogExceptionType import io.embrace.android.embracesdk.Severity import io.embrace.android.embracesdk.internal.arch.destination.LogWriter @@ -16,9 +17,10 @@ import io.embrace.android.embracesdk.internal.otel.attrs.embExceptionHandling import io.embrace.android.embracesdk.internal.payload.AppFramework import io.embrace.android.embracesdk.internal.payload.Envelope import io.embrace.android.embracesdk.internal.session.orchestrator.PayloadStore -import io.embrace.android.embracesdk.internal.utils.PropertyUtils.sanitizeProperties +import io.embrace.android.embracesdk.internal.utils.PropertyUtils.truncate import io.embrace.android.embracesdk.internal.utils.Uuid import io.opentelemetry.semconv.incubating.LogIncubatingAttributes +import java.io.Serializable /** * Creates log records to be sent using the Open Telemetry Logs data model. @@ -161,11 +163,48 @@ class EmbraceLogService( } } + private fun sanitizeProperties( + properties: Map?, + bypassPropertyLimit: Boolean = false, + ): Map { + return if (properties == null) { + emptyMap() + } else { + runCatching { + if (bypassPropertyLimit) { + properties.entries.associate { + Pair(it.key, checkIfSerializable(it.value)) + } + } else { + properties.entries.take(MAX_PROPERTY_COUNT).associate { + Pair( + first = truncate(it.key, MAX_PROPERTY_KEY_LENGTH), + second = truncate(checkIfSerializable(it.value).toString(), MAX_PROPERTY_VALUE_LENGTH) + ) + } + } + }.getOrDefault(emptyMap()) + } + } + + private fun checkIfSerializable(value: Any): Any { + if (!(value is Parcelable || value is Serializable)) { + return "not serializable" + } + return value + } + private companion object { /** * The default limit of Unity log messages that can be sent. */ private const val LOG_MESSAGE_UNITY_MAXIMUM_ALLOWED_LENGTH = 16384 + + private const val MAX_PROPERTY_COUNT: Int = 100 + + private const val MAX_PROPERTY_KEY_LENGTH = 128 + + private const val MAX_PROPERTY_VALUE_LENGTH = 1024 } } diff --git a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/PropertyUtils.kt b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/PropertyUtils.kt index b388c7cc58..740c1ddf1a 100644 --- a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/PropertyUtils.kt +++ b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/utils/PropertyUtils.kt @@ -1,33 +1,14 @@ package io.embrace.android.embracesdk.internal.utils -import android.os.Parcelable -import java.io.Serializable - -/** - * Utility to for sanitizing user-supplied properties. - */ object PropertyUtils { - const val MAX_PROPERTY_SIZE: Int = 50 + private const val END_CHARS = "..." - fun sanitizeProperties(properties: Map?, bypassPropertyLimit: Boolean = false): Map { - return if (properties == null) { - emptyMap() - } else { - runCatching { - if (bypassPropertyLimit) { - properties.entries - } else { - properties.entries.take(MAX_PROPERTY_SIZE) - }.associate { Pair(it.key, checkIfSerializable(it.value)) } - }.getOrDefault(emptyMap()) + fun truncate(value: String, maxLength: Int): String { + if (value.length <= maxLength) { + return value } - } - private fun checkIfSerializable(value: Any): Any { - if (!(value is Parcelable || value is Serializable)) { - return "not serializable" - } - return value + return "${value.take(maxLength - 3)}$END_CHARS" } } diff --git a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/config/behavior/SessionBehaviorImplImplTest.kt b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/config/behavior/SessionBehaviorImplImplTest.kt index 05746fd16b..37e998ef95 100644 --- a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/config/behavior/SessionBehaviorImplImplTest.kt +++ b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/config/behavior/SessionBehaviorImplImplTest.kt @@ -27,7 +27,7 @@ internal class SessionBehaviorImplImplTest { assertNull(getSessionComponents()) assertFalse(isGatingFeatureEnabled()) assertFalse(isSessionControlEnabled()) - assertEquals(10, getMaxSessionProperties()) + assertEquals(100, getMaxSessionProperties()) } } @@ -58,6 +58,13 @@ internal class SessionBehaviorImplImplTest { assertEquals(setOf("crashes", "errors"), behavior.getFullSessionEvents()) } + @Test + fun `remote session properties limit is capped to 200`() { + with(createSessionBehavior(remoteCfg = RemoteConfig(maxSessionProperties = 1000))) { + assertEquals(200, getMaxSessionProperties()) + } + } + private fun buildGatingConfig(events: Set) = RemoteConfig( sessionConfig = SessionRemoteConfig( fullSessionEvents = events diff --git a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/logs/EmbraceLogServiceTest.kt b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/logs/EmbraceLogServiceTest.kt index acc7916a48..2406992482 100644 --- a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/logs/EmbraceLogServiceTest.kt +++ b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/logs/EmbraceLogServiceTest.kt @@ -259,4 +259,66 @@ internal class EmbraceLogServiceTest { val attachment = payloadStore.storedAttachments.single() assertEquals(bytes, attachment.data.second) } + + @Test + fun `log properties truncated properly`() { + logService.log( + message = "message", + severity = Severity.INFO, + logExceptionType = LogExceptionType.NONE, + properties = tooBigProperties + ) + + // then the message is not ellipsized + val logProps = fakeLogWriter.logEvents.single().schemaType.attributes().filter { it.key.startsWith("test") } + assertEquals(truncatedProps, logProps) + } + + @Test + fun `unserializable log values turned into error string`() { + logService.log( + message = "message", + severity = Severity.INFO, + logExceptionType = LogExceptionType.NONE, + properties = mapOf("badvalue" to UnSerializableClass()) + ) + assertEquals("not serializable", fakeLogWriter.logEvents.single().schemaType.attributes()["badvalue"]) + } + + @Test + fun `log properties unchanged if embrace not in use`() { + fakeConfigService = FakeConfigService(onlyUsingOtelExporters = true) + logService = createEmbraceLogService() + logService.log( + message = "message", + severity = Severity.INFO, + logExceptionType = LogExceptionType.NONE, + properties = tooBigProperties + ) + + // then the message is not ellipsized + val logProps = fakeLogWriter.logEvents.single().schemaType.attributes().filter { it.key.startsWith("test") } + assertEquals(tooBigProperties, logProps) + } + + private class UnSerializableClass + + companion object { + private val twoHundredXs = "x".repeat(200) + private val twoThousandXs = twoHundredXs.repeat(10) + + val tooBigProperties = mutableMapOf().apply { + repeat(150) { + this["test$it$twoHundredXs"] = twoThousandXs + } + } + + val truncatedProps = mutableMapOf().apply { + val expectedValue = twoThousandXs.take(1021) + "..." + repeat(100) { + val key = "test$it$twoHundredXs".take(125) + "..." + this[key] = expectedValue + } + } + } } diff --git a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/utils/PropertyUtilsTest.kt b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/utils/PropertyUtilsTest.kt index 3eb0f84518..00c10bb183 100644 --- a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/utils/PropertyUtilsTest.kt +++ b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/utils/PropertyUtilsTest.kt @@ -1,72 +1,19 @@ package io.embrace.android.embracesdk.internal.utils -import io.embrace.android.embracesdk.internal.utils.PropertyUtils.sanitizeProperties import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull -import org.junit.Assert.assertTrue import org.junit.Test internal class PropertyUtilsTest { @Test - fun testEmptyCase() { - assertEquals(emptyMap(), sanitizeProperties(null)) - assertEquals(emptyMap(), sanitizeProperties(emptyMap())) + fun `no truncation`() { + val value = "a".repeat(100) + assertEquals(value, PropertyUtils.truncate(value, 100)) } @Test - fun testPropertyLimitExceeded() { - val input = (0..70).associateBy { "$it" } - val expected = (0..49).associateBy { "$it" } - assertEquals(expected, sanitizeProperties(input as Map?)) + fun `basic truncation`() { + val value = "a".repeat(110) + assertEquals(value.take(97) + "...", PropertyUtils.truncate(value, 100)) } - - @Test - fun testSerializableValue() { - val obj = SerializableClass() - assertEquals(obj, sanitizeProperties(mapOf("a" to obj))["a"]) - } - - @Test - fun testUnserializableValue() { - assertEquals("not serializable", sanitizeProperties(mapOf("a" to UnSerializableClass()))["a"]) - } - - @Test - fun `bypass limits`() { - val input = (0..20).associateBy { "$it" } - assertEquals(input.size, sanitizeProperties(input, true).size) - } - - @Test - fun testPropertiesNormalization() { - val sourceMap: MutableMap = HashMap() - sourceMap[""] = "Empty key" - sourceMap["EmptyValue"] = "" - sourceMap["NullValue"] = "" - for (i in 1..99) { - sourceMap["Key$i"] = "Value$i" - } - val resultMap = sanitizeProperties(sourceMap) - assertTrue( - "Unexpected normalized map size.", - resultMap.size <= PropertyUtils.MAX_PROPERTY_SIZE - ) - resultMap.entries.stream() - .peek { (key): Map.Entry -> - assertNotNull( - "Unexpected normalized map key: NULL.", - key - ) - } - .peek { (_, value): Map.Entry -> - assertNotNull( - "Unexpected normalized map value: NULL.", - value - ) - } - } - - private class SerializableClass : java.io.Serializable - private class UnSerializableClass } diff --git a/embrace-android-otel/src/test/kotlin/io/embrace/android/embracesdk/internal/otel/spans/SpanServiceImplTest.kt b/embrace-android-otel/src/test/kotlin/io/embrace/android/embracesdk/internal/otel/spans/SpanServiceImplTest.kt index 81505f6395..a0a158a978 100644 --- a/embrace-android-otel/src/test/kotlin/io/embrace/android/embracesdk/internal/otel/spans/SpanServiceImplTest.kt +++ b/embrace-android-otel/src/test/kotlin/io/embrace/android/embracesdk/internal/otel/spans/SpanServiceImplTest.kt @@ -535,7 +535,7 @@ internal class SpanServiceImplTest { val completedSpans = spanSink.completedSpans() assertEquals(1, completedSpans.size) val attrs = completedSpans[0].attributes.filterNot { it.key.startsWith("emb.") } - assertEquals(49, attrs.size) + assertEquals(99, attrs.size) } @Test diff --git a/embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/instrumented/schema/OtelLimitsConfig.kt b/embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/instrumented/schema/OtelLimitsConfig.kt index 641a506bff..7b48cb3f6c 100644 --- a/embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/instrumented/schema/OtelLimitsConfig.kt +++ b/embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/instrumented/schema/OtelLimitsConfig.kt @@ -11,13 +11,13 @@ interface OtelLimitsConfig { fun getMaxNameLength(): Int = 50 fun getMaxCustomEventCount(): Int = 10 fun getMaxSystemEventCount(): Int = 11000 - fun getMaxCustomAttributeCount(): Int = 50 + fun getMaxCustomAttributeCount(): Int = 100 fun getMaxSystemAttributeCount(): Int = 300 fun getMaxCustomLinkCount(): Int = 10 fun getMaxSystemLinkCount(): Int = 100 fun getMaxInternalAttributeKeyLength(): Int = 1000 fun getMaxInternalAttributeValueLength(): Int = 2000 - fun getMaxCustomAttributeKeyLength(): Int = 50 - fun getMaxCustomAttributeValueLength(): Int = 500 + fun getMaxCustomAttributeKeyLength(): Int = 128 + fun getMaxCustomAttributeValueLength(): Int = 1024 fun getExceptionEventName(): String = "exception" } diff --git a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt index 265f8c5170..a35889032f 100644 --- a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt +++ b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/LogFeatureTest.kt @@ -427,14 +427,14 @@ internal class LogFeatureTest { @Test fun `default maximum number of session and log properties are recorded in log`() { val props = buildMap { - repeat(50) { + repeat(150) { set("prop$it", "val") } } testRule.runTest( testCaseAction = { recordSession { - repeat(20) { + repeat(150) { embrace.addSessionProperty("session-prop$it", "val", true) } embrace.logMessage("test", Severity.INFO, props) @@ -442,7 +442,7 @@ internal class LogFeatureTest { }, assertAction = { val log = getSingleLogEnvelope().getLogOfType(EmbType.System.Log) - assertEquals(50, log.attributes?.count { it.key?.startsWith("prop") == true }) + assertEquals(100, log.attributes?.count { it.key?.startsWith("prop") == true }) }, otelExportAssertion = { val logData = awaitLogs(1) { it.severity == io.opentelemetry.api.logs.Severity.INFO }.single() @@ -450,7 +450,7 @@ internal class LogFeatureTest { it.key.key.startsWith("prop") || it.key.key.isSessionPropertyAttributeName() }.size - assertEquals(60, totalPropsCount) + assertEquals(200, totalPropsCount) } ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 69c79a05b8..ec3a2e3e56 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ openTelemetryCore = "1.51.0" openTelementrySemConv = "1.29.0-alpha" moshi = "1.15.2" lifecycle = "2.7.0" # version pinned to 2.7.0 because of AGP bug -otelKotlin = "0.2.2" +otelKotlin = "0.2.3" protobuf = "4.31.1" profileinstaller = "1.3.1" # version pinned to 1.3.1 because of AGP bug okhttp = "4.12.0"