Skip to content

Commit 878a488

Browse files
committed
infer attribute type from sentry_value_t value
1 parent 46cd9f1 commit 878a488

File tree

7 files changed

+75
-93
lines changed

7 files changed

+75
-93
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
**Features**:
66

7-
- Add custom attributes API for logs. Treats the first `varg` passed into `sentry_logs_X(message,...)` as a `sentry_value_t` object of attributes. ([#1435](https://github.com/getsentry/sentry-native/pull/1435))
7+
- Add custom attributes API for logs. When `logs_with_attributes` is set to `true`, treats the first `varg` passed into `sentry_logs_X(message,...)` as a `sentry_value_t` object of attributes. ([#1435](https://github.com/getsentry/sentry-native/pull/1435))
88

99
**Fixes**:
1010

examples/example.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ static sentry_value_t
163163
before_send_log_callback(sentry_value_t log, void *user_data)
164164
{
165165
(void)user_data;
166-
sentry_value_t attribute = sentry_value_new_attribute(
167-
"string", sentry_value_new_string("little"), NULL);
166+
sentry_value_t attribute
167+
= sentry_value_new_attribute(sentry_value_new_string("little"), NULL);
168168
sentry_value_set_by_key(sentry_value_get_by_key(log, "attributes"),
169169
"coffeepot.size", attribute);
170170
return log;
@@ -511,11 +511,11 @@ main(int argc, char **argv)
511511
if (has_arg(argc, argv, "log-attributes")) {
512512
sentry_value_t attributes = sentry_value_new_object();
513513
sentry_value_t attr = sentry_value_new_attribute(
514-
"string", sentry_value_new_string("my_attribute"), NULL);
514+
sentry_value_new_string("my_attribute"), NULL);
515515
sentry_value_t attr_2 = sentry_value_new_attribute(
516-
"integer", sentry_value_new_int64(INT64_MAX), "fermions");
516+
sentry_value_new_int64(INT64_MAX), "fermions");
517517
sentry_value_t attr_3 = sentry_value_new_attribute(
518-
"integer", sentry_value_new_int64(INT64_MIN), "bosons");
518+
sentry_value_new_int64(INT64_MIN), "bosons");
519519
sentry_value_set_by_key(attributes, "my.custom.attribute", attr);
520520
sentry_value_set_by_key(attributes, "number.first", attr_2);
521521
sentry_value_set_by_key(attributes, "number.second", attr_3);
@@ -526,6 +526,18 @@ main(int argc, char **argv)
526526
// passed-in value is accidentally not an object
527527
sentry_log_warn("logging with %s custom attributes",
528528
sentry_value_new_null(), "new_null as");
529+
sentry_value_t param_attributes = sentry_value_new_object();
530+
sentry_value_t param_attr = sentry_value_new_attribute(
531+
sentry_value_new_string("parameter"), NULL);
532+
sentry_value_set_by_key(
533+
param_attributes, "message.parameter.0", param_attr);
534+
sentry_log_fatal(
535+
"logging with a custom parameter attributes", param_attributes);
536+
sentry_value_t param_attributes_2 = sentry_value_new_object();
537+
sentry_value_t param_attr_2 = sentry_value_new_attribute(
538+
sentry_value_new_string("parameter"), NULL);
539+
sentry_log_fatal("logging with a custom parameter %s attributes",
540+
param_attributes, "and format-string");
529541
}
530542

531543
if (has_arg(argc, argv, "attachment")) {

include/sentry.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,15 +326,17 @@ SENTRY_API sentry_value_t sentry_value_new_user_n(const char *id, size_t id_len,
326326

327327
/**
328328
* Creates a new attribute object.
329-
* `type` and `value` are required, `unit` is optional.
329+
* value` is required, `unit` is optional.
330+
*
331+
*'value' must be a bool, int, double or string (not null, list, object)
330332
*
331333
* Moves ownership of `value` into the object. The caller does not
332334
* have to call `sentry_value_decref` on it.
333335
*/
334336
SENTRY_API sentry_value_t sentry_value_new_attribute(
335-
const char *type, sentry_value_t value, const char *unit);
336-
SENTRY_API sentry_value_t sentry_value_new_attribute_n(const char *type,
337-
size_t type_len, sentry_value_t value, const char *unit, size_t unit_len);
337+
sentry_value_t value, const char *unit);
338+
SENTRY_API sentry_value_t sentry_value_new_attribute_n(
339+
sentry_value_t value, const char *unit, size_t unit_len);
338340

339341
/**
340342
* Returns the type of the value passed.

src/sentry_logs.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,14 +685,12 @@ construct_log(sentry_level_t level, const char *message, va_list args)
685685
sentry_value_t custom_attributes
686686
= va_arg(args_copy, sentry_value_t);
687687
va_end(args_copy);
688-
// TODO is this enough to check whether this is a valid
689-
// sentry_value_t object?
690688
if (sentry_value_get_type(custom_attributes)
691689
== SENTRY_VALUE_TYPE_OBJECT) {
692690
SENTRY_DEBUG("Discarded custom attributes on log: non-object "
693691
"sentry_value_t passed in");
694692
sentry_value_decref(attributes);
695-
attributes = custom_attributes;
693+
attributes = sentry__value_clone(custom_attributes);
696694
}
697695
}
698696

src/sentry_value.c

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -510,31 +510,36 @@ sentry_value_new_user(const char *id, const char *username, const char *email,
510510
}
511511

512512
sentry_value_t
513-
sentry_value_new_attribute_n(const char *type, size_t type_len,
513+
sentry_value_new_attribute_n(
514514
sentry_value_t value, const char *unit, size_t unit_len)
515515
{
516-
// Check if type is valid
517-
if (!type || type_len == 0) {
518-
sentry_value_decref(value);
519-
return sentry_value_new_null();
520-
}
521-
522-
// Check if type is one of the allowed values
523-
if (!((type_len == 6 && strncmp(type, "string", 6) == 0)
524-
|| (type_len == 7 && strncmp(type, "integer", 7) == 0)
525-
|| (type_len == 6 && strncmp(type, "double", 6) == 0)
526-
|| (type_len == 7 && strncmp(type, "boolean", 7) == 0))) {
527-
SENTRY_DEBUG("attribute type has to be `string`, `integer`, `double` "
528-
"or `boolean`");
516+
sentry_value_t attribute = sentry_value_new_object();
517+
char *type;
518+
switch (sentry_value_get_type(value)) {
519+
case SENTRY_VALUE_TYPE_BOOL:
520+
type = "boolean";
521+
break;
522+
case SENTRY_VALUE_TYPE_INT32:
523+
case SENTRY_VALUE_TYPE_INT64:
524+
case SENTRY_VALUE_TYPE_UINT64:
525+
type = "integer";
526+
break;
527+
case SENTRY_VALUE_TYPE_DOUBLE:
528+
type = "double";
529+
break;
530+
case SENTRY_VALUE_TYPE_STRING:
531+
type = "string";
532+
break;
533+
case SENTRY_VALUE_TYPE_NULL:
534+
case SENTRY_VALUE_TYPE_LIST:
535+
case SENTRY_VALUE_TYPE_OBJECT:
536+
default:
529537
sentry_value_decref(value);
530538
return sentry_value_new_null();
531539
}
532-
533-
sentry_value_t attribute = sentry_value_new_object();
534540
sentry_value_set_by_key(
535-
attribute, "type", sentry_value_new_string_n(type, type_len));
541+
attribute, "type", sentry_value_new_string_n(type, strlen(type)));
536542
sentry_value_set_by_key(attribute, "value", value);
537-
// TODO should we validate whether the "value" matches the given "type"?
538543
if (unit && unit_len) {
539544
sentry_value_set_by_key(
540545
attribute, "unit", sentry_value_new_string_n(unit, unit_len));
@@ -543,15 +548,9 @@ sentry_value_new_attribute_n(const char *type, size_t type_len,
543548
}
544549

545550
sentry_value_t
546-
sentry_value_new_attribute(
547-
const char *type, sentry_value_t value, const char *unit)
551+
sentry_value_new_attribute(sentry_value_t value, const char *unit)
548552
{
549-
if (!type) {
550-
sentry_value_decref(value);
551-
return sentry_value_new_null();
552-
}
553-
return sentry_value_new_attribute_n(
554-
type, strlen(type), value, unit, unit ? strlen(unit) : 0);
553+
return sentry_value_new_attribute_n(value, unit, unit ? strlen(unit) : 0);
555554
}
556555

557556
sentry_value_type_t

tests/unit/test_logs.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ SENTRY_TEST(logs_custom_attributes_with_format_strings)
308308
// Test 1: Custom attributes with format string
309309
sentry_value_t attributes1 = sentry_value_new_object();
310310
sentry_value_t attr1 = sentry_value_new_attribute(
311-
"string", sentry_value_new_string("custom_value"), NULL);
311+
sentry_value_new_string("custom_value"), NULL);
312312
sentry_value_set_by_key(attributes1, "my.custom.attribute", attr1);
313313
TEST_CHECK_INT_EQUAL(sentry_log_info("User %s logged in with code %d",
314314
attributes1, "Alice", 200),
@@ -321,16 +321,16 @@ SENTRY_TEST(logs_custom_attributes_with_format_strings)
321321

322322
// Test 3: Custom attributes with no format parameters
323323
sentry_value_t attributes2 = sentry_value_new_object();
324-
sentry_value_t attr2 = sentry_value_new_attribute(
325-
"integer", sentry_value_new_int32(42), NULL);
324+
sentry_value_t attr2
325+
= sentry_value_new_attribute(sentry_value_new_int32(42), NULL);
326326
sentry_value_set_by_key(attributes2, "special.number", attr2);
327327
TEST_CHECK_INT_EQUAL(
328328
sentry_log_error("Simple message with custom attrs", attributes2), 0);
329329

330330
// Test 4: Custom attributes with multiple format types
331331
sentry_value_t attributes3 = sentry_value_new_object();
332-
sentry_value_t attr3 = sentry_value_new_attribute(
333-
"string", sentry_value_new_string("tracking"), NULL);
332+
sentry_value_t attr3
333+
= sentry_value_new_attribute(sentry_value_new_string("tracking"), NULL);
334334
sentry_value_set_by_key(attributes3, "event.type", attr3);
335335
TEST_CHECK_INT_EQUAL(
336336
sentry_log_debug("Processing item %d of %d (%.1f%% complete)",

tests/unit/test_value.c

Lines changed: 20 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ SENTRY_TEST(value_attribute)
437437
{
438438
// Test valid attribute types
439439
sentry_value_t string_attr = sentry_value_new_attribute(
440-
"string", sentry_value_new_string("test_value"), NULL);
440+
sentry_value_new_string("test_value"), NULL);
441441
TEST_CHECK(sentry_value_get_type(string_attr) == SENTRY_VALUE_TYPE_OBJECT);
442442
TEST_CHECK_STRING_EQUAL(
443443
sentry_value_as_string(sentry_value_get_by_key(string_attr, "type")),
@@ -449,8 +449,8 @@ SENTRY_TEST(value_attribute)
449449
sentry_value_is_null(sentry_value_get_by_key(string_attr, "unit")));
450450
sentry_value_decref(string_attr);
451451

452-
sentry_value_t integer_attr = sentry_value_new_attribute(
453-
"integer", sentry_value_new_int32(42), NULL);
452+
sentry_value_t integer_attr
453+
= sentry_value_new_attribute(sentry_value_new_int32(42), NULL);
454454
TEST_CHECK(sentry_value_get_type(integer_attr) == SENTRY_VALUE_TYPE_OBJECT);
455455
TEST_CHECK_STRING_EQUAL(
456456
sentry_value_as_string(sentry_value_get_by_key(integer_attr, "type")),
@@ -462,8 +462,8 @@ SENTRY_TEST(value_attribute)
462462
sentry_value_is_null(sentry_value_get_by_key(integer_attr, "unit")));
463463
sentry_value_decref(integer_attr);
464464

465-
sentry_value_t double_attr = sentry_value_new_attribute(
466-
"double", sentry_value_new_double(3.14), NULL);
465+
sentry_value_t double_attr
466+
= sentry_value_new_attribute(sentry_value_new_double(3.14), NULL);
467467
TEST_CHECK(sentry_value_get_type(double_attr) == SENTRY_VALUE_TYPE_OBJECT);
468468
TEST_CHECK_STRING_EQUAL(
469469
sentry_value_as_string(sentry_value_get_by_key(double_attr, "type")),
@@ -475,8 +475,8 @@ SENTRY_TEST(value_attribute)
475475
sentry_value_is_null(sentry_value_get_by_key(double_attr, "unit")));
476476
sentry_value_decref(double_attr);
477477

478-
sentry_value_t boolean_attr = sentry_value_new_attribute(
479-
"boolean", sentry_value_new_bool(true), NULL);
478+
sentry_value_t boolean_attr
479+
= sentry_value_new_attribute(sentry_value_new_bool(true), NULL);
480480
TEST_CHECK(sentry_value_get_type(boolean_attr) == SENTRY_VALUE_TYPE_OBJECT);
481481
TEST_CHECK_STRING_EQUAL(
482482
sentry_value_as_string(sentry_value_get_by_key(boolean_attr, "type")),
@@ -488,8 +488,8 @@ SENTRY_TEST(value_attribute)
488488
sentry_value_decref(boolean_attr);
489489

490490
// Test attribute with unit
491-
sentry_value_t attr_with_unit = sentry_value_new_attribute(
492-
"integer", sentry_value_new_int32(100), "percent");
491+
sentry_value_t attr_with_unit
492+
= sentry_value_new_attribute(sentry_value_new_int32(100), "percent");
493493
TEST_CHECK(
494494
sentry_value_get_type(attr_with_unit) == SENTRY_VALUE_TYPE_OBJECT);
495495
TEST_CHECK_STRING_EQUAL(
@@ -503,27 +503,27 @@ SENTRY_TEST(value_attribute)
503503
"percent");
504504
sentry_value_decref(attr_with_unit);
505505

506-
// Test invalid attribute types
507-
sentry_value_t invalid_attr = sentry_value_new_attribute(
508-
"invalid_type", sentry_value_new_string("test"), NULL);
506+
// Test invalid sentry_value_t types
507+
sentry_value_t invalid_attr
508+
= sentry_value_new_attribute(sentry_value_new_list(), NULL);
509509
TEST_CHECK(sentry_value_is_null(invalid_attr));
510510
sentry_value_decref(invalid_attr);
511511

512512
// Test NULL type
513-
sentry_value_t null_type_attr = sentry_value_new_attribute(
514-
NULL, sentry_value_new_string("test"), NULL);
513+
sentry_value_t null_type_attr
514+
= sentry_value_new_attribute(sentry_value_new_null(), NULL);
515515
TEST_CHECK(sentry_value_is_null(null_type_attr));
516516
sentry_value_decref(null_type_attr);
517517

518-
// Test empty type
519-
sentry_value_t empty_type_attr
520-
= sentry_value_new_attribute("", sentry_value_new_string("test"), NULL);
521-
TEST_CHECK(sentry_value_is_null(empty_type_attr));
522-
sentry_value_decref(empty_type_attr);
518+
// Test NULL type
519+
sentry_value_t object_type_attr
520+
= sentry_value_new_attribute(sentry_value_new_object(), NULL);
521+
TEST_CHECK(sentry_value_is_null(null_type_attr));
522+
sentry_value_decref(null_type_attr);
523523

524524
// Test _n version with explicit lengths
525525
sentry_value_t string_attr_n = sentry_value_new_attribute_n(
526-
"string", 6, sentry_value_new_string("test_n"), "bytes", 5);
526+
sentry_value_new_string("test_n"), "bytes", 5);
527527
TEST_CHECK(
528528
sentry_value_get_type(string_attr_n) == SENTRY_VALUE_TYPE_OBJECT);
529529
TEST_CHECK_STRING_EQUAL(
@@ -536,35 +536,6 @@ SENTRY_TEST(value_attribute)
536536
sentry_value_as_string(sentry_value_get_by_key(string_attr_n, "unit")),
537537
"bytes");
538538
sentry_value_decref(string_attr_n);
539-
540-
// Test _n version with zero length type (should return null)
541-
sentry_value_t zero_len_attr = sentry_value_new_attribute_n(
542-
"string", 0, sentry_value_new_string("test"), NULL, 0);
543-
TEST_CHECK(sentry_value_is_null(zero_len_attr));
544-
sentry_value_decref(zero_len_attr);
545-
546-
// Test _n version with NULL type
547-
sentry_value_t null_type_attr_n = sentry_value_new_attribute_n(
548-
NULL, 6, sentry_value_new_string("test"), NULL, 0);
549-
TEST_CHECK(sentry_value_is_null(null_type_attr_n));
550-
sentry_value_decref(null_type_attr_n);
551-
552-
// Test _n version with partial string matching (should work for valid
553-
// types)
554-
const char *long_type = "string_with_extra_chars";
555-
sentry_value_t partial_attr = sentry_value_new_attribute_n(
556-
long_type, 6, sentry_value_new_string("partial"), NULL, 0);
557-
TEST_CHECK(sentry_value_get_type(partial_attr) == SENTRY_VALUE_TYPE_OBJECT);
558-
TEST_CHECK_STRING_EQUAL(
559-
sentry_value_as_string(sentry_value_get_by_key(partial_attr, "type")),
560-
"string");
561-
sentry_value_decref(partial_attr);
562-
563-
// Test _n version with invalid partial string
564-
sentry_value_t invalid_partial_attr = sentry_value_new_attribute_n(
565-
"invalid", 7, sentry_value_new_string("test"), NULL, 0);
566-
TEST_CHECK(sentry_value_is_null(invalid_partial_attr));
567-
sentry_value_decref(invalid_partial_attr);
568539
}
569540

570541
SENTRY_TEST(value_freezing)

0 commit comments

Comments
 (0)