Skip to content

Structured Logs: follow up - custom attributes #1405

@JoshuaMoelans

Description

@JoshuaMoelans

Part of #1398
The spec allows for key-value paired attributes which are added as key : {"value": value, "type": type} to the 'attributes' item in the envelope. This is possible using before_send_log, but not convenient (as one would need to inspect the log to add log-specific attributes).

We could approach this in a few different ways:

Attributes-only log function

Since downstream does not need string-interpolation (as this is handled from their side), we could provide a simple attributes-only log function

  • Add option to disable string interpolation (both for parsing arguments as well as writing the body field).
// construct attributes dict
sentry_value_t attributes = sentry_value_new_object();
// create item (e.g. message parameter)
sentry_value_t message_param = sentry_value_new_object();
sentry_value_set_by_key(message_param, "value", sentry_value_new_string("login"));
sentry_value_set_by_key(message_param, "type", sentry_value_new_string("string"));
sentry_value_set_by_key(attributes, "sentry.message.parameter.0", action_attr);

sentry_log_debug("I'm a debug string!", attributes);

Reuse existing API

We can try to parse an additional sentry_value_t at the end of the parameters, but since this might or might not be there, this could be tricky.

// construct attributes dict
sentry_value_t attributes = sentry_value_new_object();
// create item
sentry_value_t action_attr = sentry_value_new_object();
sentry_value_set_by_key(action_attr, "value", sentry_value_new_string("login"));
sentry_value_set_by_key(action_attr, "type", sentry_value_new_string("string"));
sentry_value_set_by_key(attributes, "user.action", action_attr);

sentry_log_debug("I'm a %s string!", "debug", attributes);

Implement additional API

A simpler solution (although it doubles the API surface) would be to add logs functions that take in the attributes as the first argument, such that under the hood we can still call into the existing sentry_logs_X functions, and then just add the given attributes to the constructed log.

// construct attributes dict
sentry_value_t attributes = sentry_value_new_object();
// create item
sentry_value_t action_attr = sentry_value_new_object();
sentry_value_set_by_key(action_attr, "value", sentry_value_new_string("login"));
sentry_value_set_by_key(action_attr, "type", sentry_value_new_string("string"));
sentry_value_set_by_key(attributes, "user.action", action_attr);

sentry_log_debug_attr(attributes, "I'm a %s string!", "debug");

Consolidate with alternative logs API

#1297
We had a POC for a logs API that looked like this:

sentry_value_t parameters = sentry_value_new_list();
sentry_value_t param = sentry_value_new_object();
sentry_value_set_by_key(param, "name", sentry_value_new_string("intparam"));
sentry_value_set_by_key(param, "value", sentry_value_new_int32(-1));
sentry_value_append(parameters, param);
sentry_log_debug_value("My intparam value is now %i", parameters);

We could extend that one to also allow for the attributes as a third parameter (which could be a sentry_value_new_null) to avoid having even more logs APIs (normal, with attributes, with named parameters, with named parameters & attributes)

sentry_value_t parameters = sentry_value_new_list();
sentry_value_t param = sentry_value_new_object();
sentry_value_set_by_key(param, "name", sentry_value_new_string("intparam"));
sentry_value_set_by_key(param, "value", sentry_value_new_int32(-1));
sentry_value_append(parameters, param);

// construct attributes dict
sentry_value_t attributes = sentry_value_new_object();
// create item
sentry_value_t action_attr = sentry_value_new_object();
sentry_value_set_by_key(action_attr, "value", sentry_value_new_string("login"));
sentry_value_set_by_key(action_attr, "type", sentry_value_new_string("string"));
sentry_value_set_by_key(attributes, "user.action", action_attr);

sentry_log_debug_value("My intparam value is now %i", parameters, attributes);

Part of #1398

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions