Skip to content
Draft
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 @@ -9,6 +9,7 @@
**Features**:

- Provide Clang-CL support. ([#1161](https://github.com/getsentry/sentry-native/pull/1161), [crashpad#100](https://github.com/getsentry/crashpad/pull/100))
- Add `before_breadcrumb` hook ([#1166](https://github.com/getsentry/sentry-native/pull/1166))

**Thank you**:

Expand Down
35 changes: 35 additions & 0 deletions examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,31 @@ on_crash_callback(
return event;
}

static sentry_value_t
before_breadcrumb_callback(sentry_value_t breadcrumb, void *hint, void *closure)
{
(void)hint;
(void)closure;

// make our mark on the breadcrumbs
sentry_value_set_by_key(
breadcrumb, "category", sentry_value_new_string("before_breadcrumb"));

return breadcrumb;
}

static sentry_value_t
discarding_before_breadcrumb_callback(
sentry_value_t breadcrumb, void *hint, void *closure)
{
(void)hint;
(void)closure;

// discard breadcrumb
sentry_value_decref(breadcrumb);
return sentry_value_new_null();
}

static void
print_envelope(sentry_envelope_t *envelope, void *unused_state)
{
Expand Down Expand Up @@ -260,6 +285,16 @@ main(int argc, char **argv)
options, discarding_on_crash_callback, NULL);
}

if (has_arg(argc, argv, "before-breadcrumb")) {
sentry_options_set_before_breadcrumb(
options, before_breadcrumb_callback, NULL);
}

if (has_arg(argc, argv, "discarding-before-breadcrumb")) {
sentry_options_set_before_breadcrumb(
options, discarding_before_breadcrumb_callback, NULL);
}

if (has_arg(argc, argv, "traces-sampler")) {
sentry_options_set_traces_sampler(options, traces_sampler_callback);
}
Expand Down
22 changes: 22 additions & 0 deletions include/sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,28 @@ typedef sentry_value_t (*sentry_crash_function_t)(
SENTRY_API void sentry_options_set_on_crash(
sentry_options_t *opts, sentry_crash_function_t func, void *data);

/**
* Type of the `on_breadcrumb` callback.
*
* This function is called with a breadcrumb before it is added to be sent
* in case of an event.
*
* The callback takes ownership of the `breadcrumb`, and
* should usually return that same breadcrumb. In case the breadcrumb should be
* discarded, the callback needs to call `sentry_value_decref` on the provided
* breadcrumb, and return a `sentry_value_new_null()` instead.
*/
typedef sentry_value_t (*sentry_breadcrumb_function_t)(
sentry_value_t breadcrumb, void *hint, void *closure);

/**
* Sets the `sentry_options_set_before_breadcrumb` callback.
*
* See the `sentry_breadcrumb_function_t` typedef above for more information.
*/
SENTRY_API void sentry_options_set_before_breadcrumb(
sentry_options_t *opts, sentry_breadcrumb_function_t func, void *data);

/**
* Sets the DSN.
*/
Expand Down
11 changes: 11 additions & 0 deletions src/sentry_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,17 @@ sentry_add_breadcrumb(sentry_value_t breadcrumb)
{
size_t max_breadcrumbs = SENTRY_BREADCRUMBS_MAX;
SENTRY_WITH_OPTIONS (options) {
if (options->on_breadcrumb_func) {
SENTRY_DEBUG("invoking `before_breadcrumb` hook");
breadcrumb = options->on_breadcrumb_func(
breadcrumb, NULL, options->on_breadcrumb_data);
if (sentry_value_is_null(breadcrumb)) {
sentry_value_decref(breadcrumb);
SENTRY_DEBUG(
"breadcrumb was discarded by the `before_breadcrumb` hook");
return;
}
}
if (options->backend && options->backend->add_breadcrumb_func) {
// the hook will *not* take ownership
options->backend->add_breadcrumb_func(
Expand Down
8 changes: 8 additions & 0 deletions src/sentry_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ sentry_options_set_on_crash(
opts->on_crash_data = data;
}

void
sentry_options_set_before_breadcrumb(
sentry_options_t *opts, sentry_breadcrumb_function_t func, void *data)
{
opts->on_breadcrumb_func = func;
opts->on_breadcrumb_data = data;
}

void
sentry_options_set_dsn_n(
sentry_options_t *opts, const char *raw_dsn, size_t raw_dsn_len)
Expand Down
2 changes: 2 additions & 0 deletions src/sentry_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ struct sentry_options_s {
void *before_send_data;
sentry_crash_function_t on_crash_func;
void *on_crash_data;
sentry_breadcrumb_function_t on_breadcrumb_func;
void *on_breadcrumb_data;

/* Experimentally exposed */
double traces_sample_rate;
Expand Down
11 changes: 11 additions & 0 deletions tests/assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,17 @@ def assert_no_before_send(envelope):
assert ("adapted_by", "before_send") not in event.items()


def assert_before_breadcrumb(envelope):
event = envelope.get_event()
breadcrumbs = event["breadcrumbs"]
assert all(b["category"] == "before_breadcrumb" for b in breadcrumbs)


def assert_discarding_before_breadcrumb(envelope):
event = envelope.get_event()
assert event["breadcrumbs"] == []


@dataclass(frozen=True)
class CrashpadAttachments:
event: dict
Expand Down
50 changes: 50 additions & 0 deletions tests/test_integration_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
assert_attachment,
assert_meta,
assert_breadcrumb,
assert_before_breadcrumb,
assert_discarding_before_breadcrumb,
assert_stacktrace,
assert_event,
assert_exception,
Expand Down Expand Up @@ -179,6 +181,54 @@ def test_user_feedback_http(cmake, httpserver):
assert_user_feedback(envelope)


def test_before_breadcrumb_http(cmake, httpserver):
tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "none"})

httpserver.expect_request(
"/api/123456/envelope/",
headers={"x-sentry-auth": auth_header},
).respond_with_data("OK")
env = dict(os.environ, SENTRY_DSN=make_dsn(httpserver))

run(
tmp_path,
"sentry_example",
["log", "before-breadcrumb", "capture-event"],
check=True,
env=env,
)

assert len(httpserver.log) == 1
output = httpserver.log[0][0].get_data()
envelope = Envelope.deserialize(output)

assert_before_breadcrumb(envelope)


def test_discarding_before_breadcrumb_http(cmake, httpserver):
tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "none"})

httpserver.expect_request(
"/api/123456/envelope/",
headers={"x-sentry-auth": auth_header},
).respond_with_data("OK")
env = dict(os.environ, SENTRY_DSN=make_dsn(httpserver))

run(
tmp_path,
"sentry_example",
["log", "discarding-before-breadcrumb", "capture-event"],
check=True,
env=env,
)

assert len(httpserver.log) == 1
output = httpserver.log[0][0].get_data()
envelope = Envelope.deserialize(output)

assert_discarding_before_breadcrumb(envelope)


def test_exception_and_session_http(cmake, httpserver):
tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "none"})

Expand Down
28 changes: 28 additions & 0 deletions tests/unit/test_basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,34 @@ SENTRY_TEST(discarding_before_send)
TEST_CHECK_INT_EQUAL(called_beforesend, 1);
}

static sentry_value_t
before_breadcrumb(sentry_value_t breadcrumb, void *UNUSED(hint), void *data)
{
uint64_t *called = data;
*called += 1;

return breadcrumb;
}

SENTRY_TEST(calling_before_breadcrumb)
{
uint64_t called_before_breadcrumb = 0;

SENTRY_TEST_OPTIONS_NEW(options);
sentry_options_set_dsn(options, "https://[email protected]/42");
sentry_options_set_before_breadcrumb(
options, before_breadcrumb, &called_before_breadcrumb);
sentry_init(options);

sentry_add_breadcrumb(sentry_value_new_breadcrumb("foo", "bar"));
sentry_add_breadcrumb(sentry_value_new_breadcrumb("error", "app failed"));
sentry_add_breadcrumb(sentry_value_new_breadcrumb("spam", "hello world"));

sentry_close();

TEST_CHECK_INT_EQUAL(called_before_breadcrumb, 3);
}

SENTRY_TEST(crash_marker)
{
SENTRY_TEST_OPTIONS_NEW(options);
Expand Down
1 change: 1 addition & 0 deletions tests/unit/tests.inc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ XX(basic_write_envelope_to_file)
XX(bgworker_flush)
XX(breadcrumb_without_type_or_message_still_valid)
XX(build_id_parser)
XX(calling_before_breadcrumb)
XX(capture_minidump_basic)
XX(capture_minidump_invalid_path)
XX(capture_minidump_null_path)
Expand Down
Loading