diff --git a/CHANGELOG.md b/CHANGELOG.md
index f4cfc2adde..d0aef1e6dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,9 +5,7 @@
### Features
- Add scope-level attributes API ([#5118](https://github.com/getsentry/sentry-java/pull/5118))
-<<<<<<< feat/scope-attributes-logger-metrics
- Automatically include scope attributes in logs and metrics ([#5120](https://github.com/getsentry/sentry-java/pull/5120))
-=======
- Create `sentry-opentelemetry-otlp` and `sentry-opentelemetry-otlp-spring` modules for combining OpenTelemetry SDK OTLP export with Sentry SDK ([#5100](https://github.com/getsentry/sentry-java/pull/5100))
- OpenTelemetry is configured to send spans to Sentry directly using an OTLP endpoint.
- Sentry only uses trace and span ID from OpenTelemetry (via `OpenTelemetryOtlpEventProcessor`) but will not send spans through OpenTelemetry nor use OpenTelemetry `Context` for `Scopes` propagation.
@@ -31,10 +29,10 @@
```
->>>>>>> feat/global-attributes-api
### Fixes
+- Fix attribute type detection for `Long`, `Short`, `Byte`, `BigInteger`, `AtomicInteger`, and `AtomicLong` being incorrectly inferred as `double` instead of `integer` ([#5122](https://github.com/getsentry/sentry-java/pull/5122))
- Remove `AndroidRuntimeManager` StrictMode relaxation to prevent ANRs during SDK init ([#5127](https://github.com/getsentry/sentry-java/pull/5127))
- **IMPORTANT:** StrictMode violations may appear again in debug builds. This is intentional to prevent ANRs in production releases.
- Fix crash when unregistering `SystemEventsBroadcastReceiver` with try-catch block. ([#5106](https://github.com/getsentry/sentry-java/pull/5106))
diff --git a/sentry/src/main/java/io/sentry/SentryAttributeType.java b/sentry/src/main/java/io/sentry/SentryAttributeType.java
index 8de00d277d..86325c248a 100644
--- a/sentry/src/main/java/io/sentry/SentryAttributeType.java
+++ b/sentry/src/main/java/io/sentry/SentryAttributeType.java
@@ -1,6 +1,9 @@
package io.sentry;
+import java.math.BigInteger;
import java.util.Locale;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -18,7 +21,13 @@ public enum SentryAttributeType {
if (value instanceof Boolean) {
return BOOLEAN;
}
- if (value instanceof Integer) {
+ if (value instanceof Integer
+ || value instanceof Long
+ || value instanceof Short
+ || value instanceof Byte
+ || value instanceof BigInteger
+ || value instanceof AtomicInteger
+ || value instanceof AtomicLong) {
return INTEGER;
}
if (value instanceof Number) {
diff --git a/sentry/src/test/java/io/sentry/SentryAttributeTypeTest.kt b/sentry/src/test/java/io/sentry/SentryAttributeTypeTest.kt
new file mode 100644
index 0000000000..f1e1cf169a
--- /dev/null
+++ b/sentry/src/test/java/io/sentry/SentryAttributeTypeTest.kt
@@ -0,0 +1,80 @@
+package io.sentry
+
+import java.math.BigDecimal
+import java.math.BigInteger
+import java.util.concurrent.atomic.AtomicInteger
+import java.util.concurrent.atomic.AtomicLong
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class SentryAttributeTypeTest {
+
+ @Test
+ fun `inferFrom returns BOOLEAN for Boolean`() {
+ assertEquals(SentryAttributeType.BOOLEAN, SentryAttributeType.inferFrom(true))
+ assertEquals(SentryAttributeType.BOOLEAN, SentryAttributeType.inferFrom(false))
+ }
+
+ @Test
+ fun `inferFrom returns INTEGER for Integer`() {
+ assertEquals(SentryAttributeType.INTEGER, SentryAttributeType.inferFrom(42))
+ }
+
+ @Test
+ fun `inferFrom returns INTEGER for Long`() {
+ assertEquals(SentryAttributeType.INTEGER, SentryAttributeType.inferFrom(42L))
+ }
+
+ @Test
+ fun `inferFrom returns INTEGER for Short`() {
+ assertEquals(SentryAttributeType.INTEGER, SentryAttributeType.inferFrom(42.toShort()))
+ }
+
+ @Test
+ fun `inferFrom returns INTEGER for Byte`() {
+ assertEquals(SentryAttributeType.INTEGER, SentryAttributeType.inferFrom(42.toByte()))
+ }
+
+ @Test
+ fun `inferFrom returns INTEGER for BigInteger`() {
+ assertEquals(SentryAttributeType.INTEGER, SentryAttributeType.inferFrom(BigInteger.valueOf(42)))
+ }
+
+ @Test
+ fun `inferFrom returns INTEGER for AtomicInteger`() {
+ assertEquals(SentryAttributeType.INTEGER, SentryAttributeType.inferFrom(AtomicInteger(42)))
+ }
+
+ @Test
+ fun `inferFrom returns INTEGER for AtomicLong`() {
+ assertEquals(SentryAttributeType.INTEGER, SentryAttributeType.inferFrom(AtomicLong(42)))
+ }
+
+ @Test
+ fun `inferFrom returns DOUBLE for Double`() {
+ assertEquals(SentryAttributeType.DOUBLE, SentryAttributeType.inferFrom(3.14))
+ }
+
+ @Test
+ fun `inferFrom returns DOUBLE for Float`() {
+ assertEquals(SentryAttributeType.DOUBLE, SentryAttributeType.inferFrom(3.14f))
+ }
+
+ @Test
+ fun `inferFrom returns DOUBLE for BigDecimal`() {
+ assertEquals(
+ SentryAttributeType.DOUBLE,
+ SentryAttributeType.inferFrom(BigDecimal.valueOf(3.14)),
+ )
+ }
+
+ @Test
+ fun `inferFrom returns STRING for String`() {
+ assertEquals(SentryAttributeType.STRING, SentryAttributeType.inferFrom("hello"))
+ }
+
+ @Test
+ fun `inferFrom returns STRING for null`() {
+ assertEquals(SentryAttributeType.STRING, SentryAttributeType.inferFrom(null))
+ }
+}