Skip to content
Merged
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 @@ -7,6 +7,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))
- Add runtime API to query user consent requirement. ([#1443](https://github.com/getsentry/sentry-native/pull/1443))
- Add logs flush on `sentry_flush()`. ([#1434](https://github.com/getsentry/sentry-native/pull/1434))
- Add global attributes API. These are added to all `sentry_log_X` calls. ([#1450](https://github.com/getsentry/sentry-native/pull/1450))

## 0.12.1

Expand Down
18 changes: 15 additions & 3 deletions include/sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,12 @@ SENTRY_API sentry_value_t sentry_value_new_user_n(const char *id, size_t id_len,

/**
* Creates a new attribute object.
* value` is required, `unit` is optional.
* value is required, unit is optional.
*
*'value' must be a bool, int, double or string (not null, list, object)
* value must be a bool, int, double or string `sentry_value_t`
* OR a list of bool, int, double or string (with all items being the same type)
*
* Moves ownership of `value` into the object. The caller does not
* Moves ownership of value into the object. The caller does not
* have to call `sentry_value_decref` on it.
*/
SENTRY_API sentry_value_t sentry_value_new_attribute(
Expand Down Expand Up @@ -1858,6 +1859,17 @@ SENTRY_API void sentry_scope_set_extra_n(sentry_scope_t *scope, const char *key,
SENTRY_API void sentry_remove_extra(const char *key);
SENTRY_API void sentry_remove_extra_n(const char *key, size_t key_len);

/**
* Sets attributes created with `sentry_value_new_attribute` to be applied to
* all:
* - logs
*/
SENTRY_API void sentry_set_attribute(const char *key, sentry_value_t attribute);
SENTRY_API void sentry_set_attribute_n(
const char *key, size_t key_len, sentry_value_t attribute);
SENTRY_API void sentry_remove_attribute(const char *key);
SENTRY_API void sentry_remove_attribute_n(const char *key, size_t key_len);

/**
* Sets a context object.
*/
Expand Down
33 changes: 33 additions & 0 deletions src/sentry_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,39 @@ sentry_remove_extra_n(const char *key, size_t key_len)
}
}

void
sentry_set_attribute(const char *key, sentry_value_t attribute)
{
SENTRY_WITH_SCOPE_MUT (scope) {
sentry__scope_set_attribute(scope, key, attribute);
}
}

void
sentry_set_attribute_n(
const char *key, size_t key_len, sentry_value_t attribute)
{
SENTRY_WITH_SCOPE_MUT (scope) {
sentry__scope_set_attribute_n(scope, key, key_len, attribute);
}
}

void
sentry_remove_attribute(const char *key)
{
SENTRY_WITH_SCOPE_MUT (scope) {
sentry__scope_remove_attribute(scope, key);
}
}

void
sentry_remove_attribute_n(const char *key, size_t key_len)
{
SENTRY_WITH_SCOPE_MUT (scope) {
sentry__scope_remove_attribute_n(scope, key, key_len);
}
}

void
sentry_set_context(const char *key, sentry_value_t value)
{
Expand Down
5 changes: 4 additions & 1 deletion src/sentry_logs.c
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,10 @@ static sentry_value_t
construct_log(sentry_level_t level, const char *message, va_list args)
{
sentry_value_t log = sentry_value_new_object();
sentry_value_t attributes = sentry_value_new_object();
sentry_value_t attributes = sentry_value_new_null();
SENTRY_WITH_SCOPE (scope) {
attributes = sentry__value_clone(scope->attributes);
}

SENTRY_WITH_OPTIONS (options) {
// Extract custom attributes if the option is enabled
Expand Down
34 changes: 34 additions & 0 deletions src/sentry_scope.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ init_scope(sentry_scope_t *scope)
scope->user = sentry_value_new_null();
scope->tags = sentry_value_new_object();
scope->extra = sentry_value_new_object();
scope->attributes = sentry_value_new_object();
scope->contexts = sentry_value_new_object();
scope->propagation_context = sentry_value_new_object();
scope->breadcrumbs = sentry__ringbuffer_new(SENTRY_BREADCRUMBS_MAX);
Expand Down Expand Up @@ -110,6 +111,7 @@ cleanup_scope(sentry_scope_t *scope)
sentry_value_decref(scope->user);
sentry_value_decref(scope->tags);
sentry_value_decref(scope->extra);
sentry_value_decref(scope->attributes);
sentry_value_decref(scope->contexts);
sentry_value_decref(scope->propagation_context);
sentry__ringbuffer_free(scope->breadcrumbs);
Expand Down Expand Up @@ -588,6 +590,38 @@ sentry_scope_set_extra_n(sentry_scope_t *scope, const char *key, size_t key_len,
sentry_value_set_by_key_n(scope->extra, key, key_len, value);
}

void
sentry__scope_set_attribute(
sentry_scope_t *scope, const char *key, sentry_value_t attribute)
{
sentry__scope_set_attribute_n(scope, key, strlen(key), attribute);
}

void
sentry__scope_set_attribute_n(sentry_scope_t *scope, const char *key,
size_t key_len, sentry_value_t attribute)
{
if (sentry_value_is_null(sentry_value_get_by_key(attribute, "value"))
|| sentry_value_is_null(sentry_value_get_by_key(attribute, "type"))) {
SENTRY_DEBUG("Cannot set attribute with missing 'value' or 'type'");
return;
}
sentry_value_set_by_key_n(scope->attributes, key, key_len, attribute);
}

void
sentry__scope_remove_attribute(sentry_scope_t *scope, const char *key)
{
sentry_value_remove_by_key(scope->attributes, key);
}

void
sentry__scope_remove_attribute_n(
sentry_scope_t *scope, const char *key, size_t key_len)
{
sentry_value_remove_by_key_n(scope->attributes, key, key_len);
}

void
sentry_scope_set_context(
sentry_scope_t *scope, const char *key, sentry_value_t value)
Expand Down
16 changes: 16 additions & 0 deletions src/sentry_scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct sentry_scope_s {
sentry_value_t user;
sentry_value_t tags;
sentry_value_t extra;
sentry_value_t attributes;
sentry_value_t contexts;
sentry_value_t propagation_context;
sentry_ringbuffer_t *breadcrumbs;
Expand Down Expand Up @@ -96,6 +97,21 @@ void sentry__scope_set_fingerprint_va(
void sentry__scope_set_fingerprint_nva(sentry_scope_t *scope,
const char *fingerprint, size_t fingerprint_len, va_list va);

/**
* Internal scope-based attribute functions.
* For now, these are only used by the non-scope API functions that operate
* on the global scope.
* Once we have attributes for events or scope-based logs/metrics/spans APIs
* these can become part of the public API too.
*/
void sentry__scope_set_attribute(
sentry_scope_t *scope, const char *key, sentry_value_t attribute);
void sentry__scope_set_attribute_n(sentry_scope_t *scope, const char *key,
size_t key_len, sentry_value_t attribute);
void sentry__scope_remove_attribute(sentry_scope_t *scope, const char *key);
void sentry__scope_remove_attribute_n(
sentry_scope_t *scope, const char *key, size_t key_len);

/**
* These are convenience macros to automatically lock/unlock the global scope
* inside a code block.
Expand Down
60 changes: 47 additions & 13 deletions src/sentry_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,33 +509,67 @@ sentry_value_new_user(const char *id, const char *username, const char *email,
ip_address, ip_address ? strlen(ip_address) : 0);
}

sentry_value_t
sentry_value_new_attribute_n(
sentry_value_t value, const char *unit, size_t unit_len)
/**
* Converts a sentry_value_t attribute to its type string representation.
* For lists, checks the first element to determine the array type.
* Returns NULL for unsupported types (NULL, OBJECT).
* https://develop.sentry.dev/sdk/telemetry/spans/span-protocol/#attribute-object-properties
*/
static const char *
attribute_value_type_to_str(sentry_value_t value)
{
char *type;
switch (sentry_value_get_type(value)) {
case SENTRY_VALUE_TYPE_BOOL:
type = "boolean";
break;
return "boolean";
case SENTRY_VALUE_TYPE_INT32:
case SENTRY_VALUE_TYPE_INT64:
case SENTRY_VALUE_TYPE_UINT64:
type = "integer";
break;
return "integer";
case SENTRY_VALUE_TYPE_DOUBLE:
type = "double";
break;
return "double";
case SENTRY_VALUE_TYPE_STRING:
type = "string";
break;
return "string";
case SENTRY_VALUE_TYPE_LIST: {
sentry_value_t first_item = sentry_value_get_by_index(value, 0);
if (sentry_value_is_null(first_item)) {
return NULL;
}
// Determine type based on first element
switch (sentry_value_get_type(first_item)) {
case SENTRY_VALUE_TYPE_BOOL:
return "boolean[]";
case SENTRY_VALUE_TYPE_INT32:
case SENTRY_VALUE_TYPE_INT64:
case SENTRY_VALUE_TYPE_UINT64:
return "integer[]";
case SENTRY_VALUE_TYPE_DOUBLE:
return "double[]";
case SENTRY_VALUE_TYPE_STRING:
return "string[]";
case SENTRY_VALUE_TYPE_NULL:
case SENTRY_VALUE_TYPE_OBJECT:
case SENTRY_VALUE_TYPE_LIST:
default:
return NULL;
}
}
case SENTRY_VALUE_TYPE_NULL:
case SENTRY_VALUE_TYPE_LIST:
case SENTRY_VALUE_TYPE_OBJECT:
default:
return NULL;
}
}

sentry_value_t
sentry_value_new_attribute_n(
sentry_value_t value, const char *unit, size_t unit_len)
{
const char *type = attribute_value_type_to_str(value);
if (!type) {
sentry_value_decref(value);
return sentry_value_new_null();
}

sentry_value_t attribute = sentry_value_new_object();

sentry_value_set_by_key(
Expand Down
Loading
Loading