Skip to content

Commit a001e25

Browse files
adinauerclaude
andcommitted
fix(kafka): [Queue Instrumentation 31] Write enqueued-time header as plain decimal
The sentry-task-enqueued-time Kafka header was serialized via String.valueOf(double), which emits scientific notation (e.g. 1.776933649613E9) for epoch-seconds values. Cross-SDK consumers (sentry-python, -ruby, -php, -dotnet) expect a plain decimal like 1776938295.692000 and could not parse the Java output, defeating the cross-SDK alignment goal of #5283. Route the value through DateUtils.doubleToBigDecimal(...).toString(), the same helper already used to serialize epoch-seconds timestamps in SentryTransaction, SentrySpan, SentryLogEvent, etc. At the pinned scale of 6, BigDecimal.toString() produces plain decimal form for all realistic epoch-seconds magnitudes. Add regression assertions that reject scientific notation and pin the plain-decimal format in SentryKafkaProducerInterceptorTest. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7384727 commit a001e25

2 files changed

Lines changed: 16 additions & 2 deletions

File tree

sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducerInterceptor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ private void injectHeaders(final @NotNull Headers headers, final @NotNull ISpan
128128
headers.remove(SENTRY_ENQUEUED_TIME_HEADER);
129129
headers.add(
130130
SENTRY_ENQUEUED_TIME_HEADER,
131-
String.valueOf(DateUtils.millisToSeconds(System.currentTimeMillis()))
131+
DateUtils.doubleToBigDecimal(DateUtils.millisToSeconds(System.currentTimeMillis()))
132+
.toString()
132133
.getBytes(StandardCharsets.UTF_8));
133134
}
134135

sentry-kafka/src/test/kotlin/io/sentry/kafka/SentryKafkaProducerInterceptorTest.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import kotlin.test.AfterTest
1717
import kotlin.test.BeforeTest
1818
import kotlin.test.Test
1919
import kotlin.test.assertEquals
20+
import kotlin.test.assertFalse
2021
import kotlin.test.assertNotNull
2122
import kotlin.test.assertSame
2223
import kotlin.test.assertTrue
@@ -84,7 +85,19 @@ class SentryKafkaProducerInterceptorTest {
8485
val enqueuedTimeHeader =
8586
record.headers().lastHeader(SentryKafkaProducerInterceptor.SENTRY_ENQUEUED_TIME_HEADER)
8687
assertNotNull(enqueuedTimeHeader)
87-
val enqueuedTime = String(enqueuedTimeHeader.value(), StandardCharsets.UTF_8).toDouble()
88+
val enqueuedTimeRaw = String(enqueuedTimeHeader.value(), StandardCharsets.UTF_8)
89+
// Must be written as a plain decimal so cross-SDK consumers (e.g. sentry-python) can
90+
// parse it. String.valueOf(double) would emit scientific notation (e.g. 1.77E9) for
91+
// epoch seconds.
92+
assertFalse(
93+
enqueuedTimeRaw.contains('E') || enqueuedTimeRaw.contains('e'),
94+
"enqueued-time header must not use scientific notation, got: $enqueuedTimeRaw",
95+
)
96+
assertTrue(
97+
enqueuedTimeRaw.matches(Regex("""^\d+\.\d{6}$""")),
98+
"enqueued-time header must be plain epoch seconds with 6 decimals, got: $enqueuedTimeRaw",
99+
)
100+
val enqueuedTime = enqueuedTimeRaw.toDouble()
88101
assertTrue(enqueuedTime > 0)
89102
}
90103

0 commit comments

Comments
 (0)