getsentry / sentry-native

Sentry SDK for C, C++ and native applications.
MIT License
403 stars 170 forks source link

When I use the sentry_set_context function inside the before_send callback function, it doesn't work #1053

Closed cr545l closed 1 month ago

cr545l commented 1 month ago

Description

sentry_value_t before_send(sentry_value_t event, void* hint, void* closure) 
{
    sentry_set_context("my_data2", my_data2); // ❌ NOT WORK
    return event;
}

void my_sentry_init(const char* release)
{
    sentry_options_t* options = sentry_options_new();
    sentry_options_set_before_send(options, before_send, NULL);
    sentry_set_context("my_data1", my_data1); // 🟢 WORK
}

I am able to access my_data in the function where the before_send callback is set. However, using sentry_set_context in that section doesn't work. Is this a bug? Is there a better approach?

When does the problem happen

Environment

Steps To Reproduce

Log output

supervacuus commented 1 month ago

No, this is not a bug. sentry_set_context() is a scope function, and scope functions are related to the "scopes" inside your application so that they can be applied to any event automatically when sent inside the scope.

sentry_set_context("my_context_data", my_context_data);

sentry_capture_event(event1); // event1 sent with "my_context_data" automatically applied
sentry_capture_event(event2); // event2 sent with "my_context_data" automatically applied

sentry_set_context("other_context_data", other_context_data);

sentry_capture_event(event3); // event3 sent with "my_context_data" and "other_context_data" automatically applied

The SDK invokes the before_send-hook after applying the scope to the event. This allows you to modify the event at the last moment before it is sent but after all automatic meta-data additions.

Calling sentry_set_context() inside the before_send hook will not affect the event currently being processed by the callback. If you must set a context inside the before_send callback, you can write directly to the event's "contexts" object using the value API. However, please keep in mind that this completely bypasses the scope mechanism, and with that, you capture contexts based on when an event is sent and no longer where it was sent from in your application.

limbonaut commented 1 month ago

@cr545l Workaround:

void SentryUtil::sentry_event_set_context(sentry_value_t p_event, const char *p_context_name, sentry_value_t p_context) {
       sentry_value_t contexts = sentry_value_get_by_key(p_event, "contexts");
    if (sentry_value_is_null(contexts)) {
        contexts = sentry_value_new_object();
        sentry_value_set_by_key(p_event, "contexts", contexts);
    }
    sentry_value_set_by_key(contexts, p_context_name, p_context);
}
cr545l commented 1 month ago

@limbonaut Thank you, it works well