Skip to content

Commit 596b702

Browse files
fix: serialize uint64_t values as numerical instead of string (#1408)
* serialize uint64 values as numerical instead of string * CHANGELOG.md * construct unsigned int log params as sentry_value_t string type * change format to expected unsigned long long int * pass through the conversion character * add tests for logs parameter conversion types * less strict pointer argument check
1 parent b58c786 commit 596b702

File tree

6 files changed

+116
-10
lines changed

6 files changed

+116
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
**Fixes**:
1111

1212
- Use proper SDK name determination for structured logs `sdk.name` attribute. ([#1399](https://github.com/getsentry/sentry-native/pull/1399))
13+
- Serialize `uint64` values as numerical instead of string. ([#1408](https://github.com/getsentry/sentry-native/pull/1408))
1314

1415
## 0.11.2
1516

src/sentry_json.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,9 @@ sentry__jsonwriter_write_int64(sentry_jsonwriter_t *jw, int64_t val)
381381
void
382382
sentry__jsonwriter_write_uint64(sentry_jsonwriter_t *jw, uint64_t val)
383383
{
384-
// TODO currently all uint64 values should be sent as strings; update when
385-
// this changes and 64-bit unsigned integers can be ingested properly
386-
// see
387-
// https://github.com/getsentry/sentry-native/pull/1326#discussion_r2241965997
388384
if (can_write_item(jw)) {
389385
char buf[26];
390-
snprintf(buf, sizeof(buf), "\"%" PRIu64 "\"", val);
386+
snprintf(buf, sizeof(buf), "%" PRIu64, val);
391387
write_str(jw, buf);
392388
}
393389
}

src/sentry_logs.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,13 @@ static
335335
case 'X':
336336
case 'o': {
337337
unsigned long long int val = va_arg(*args_copy, unsigned long long int);
338+
// TODO update once unsigned 64-bit can be sent as non-string
339+
char buf[26];
340+
char format[8];
341+
snprintf(format, sizeof(format), "%%ll%c", conversion);
342+
snprintf(buf, sizeof(buf), format, val);
338343
sentry_value_set_by_key(
339-
param_obj, "value", sentry_value_new_uint64(val));
340-
// TODO update once unsigned 64-bit can be sent
344+
param_obj, "value", sentry_value_new_string(buf));
341345
sentry_value_set_by_key(
342346
param_obj, "type", sentry_value_new_string("string"));
343347
break;

tests/unit/test_logs.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "sentry_testsupport.h"
33

44
#include "sentry_envelope.h"
5+
#include <string.h>
56

67
#ifdef SENTRY_PLATFORM_WINDOWS
78
# include <windows.h>
@@ -168,3 +169,106 @@ SENTRY_TEST(logs_param_conversion)
168169
test_param_conversion_helper("%d %d %d", a, b, c);
169170
#endif
170171
}
172+
173+
static void
174+
test_param_conversion_types(const char *format, ...)
175+
{
176+
sentry_value_t attributes = sentry_value_new_object();
177+
va_list args;
178+
va_start(args, format);
179+
int param_count = populate_message_parameters(attributes, format, args);
180+
va_end(args);
181+
182+
// Verify we got the expected number of parameters
183+
TEST_CHECK_INT_EQUAL(param_count, 7);
184+
185+
// Verify the parameters were extracted correctly
186+
sentry_value_t param0
187+
= sentry_value_get_by_key(attributes, "sentry.message.parameter.0");
188+
sentry_value_t param1
189+
= sentry_value_get_by_key(attributes, "sentry.message.parameter.1");
190+
sentry_value_t param2
191+
= sentry_value_get_by_key(attributes, "sentry.message.parameter.2");
192+
sentry_value_t param3
193+
= sentry_value_get_by_key(attributes, "sentry.message.parameter.3");
194+
sentry_value_t param4
195+
= sentry_value_get_by_key(attributes, "sentry.message.parameter.4");
196+
sentry_value_t param5
197+
= sentry_value_get_by_key(attributes, "sentry.message.parameter.5");
198+
sentry_value_t param6
199+
= sentry_value_get_by_key(attributes, "sentry.message.parameter.6");
200+
201+
TEST_CHECK(!sentry_value_is_null(param0));
202+
TEST_CHECK(!sentry_value_is_null(param1));
203+
TEST_CHECK(!sentry_value_is_null(param2));
204+
TEST_CHECK(!sentry_value_is_null(param3));
205+
TEST_CHECK(!sentry_value_is_null(param4));
206+
TEST_CHECK(!sentry_value_is_null(param5));
207+
TEST_CHECK(!sentry_value_is_null(param6));
208+
209+
// Check the values and types
210+
sentry_value_t value0 = sentry_value_get_by_key(param0, "value");
211+
sentry_value_t value1 = sentry_value_get_by_key(param1, "value");
212+
sentry_value_t value2 = sentry_value_get_by_key(param2, "value");
213+
sentry_value_t value3 = sentry_value_get_by_key(param3, "value");
214+
sentry_value_t value4 = sentry_value_get_by_key(param4, "value");
215+
sentry_value_t value5 = sentry_value_get_by_key(param5, "value");
216+
sentry_value_t value6 = sentry_value_get_by_key(param6, "value");
217+
218+
sentry_value_t type0 = sentry_value_get_by_key(param0, "type");
219+
sentry_value_t type1 = sentry_value_get_by_key(param1, "type");
220+
sentry_value_t type2 = sentry_value_get_by_key(param2, "type");
221+
sentry_value_t type3 = sentry_value_get_by_key(param3, "type");
222+
sentry_value_t type4 = sentry_value_get_by_key(param4, "type");
223+
sentry_value_t type5 = sentry_value_get_by_key(param5, "type");
224+
sentry_value_t type6 = sentry_value_get_by_key(param6, "type");
225+
226+
// Validate %u (unsigned) - should be string type with UINT64_MAX value
227+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(type0), "string");
228+
TEST_CHECK_STRING_EQUAL(
229+
sentry_value_as_string(value0), "18446744073709551615");
230+
231+
// Validate %d (signed integer) - should be integer type with INT64_MIN
232+
// value
233+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(type1), "integer");
234+
TEST_CHECK_INT_EQUAL(sentry_value_as_int64(value1), INT64_MIN);
235+
236+
// Validate %f (float) - should be double type with 3.14159 value
237+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(type2), "double");
238+
TEST_CHECK(sentry_value_as_double(value2) == 3.14159);
239+
240+
// Validate %c (character) - should be string type with 'A' value
241+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(type3), "string");
242+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(value3), "A");
243+
244+
// Validate %s (string) - should be string type with "test" value
245+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(type4), "string");
246+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(value4), "test");
247+
248+
// Validate %p (pointer) - should be string type with pointer representation
249+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(type5), "string");
250+
// Pointer value format is platform-dependent, but should contain the hex
251+
// digits (can be upper- or lower-cased)
252+
const char *ptr_str = sentry_value_as_string(value5);
253+
TEST_CHECK(ptr_str != NULL);
254+
TEST_CHECK(strstr(ptr_str, "12345abc") != NULL
255+
|| strstr(ptr_str, "12345ABC") != NULL);
256+
257+
// Validate %x (hex uint64) - should be string type with hex representation
258+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(type6), "string");
259+
TEST_CHECK_STRING_EQUAL(sentry_value_as_string(value6), "deadbeefdeadbeef");
260+
261+
sentry_value_decref(attributes);
262+
}
263+
264+
SENTRY_TEST(logs_param_types)
265+
{
266+
uint64_t a = UINT64_MAX;
267+
int64_t b = INT64_MIN;
268+
double c = 3.14159;
269+
char d = 'A';
270+
const char *e = "test";
271+
void *f = (void *)0x12345abc;
272+
uint64_t g = 0xDEADBEEFDEADBEEF;
273+
test_param_conversion_types("%u %d %f %c %s %p %x", a, b, c, d, e, f, g);
274+
}

