diff --git a/CHANGELOG.md b/CHANGELOG.md index 295f7d4650..e8cc368213 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,10 @@ - Report the cellular network technology generation in `device.connection_effective_type`, for example `4g` or `5g` ([#6146](https://github.com/getsentry/sentry-java/pull/6146)) +### Fixes + +- Avoid duplicate serialization debug logs when calculating serialized object sizes ([#6255](https://github.com/getsentry/sentry-java/pull/6255)) + ### Dependencies - Bump Native SDK from v0.17.1 to v0.17.2 ([#6230](https://github.com/getsentry/sentry-java/pull/6230)) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 2007edf00c..d3c6dc9447 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -1233,6 +1233,7 @@ public abstract interface class io/sentry/ISerializer { public abstract fun deserializeEnvelope (Ljava/io/InputStream;)Lio/sentry/SentryEnvelope; public abstract fun serialize (Lio/sentry/SentryEnvelope;Ljava/io/OutputStream;)V public abstract fun serialize (Ljava/lang/Object;Ljava/io/Writer;)V + public fun serialize (Ljava/lang/Object;Ljava/io/Writer;Z)V public abstract fun serialize (Ljava/util/Map;)Ljava/lang/String; } @@ -1450,6 +1451,7 @@ public final class io/sentry/JsonSerializer : io/sentry/ISerializer { public fun deserializeEnvelope (Ljava/io/InputStream;)Lio/sentry/SentryEnvelope; public fun serialize (Lio/sentry/SentryEnvelope;Ljava/io/OutputStream;)V public fun serialize (Ljava/lang/Object;Ljava/io/Writer;)V + public fun serialize (Ljava/lang/Object;Ljava/io/Writer;Z)V public fun serialize (Ljava/util/Map;)Ljava/lang/String; } diff --git a/sentry/src/main/java/io/sentry/ISerializer.java b/sentry/src/main/java/io/sentry/ISerializer.java index f74c9ab022..0f7c193ab0 100644 --- a/sentry/src/main/java/io/sentry/ISerializer.java +++ b/sentry/src/main/java/io/sentry/ISerializer.java @@ -23,6 +23,20 @@ public interface ISerializer { void serialize(@NotNull T entity, @NotNull Writer writer) throws IOException; + /** + * Serializes an entity to a writer with optional logging control. + * + * @param entity the entity to serialize + * @param writer the writer to serialize to + * @param enableLogging whether serializer logging is enabled, if supported + * @param the type of entity + * @throws IOException if serialization fails + */ + default void serialize(@NotNull T entity, @NotNull Writer writer, boolean enableLogging) + throws IOException { + serialize(entity, writer); + } + /** * Serializes an envelope * diff --git a/sentry/src/main/java/io/sentry/JsonSerializer.java b/sentry/src/main/java/io/sentry/JsonSerializer.java index 79a1c72bef..d7b7423e52 100644 --- a/sentry/src/main/java/io/sentry/JsonSerializer.java +++ b/sentry/src/main/java/io/sentry/JsonSerializer.java @@ -208,10 +208,16 @@ public JsonSerializer(@NotNull SentryOptions options) { @Override public void serialize(@NotNull T entity, @NotNull Writer writer) throws IOException { + serialize(entity, writer, true); + } + + @Override + public void serialize(@NotNull T entity, @NotNull Writer writer, boolean enableLogging) + throws IOException { Objects.requireNonNull(entity, "The entity is required."); Objects.requireNonNull(writer, "The Writer object is required."); - if (options.getLogger().isEnabled(SentryLevel.DEBUG)) { + if (enableLogging && options.getLogger().isEnabled(SentryLevel.DEBUG)) { String serialized = serializeToString(entity, options.isEnablePrettySerializationOutput()); options.getLogger().log(SentryLevel.DEBUG, "Serializing object: %s", serialized); } diff --git a/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java b/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java index fc9bc75aa3..ab0f5c9c32 100644 --- a/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java +++ b/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java @@ -85,7 +85,7 @@ public static long byteSizeOf( } try { final ByteCountingWriter writer = new ByteCountingWriter(); - serializer.serialize(serializable, writer); + serializer.serialize(serializable, writer, false); return writer.getByteCount(); } catch (Throwable t) { logger.log(SentryLevel.ERROR, "Could not calculate size of serializable", t); diff --git a/sentry/src/test/java/io/sentry/JsonSerializerTest.kt b/sentry/src/test/java/io/sentry/JsonSerializerTest.kt index 95b664e13a..3e234c0a7c 100644 --- a/sentry/src/test/java/io/sentry/JsonSerializerTest.kt +++ b/sentry/src/test/java/io/sentry/JsonSerializerTest.kt @@ -1550,6 +1550,20 @@ class JsonSerializerTest { .log(any(), check { assertTrue(it.startsWith("Serializing object:")) }, any()) } + @Test + fun `json serializer can disable serialization logging`() { + val logger = mock() + val options = SentryOptions() + options.setLogger(logger) + options.setDebug(true) + whenever(logger.isEnabled(any())).thenReturn(true) + + (options.serializer as JsonSerializer).serialize(mapOf("key" to "val"), StringWriter(), false) + + verify(logger, never()) + .log(any(), check { assertTrue(it.startsWith("Serializing object:")) }, any()) + } + @Test fun `json serializer does not close the stream that is passed in`() { val stream = mock() diff --git a/sentry/src/test/java/io/sentry/util/JsonSerializationUtilsTest.kt b/sentry/src/test/java/io/sentry/util/JsonSerializationUtilsTest.kt index caa93f1af7..170ad4646f 100644 --- a/sentry/src/test/java/io/sentry/util/JsonSerializationUtilsTest.kt +++ b/sentry/src/test/java/io/sentry/util/JsonSerializationUtilsTest.kt @@ -1,6 +1,7 @@ package io.sentry.util import io.sentry.ILogger +import io.sentry.ISerializer import io.sentry.JsonSerializable import io.sentry.JsonSerializer import io.sentry.ObjectWriter @@ -18,7 +19,9 @@ import kotlin.test.assertNull import kotlin.test.assertTrue import org.mockito.invocation.InvocationOnMock import org.mockito.kotlin.any +import org.mockito.kotlin.eq import org.mockito.kotlin.mock +import org.mockito.kotlin.verify class JsonSerializationUtilsTest { @@ -117,6 +120,16 @@ class JsonSerializationUtilsTest { assertTrue(byteSize > 0, "byteSize should be positive") } + @Test + fun `byteSizeOf disables serialization logging`() { + val mockSerializer: ISerializer = mock() + val serializable: JsonSerializable = mock() + + JsonSerializationUtils.byteSizeOf(mockSerializer, logger, serializable) + + verify(mockSerializer).serialize(eq(serializable), any(), eq(false)) + } + @Test fun `byteSizeOf returns 0 on serialization error`() { val serializable =