Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features

- Support collections and arrays in log attribute type inference ([#5124](https://github.com/getsentry/sentry-java/pull/5124))
- Add scope-level attributes API ([#5118](https://github.com/getsentry/sentry-java/pull/5118))
- Automatically include scope attributes in logs and metrics ([#5120](https://github.com/getsentry/sentry-java/pull/5120))

Expand Down
2 changes: 2 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -2813,6 +2813,7 @@ public final class io/sentry/SentryAppStartProfilingOptions$JsonKeys {
}

public final class io/sentry/SentryAttribute {
public static fun arrayAttribute (Ljava/lang/String;Ljava/util/Collection;)Lio/sentry/SentryAttribute;
public static fun booleanAttribute (Ljava/lang/String;Ljava/lang/Boolean;)Lio/sentry/SentryAttribute;
public static fun doubleAttribute (Ljava/lang/String;Ljava/lang/Double;)Lio/sentry/SentryAttribute;
public fun getName ()Ljava/lang/String;
Expand All @@ -2824,6 +2825,7 @@ public final class io/sentry/SentryAttribute {
}

public final class io/sentry/SentryAttributeType : java/lang/Enum {
public static final field ARRAY Lio/sentry/SentryAttributeType;
public static final field BOOLEAN Lio/sentry/SentryAttributeType;
public static final field DOUBLE Lio/sentry/SentryAttributeType;
public static final field INTEGER Lio/sentry/SentryAttributeType;
Expand Down
6 changes: 6 additions & 0 deletions sentry/src/main/java/io/sentry/SentryAttribute.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.sentry;

import java.util.Collection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -54,4 +55,9 @@ private SentryAttribute(
final @NotNull String name, final @Nullable String value) {
return new SentryAttribute(name, SentryAttributeType.STRING, value);
}

public static @NotNull SentryAttribute arrayAttribute(
final @NotNull String name, final @Nullable Collection<?> value) {
return new SentryAttribute(name, SentryAttributeType.ARRAY, value);
}
}
7 changes: 6 additions & 1 deletion sentry/src/main/java/io/sentry/SentryAttributeType.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.sentry;

import java.math.BigInteger;
import java.util.Collection;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
Expand All @@ -11,7 +12,8 @@ public enum SentryAttributeType {
STRING,
BOOLEAN,
INTEGER,
DOUBLE;
DOUBLE,
ARRAY;

public @NotNull String apiName() {
return name().toLowerCase(Locale.ROOT);
Expand All @@ -33,6 +35,9 @@ public enum SentryAttributeType {
if (value instanceof Number) {
return DOUBLE;
}
if (value instanceof Collection || (value != null && value.getClass().isArray())) {
return ARRAY;
}
return STRING;
}
}
40 changes: 40 additions & 0 deletions sentry/src/test/java/io/sentry/ScopesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2726,10 +2726,12 @@ class ScopesTest {
SentryAttribute.booleanAttribute("boolattr", true),
SentryAttribute.integerAttribute("intattr", 17),
SentryAttribute.doubleAttribute("doubleattr", 3.8),
SentryAttribute.arrayAttribute("arrayattr", listOf("a", "b")),
SentryAttribute.named("namedstrattr", "namedstrval"),
SentryAttribute.named("namedboolattr", false),
SentryAttribute.named("namedintattr", 18),
SentryAttribute.named("nameddoubleattr", 4.9),
SentryAttribute.named("namedarrayattr", listOf("x", "y")),
)
),
"log message",
Expand Down Expand Up @@ -2758,6 +2760,10 @@ class ScopesTest {
assertEquals(3.8, doubleattr.value)
assertEquals("double", doubleattr.type)

val arrayattr = it.attributes?.get("arrayattr")!!
assertEquals(listOf("a", "b"), arrayattr.value)
assertEquals("array", arrayattr.type)

val namedstrattr = it.attributes?.get("namedstrattr")!!
assertEquals("namedstrval", namedstrattr.value)
assertEquals("string", namedstrattr.type)
Expand All @@ -2773,6 +2779,10 @@ class ScopesTest {
val nameddoubleattr = it.attributes?.get("nameddoubleattr")!!
assertEquals(4.9, nameddoubleattr.value)
assertEquals("double", nameddoubleattr.type)

val namedarrayattr = it.attributes?.get("namedarrayattr")!!
assertEquals(listOf("x", "y"), namedarrayattr.value)
assertEquals("array", namedarrayattr.type)
},
anyOrNull(),
)
Expand Down Expand Up @@ -3460,10 +3470,12 @@ class ScopesTest {
SentryAttribute.booleanAttribute("boolattr", true),
SentryAttribute.integerAttribute("intattr", 17),
SentryAttribute.doubleAttribute("doubleattr", 3.8),
SentryAttribute.arrayAttribute("arrayattr", listOf("a", "b")),
SentryAttribute.named("namedstrattr", "namedstrval"),
SentryAttribute.named("namedboolattr", false),
SentryAttribute.named("namedintattr", 18),
SentryAttribute.named("nameddoubleattr", 4.9),
SentryAttribute.named("namedarrayattr", listOf("x", "y")),
)
),
)
Expand Down Expand Up @@ -3492,6 +3504,10 @@ class ScopesTest {
assertEquals(3.8, doubleattr.value)
assertEquals("double", doubleattr.type)

val arrayattr = it.attributes?.get("arrayattr")!!
assertEquals(listOf("a", "b"), arrayattr.value)
assertEquals("array", arrayattr.type)

val namedstrattr = it.attributes?.get("namedstrattr")!!
assertEquals("namedstrval", namedstrattr.value)
assertEquals("string", namedstrattr.type)
Expand All @@ -3507,6 +3523,10 @@ class ScopesTest {
val nameddoubleattr = it.attributes?.get("nameddoubleattr")!!
assertEquals(4.9, nameddoubleattr.value)
assertEquals("double", nameddoubleattr.type)

val namedarrayattr = it.attributes?.get("namedarrayattr")!!
assertEquals(listOf("x", "y"), namedarrayattr.value)
assertEquals("array", namedarrayattr.type)
},
anyOrNull(),
anyOrNull(),
Expand Down Expand Up @@ -3629,10 +3649,12 @@ class ScopesTest {
SentryAttribute.booleanAttribute("boolattr", true),
SentryAttribute.integerAttribute("intattr", 17),
SentryAttribute.doubleAttribute("doubleattr", 3.8),
SentryAttribute.arrayAttribute("arrayattr", listOf("a", "b")),
SentryAttribute.named("namedstrattr", "namedstrval"),
SentryAttribute.named("namedboolattr", false),
SentryAttribute.named("namedintattr", 18),
SentryAttribute.named("nameddoubleattr", 4.9),
SentryAttribute.named("namedarrayattr", listOf("x", "y")),
)
),
)
Expand Down Expand Up @@ -3661,6 +3683,10 @@ class ScopesTest {
assertEquals(3.8, doubleattr.value)
assertEquals("double", doubleattr.type)

val arrayattr = it.attributes?.get("arrayattr")!!
assertEquals(listOf("a", "b"), arrayattr.value)
assertEquals("array", arrayattr.type)

val namedstrattr = it.attributes?.get("namedstrattr")!!
assertEquals("namedstrval", namedstrattr.value)
assertEquals("string", namedstrattr.type)
Expand All @@ -3676,6 +3702,10 @@ class ScopesTest {
val nameddoubleattr = it.attributes?.get("nameddoubleattr")!!
assertEquals(4.9, nameddoubleattr.value)
assertEquals("double", nameddoubleattr.type)

val namedarrayattr = it.attributes?.get("namedarrayattr")!!
assertEquals(listOf("x", "y"), namedarrayattr.value)
assertEquals("array", namedarrayattr.type)
},
anyOrNull(),
anyOrNull(),
Expand Down Expand Up @@ -3798,10 +3828,12 @@ class ScopesTest {
SentryAttribute.booleanAttribute("boolattr", true),
SentryAttribute.integerAttribute("intattr", 17),
SentryAttribute.doubleAttribute("doubleattr", 3.8),
SentryAttribute.arrayAttribute("arrayattr", listOf("a", "b")),
SentryAttribute.named("namedstrattr", "namedstrval"),
SentryAttribute.named("namedboolattr", false),
SentryAttribute.named("namedintattr", 18),
SentryAttribute.named("nameddoubleattr", 4.9),
SentryAttribute.named("namedarrayattr", listOf("x", "y")),
)
),
)
Expand Down Expand Up @@ -3830,6 +3862,10 @@ class ScopesTest {
assertEquals(3.8, doubleattr.value)
assertEquals("double", doubleattr.type)

val arrayattr = it.attributes?.get("arrayattr")!!
assertEquals(listOf("a", "b"), arrayattr.value)
assertEquals("array", arrayattr.type)

val namedstrattr = it.attributes?.get("namedstrattr")!!
assertEquals("namedstrval", namedstrattr.value)
assertEquals("string", namedstrattr.type)
Expand All @@ -3845,6 +3881,10 @@ class ScopesTest {
val nameddoubleattr = it.attributes?.get("nameddoubleattr")!!
assertEquals(4.9, nameddoubleattr.value)
assertEquals("double", nameddoubleattr.type)

val namedarrayattr = it.attributes?.get("namedarrayattr")!!
assertEquals(listOf("x", "y"), namedarrayattr.value)
assertEquals("array", namedarrayattr.type)
},
anyOrNull(),
anyOrNull(),
Expand Down
35 changes: 35 additions & 0 deletions sentry/src/test/java/io/sentry/SentryAttributeTypeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,39 @@ class SentryAttributeTypeTest {
fun `inferFrom returns STRING for null`() {
assertEquals(SentryAttributeType.STRING, SentryAttributeType.inferFrom(null))
}

@Test
fun `inferFrom returns ARRAY for List of Strings`() {
assertEquals(SentryAttributeType.ARRAY, SentryAttributeType.inferFrom(listOf("a", "b")))
}

@Test
fun `inferFrom returns ARRAY for List of Integers`() {
assertEquals(SentryAttributeType.ARRAY, SentryAttributeType.inferFrom(listOf(1, 2, 3)))
}

@Test
fun `inferFrom returns ARRAY for Set of Booleans`() {
assertEquals(SentryAttributeType.ARRAY, SentryAttributeType.inferFrom(setOf(true, false)))
}

@Test
fun `inferFrom returns ARRAY for String array`() {
assertEquals(SentryAttributeType.ARRAY, SentryAttributeType.inferFrom(arrayOf("a", "b")))
}

@Test
fun `inferFrom returns ARRAY for int array`() {
assertEquals(SentryAttributeType.ARRAY, SentryAttributeType.inferFrom(intArrayOf(1, 2)))
}

@Test
fun `inferFrom returns ARRAY for empty list`() {
assertEquals(SentryAttributeType.ARRAY, SentryAttributeType.inferFrom(emptyList<String>()))
}

@Test
fun `inferFrom returns ARRAY for mixed-type list`() {
assertEquals(SentryAttributeType.ARRAY, SentryAttributeType.inferFrom(listOf("a", 1, true)))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SentryLogsSerializationTest {
"sentry.sdk.name" to
SentryLogEventAttributeValue("string", "sentry.java.spring-boot.jakarta"),
"sentry.environment" to SentryLogEventAttributeValue("string", "production"),
"custom.array" to SentryLogEventAttributeValue("array", listOf("a", "b")),
"sentry.sdk.version" to SentryLogEventAttributeValue("string", "8.11.1"),
"sentry.trace.parent_span_id" to
SentryLogEventAttributeValue("string", "f28b86350e534671"),
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/test/resources/json/sentry_logs.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
"type": "string",
"value": "production"
},
"custom.array":
{
"type": "array",
"value": ["a", "b"]
},
"sentry.sdk.version":
{
"type": "string",
Expand Down
Loading