tests/unit/test_value.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ SENTRY_TEST(value_uint64)
139139
// We don't convert uint64 to int32
140140
TEST_CHECK(sentry_value_as_int32(val) == 0);
141141
TEST_CHECK(sentry_value_is_true(val));
142-
TEST_CHECK_JSON_VALUE(val, "\"42\"");
142+
TEST_CHECK_JSON_VALUE(val, "42");
143143
TEST_CHECK(sentry_value_refcount(val) == 1);
144144
TEST_CHECK(sentry_value_is_frozen(val));
145145
sentry_value_decref(val);
@@ -149,15 +149,15 @@ SENTRY_TEST(value_uint64)
149149
TEST_CHECK(sentry_value_get_type(val) == SENTRY_VALUE_TYPE_UINT64);
150150
TEST_CHECK(sentry_value_as_uint64(val) == UINT64_MAX);
151151
TEST_CHECK(sentry_value_is_true(val));
152-
TEST_CHECK_JSON_VALUE(val, "\"18446744073709551615\"");
152+
TEST_CHECK_JSON_VALUE(val, "18446744073709551615");
153153
sentry_value_decref(val);
154154

155155
// Test zero
156156
val = sentry_value_new_uint64(0ULL);
157157
TEST_CHECK(sentry_value_get_type(val) == SENTRY_VALUE_TYPE_UINT64);
158158
TEST_CHECK(sentry_value_as_uint64(val) == 0ULL);
159159
TEST_CHECK(!sentry_value_is_true(val));
160-
TEST_CHECK_JSON_VALUE(val, "\"0\"");
160+
TEST_CHECK_JSON_VALUE(val, "0");
161161
TEST_CHECK(sentry_value_refcount(val) == 1);
162162
TEST_CHECK(sentry_value_is_frozen(val));
163163
sentry_value_decref(val);

tests/unit/tests.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ XX(logger_enable_disable_functionality)
8787
XX(logger_level)
8888
XX(logs_disabled_by_default)
8989
XX(logs_param_conversion)
90+
XX(logs_param_types)
9091
XX(message_with_null_text_is_valid)
9192
XX(module_addr)
9293
XX(module_finder)

0 commit comments

Comments
 (0)