Skip to content

Local scopes #1226

@jpnurmi

Description

@jpnurmi

We would like to add support for local scopes for the needs of downstream SDKs (sentry-unreal).

API proposal for capturing events with local scopes, inspired by other Sentry SDKs:

sentry_uuid_t sentry_capture_event_with_scope(sentry_value_t event, sentry_scope_callback_t callback, void *userdata)
  • Clones the current scope and pushes it on a (thread-local?) stack
  • Calls the scope configuration callback
    typedef void (*sentry_scope_callback_t)(sentry_scope_t *scope, void *userdata)
  • Flushes the local scope
  • Captures the event
  • Discards the local scope

Ideally, GenericPlatformSentryScope in sentry-unreal would be a thin wrapper around an opaque sentry_scope_t*. To achieve this, sentry-native could expose getters and setters for all the data stored in the scope:

typedef struct sentry_scope_s {
    char *transaction;
    sentry_value_t fingerprint;
    sentry_value_t user;
    sentry_value_t tags;
    sentry_value_t extra;
    sentry_value_t contexts;
    sentry_value_t breadcrumbs;
    sentry_level_t level;
    sentry_value_t client_sdk;
    sentry_transaction_t *transaction_object;
    sentry_span_t *span;
} sentry_scope_t;
  • transaction
    const char *sentry_scope_get_transaction(const sentry_scope_t *scope);
    void sentry_scope_set_transaction(sentry_scope_t *scope, const char *transaction); // + _n
  • fingerprint
    sentry_value_t sentry_scope_get_fingerprint(const sentry_scope_t *scope);
    void sentry_scope_set_fingerprint(sentry_scope_t *scope, const char *fingerprint, ...); // + _n
    void sentry_scope_remove_fingerprint(sentry_scope_t *scope);
  • user
    sentry_value_t sentry_scope_get_user(const sentry_scope_t *scope);
    void sentry_scope_set_user(sentry_scope_t *scope, sentry_value_t user);
    void sentry_scope_remove_user(sentry_scope_t *scope);
  • tags
    const char *sentry_scope_get_tag(const sentry_scope_t *scope, const char *key);
    void sentry_scope_set_tag(sentry_scope_t *scope, const char *key, const char *value); // + _n
    void sentry_scope_remove_tag(sentry_scope_t *scope, const char *key); // + _n
    sentry_value_t sentry_scope_get_tags(const sentry_scope_t *scope)
    void sentry_scope_set_tags(sentry_scope_t *scope, sentry_value_t tags)
  • extras
    sentry_value_t sentry_scope_get_extra(const sentry_scope_t *scope, const char *key);
    void sentry_scope_set_extra(sentry_scope_t *scope, const char *key, sentry_value_t value); // + _n
    void sentry_scope_remove_extra(sentry_scope_t *scope, const char *key); // + _n
    sentry_value_t sentry_scope_get_extras(const sentry_scope_t *scope);
    void sentry_scope_set_extras(sentry_scope_t *scope, sentry_value_t extras);
  • contexts
    sentry_value_t sentry_scope_get_context(const sentry_scope_t *scope, const char *key);
    void sentry_scope_set_context(sentry_scope_t *scope, const char *key, sentry_value_t value); // + _n
    void sentry_scope_remove_context(sentry_scope_t *scope, const char *key); // + _n
    sentry_value_t sentry_scope_get_contexts(const sentry_scope_t *scope);
    void sentry_scope_set_contexts(sentry_scope_t *scope, sentry_value_t contexts);
  • breadcrumbs
    void sentry_scope_add_breadcrumb(sentry_scope_t *scope, sentry_value_t breadcrumb);
    void sentry_scope_clear_breadcrumbs(sentry_scope_t *scope);
  • attachments (TODO feat: Support modifying attachments after init #433)
  • level
    sentry_level_t sentry_scope_get_level(const sentry_scope_t *scope);
    void sentry_scope_set_level(sentry_scope_t *scope, sentry_level_t level);
  • other
    void sentry_scope_clear(sentry_scope_t *scope);

Open questions

  • should transaction_object and span be cloned?
  • add dist for FGenericPlatformSentryScope::Get/SetDist?
  • add environment for FGenericPlatformSentryScope::Get/SetEnvironment?

With all this in place, the implementation of CaptureEventWithScope in sentry-unreal could look something along the lines of:

TSharedPtr<ISentryId> FGenericPlatformSentrySubsystem::CaptureEventWithScope(TSharedPtr<ISentryEvent> event, const FSentryScopeDelegate& onScopeConfigure)
{
	FScopeLock Lock(&CriticalSection);

	sentry_value_t nativeEvent = Event->GetNativeObject();

	sentry_uuid_t id = sentry_capture_event_with_scope(nativeEvent, [](sentry_scope_t *scope, void *userdata) {
		TSharedPtr<FGenericPlatformSentryScope> NewLocalScope = MakeShareable(new FGenericPlatformSentryScope(scope));
		const FSentryScopeDelegate *onScopeConfigure = static_cast<const FSentryScopeDelegate *>(userdata);
		onScopeConfigure->ExecuteIfBound(NewLocalScope);
	}, &onScopeConfigure);

	return MakeShareable(new FGenericPlatformSentryId(id));
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status

    Needs Discussion

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions