Skip to content

Commit

Permalink
No longer serialize static fields; use toString as fallback (#2309)
Browse files Browse the repository at this point in the history
  • Loading branch information
adinauer committed Oct 20, 2022
1 parent ba49577 commit 649f171
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Ensure potential callback exceptions are caught #2123 ([#2291](https://github.com/getsentry/sentry-java/pull/2291))
- Remove verbose FrameMetricsAggregator failure logging ([#2293](https://github.com/getsentry/sentry-java/pull/2293))
- Ignore broken regex for tracePropagationTarget ([#2288](https://github.com/getsentry/sentry-java/pull/2288))
- No longer serialize static fields; use toString as fallback ([#2309](https://github.com/getsentry/sentry-java/pull/2309))
- Fix `SentryFileWriter`/`SentryFileOutputStream` append overwrites file contents ([#2304](https://github.com/getsentry/sentry-java/pull/2304))
- Respect incoming parent sampled decision when continuing a trace ([#2311](https://github.com/getsentry/sentry-java/pull/2311))

Expand Down
6 changes: 6 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -3304,6 +3304,12 @@ public final class io/sentry/util/HttpUtils {
public static fun containsSensitiveHeader (Ljava/lang/String;)Z
}

public final class io/sentry/util/JsonSerializationUtils {
public fun <init> ()V
public static fun atomicIntegerArrayToList (Ljava/util/concurrent/atomic/AtomicIntegerArray;)Ljava/util/List;
public static fun calendarToMap (Ljava/util/Calendar;)Ljava/util/Map;
}

public final class io/sentry/util/LogUtils {
public fun <init> ()V
public static fun logNotInstanceOf (Ljava/lang/Class;Ljava/lang/Object;Lio/sentry/ILogger;)V
Expand Down
27 changes: 27 additions & 0 deletions sentry/src/main/java/io/sentry/JsonObjectSerializer.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
package io.sentry;

import static io.sentry.util.JsonSerializationUtils.atomicIntegerArrayToList;
import static io.sentry.util.JsonSerializationUtils.calendarToMap;

import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Currency;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicIntegerArray;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -46,6 +57,22 @@ public void serialize(
serializeCollection(writer, logger, Arrays.asList((Object[]) object));
} else if (object instanceof Map) {
serializeMap(writer, logger, (Map<?, ?>) object);
} else if (object instanceof Locale) {
writer.value(object.toString());
} else if (object instanceof AtomicIntegerArray) {
serializeCollection(writer, logger, atomicIntegerArrayToList((AtomicIntegerArray) object));
} else if (object instanceof AtomicBoolean) {
writer.value(((AtomicBoolean) object).get());
} else if (object instanceof URI) {
writer.value(object.toString());
} else if (object instanceof InetAddress) {
writer.value(object.toString());
} else if (object instanceof UUID) {
writer.value(object.toString());
} else if (object instanceof Currency) {
writer.value(object.toString());
} else if (object instanceof Calendar) {
serializeMap(writer, logger, calendarToMap((Calendar) object));
} else if (object.getClass().isEnum()) {
writer.value(object.toString());
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
package io.sentry;

import static io.sentry.util.JsonSerializationUtils.atomicIntegerArrayToList;
import static io.sentry.util.JsonSerializationUtils.calendarToMap;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.InetAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Currency;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicIntegerArray;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -39,6 +50,22 @@ public final class JsonReflectionObjectSerializer {
return object;
} else if (object instanceof String) {
return object;
} else if (object instanceof Locale) {
return object.toString();
} else if (object instanceof AtomicIntegerArray) {
return atomicIntegerArrayToList((AtomicIntegerArray) object);
} else if (object instanceof AtomicBoolean) {
return ((AtomicBoolean) object).get();
} else if (object instanceof URI) {
return object.toString();
} else if (object instanceof InetAddress) {
return object.toString();
} else if (object instanceof UUID) {
return object.toString();
} else if (object instanceof Currency) {
return object.toString();
} else if (object instanceof Calendar) {
return calendarToMap((Calendar) object);
} else if (object.getClass().isEnum()) {
return object.toString();
} else {
Expand All @@ -63,7 +90,12 @@ public final class JsonReflectionObjectSerializer {
} else if (object instanceof Map) {
serializedObject = map((Map<?, ?>) object, logger);
} else {
serializedObject = serializeObject(object, logger);
@NotNull Map<String, Object> objectAsMap = serializeObject(object, logger);
if (objectAsMap.isEmpty()) {
serializedObject = object.toString();
} else {
serializedObject = objectAsMap;
}
}
} catch (Exception exception) {
logger.log(SentryLevel.INFO, "Not serializing object due to throwing sub-path.", exception);
Expand All @@ -84,6 +116,9 @@ public final class JsonReflectionObjectSerializer {
if (Modifier.isTransient(field.getModifiers())) {
continue;
}
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
String fieldName = field.getName();
try {
field.setAccessible(true);
Expand All @@ -94,6 +129,7 @@ public final class JsonReflectionObjectSerializer {
logger.log(SentryLevel.INFO, "Cannot access field " + fieldName + ".");
}
}

return map;
}

Expand Down
37 changes: 37 additions & 0 deletions sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.sentry.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicIntegerArray;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

@ApiStatus.Internal
public final class JsonSerializationUtils {

public static @NotNull Map<String, Object> calendarToMap(final @NotNull Calendar calendar) {
final @NotNull Map<String, Object> map = new HashMap<>();

map.put("year", calendar.get(Calendar.YEAR));
map.put("month", calendar.get(Calendar.MONTH));
map.put("dayOfMonth", calendar.get(Calendar.DAY_OF_MONTH));
map.put("hourOfDay", calendar.get(Calendar.HOUR_OF_DAY));
map.put("minute", calendar.get(Calendar.MINUTE));
map.put("second", calendar.get(Calendar.SECOND));

return map;
}

public static @NotNull List<Object> atomicIntegerArrayToList(
final @NotNull AtomicIntegerArray array) {
final int numberOfItems = array.length();
final @NotNull List<Object> list = new ArrayList<>(numberOfItems);
for (int i = 0; i < numberOfItems; i++) {
list.add(array.get(i));
}
return list;
}
}
112 changes: 109 additions & 3 deletions sentry/src/test/java/io/sentry/JsonObjectSerializerTest.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
package io.sentry

import com.nhaarman.mockitokotlin2.inOrder
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.times
import com.nhaarman.mockitokotlin2.verify
import org.junit.Test
import java.net.URI
import java.util.Calendar
import java.util.Currency
import java.util.Locale
import java.util.TimeZone
import java.util.UUID
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicIntegerArray

internal class JsonObjectSerializerTest {

Expand Down Expand Up @@ -114,9 +123,9 @@ internal class JsonObjectSerializerTest {

@Test
fun `serialize unknown object without data`() {
fixture.getSUT().serialize(fixture.writer, fixture.logger, object {})
verify(fixture.writer).beginObject()
verify(fixture.writer).endObject()
val value = object {}
fixture.getSUT().serialize(fixture.writer, fixture.logger, value)
verify(fixture.writer).value(value.toString())
}

@Test
Expand Down Expand Up @@ -166,10 +175,107 @@ internal class JsonObjectSerializerTest {
verify(fixture.writer).endObject()
}

@Test
fun `serialize locale`() {
val inOrder = inOrder(fixture.writer)
fixture.getSUT().serialize(fixture.writer, fixture.logger, Locale.US)

inOrder.verify(fixture.writer).value("en_US")
}

@Test
fun `serialize locale in map`() {
val map = mapOf<String, Locale>("one" to Locale.US)
val inOrder = inOrder(fixture.writer)
fixture.getSUT().serialize(fixture.writer, fixture.logger, map)
inOrder.verify(fixture.writer).beginObject()
inOrder.verify(fixture.writer).name("one")
inOrder.verify(fixture.writer).value("en_US")
inOrder.verify(fixture.writer).endObject()
}

@Test
fun `serialize locale in list`() {
val list = listOf<Locale>(Locale.US, Locale.GERMAN)
val inOrder = inOrder(fixture.writer)
fixture.getSUT().serialize(fixture.writer, fixture.logger, list)
inOrder.verify(fixture.writer).beginArray()
inOrder.verify(fixture.writer).value("en_US")
inOrder.verify(fixture.writer).value("de")
inOrder.verify(fixture.writer).endArray()
}

@Test
fun `serialize locale in object`() {
val obj = ClassWithLocaleProperty(Locale.US)
val inOrder = inOrder(fixture.writer)
fixture.getSUT().serialize(fixture.writer, fixture.logger, obj)
inOrder.verify(fixture.writer).beginObject()
inOrder.verify(fixture.writer).name("localeProperty")
inOrder.verify(fixture.writer).value("en_US")
inOrder.verify(fixture.writer).endObject()
}

@Test
fun `serializing AtomicIntegerArray`() {
fixture.getSUT().serialize(fixture.writer, fixture.logger, AtomicIntegerArray(arrayOf(1, 2, 3).toIntArray()))
verify(fixture.writer).beginArray()
verify(fixture.writer).value(1 as Number)
verify(fixture.writer).value(2 as Number)
verify(fixture.writer).value(3 as Number)
verify(fixture.writer).endArray()
}

@Test
fun `serializing AtomicBoolean`() {
fixture.getSUT().serialize(fixture.writer, fixture.logger, AtomicBoolean(true))
verify(fixture.writer).value(true)
}

@Test
fun `serializing URI`() {
fixture.getSUT().serialize(fixture.writer, fixture.logger, URI("http://localhost:8081/api/product?id=99"))
verify(fixture.writer).value("http://localhost:8081/api/product?id=99")
}

@Test
fun `serializing UUID`() {
fixture.getSUT().serialize(fixture.writer, fixture.logger, UUID.fromString("828900a5-15dc-413f-8c17-6ef04d74e074"))
verify(fixture.writer).value("828900a5-15dc-413f-8c17-6ef04d74e074")
}

@Test
fun `serializing Currency`() {
fixture.getSUT().serialize(fixture.writer, fixture.logger, Currency.getInstance("USD"))
verify(fixture.writer).value("USD")
}

@Test
fun `serializing Calendar`() {
val calendar = Calendar.getInstance()
calendar.set(2022, 0, 1, 11, 59, 58)
fixture.getSUT().serialize(fixture.writer, fixture.logger, calendar)
verify(fixture.writer).beginObject()
verify(fixture.writer).name("year")
verify(fixture.writer).value(2022 as java.lang.Integer)
verify(fixture.writer).name("month")
verify(fixture.writer).value(0 as java.lang.Integer)
verify(fixture.writer).name("dayOfMonth")
verify(fixture.writer).value(1 as java.lang.Integer)
verify(fixture.writer).name("hourOfDay")
verify(fixture.writer).value(11 as java.lang.Integer)
verify(fixture.writer).name("minute")
verify(fixture.writer).value(59 as java.lang.Integer)
verify(fixture.writer).name("second")
verify(fixture.writer).value(58 as java.lang.Integer)
verify(fixture.writer).endObject()
}

class UnknownClassWithData(
private val integer: Int,
private val string: String
)
}

data class ClassWithEnumProperty(val enumProperty: DataCategory)
data class ClassWithLocaleProperty(val localeProperty: Locale)

0 comments on commit 649f171

Please sign in to comment.