Skip to content

Commit

Permalink
feat: capture minidump from path
Browse files Browse the repository at this point in the history
  • Loading branch information
vaind committed Oct 31, 2024
1 parent 67bd3af commit 7e56ee4
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 77 deletions.
7 changes: 2 additions & 5 deletions examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#ifdef SENTRY_PLATFORM_WINDOWS
# include <malloc.h>
# include <synchapi.h>
# define sleep_s(SECONDS) Sleep((SECONDS)*1000)
# define sleep_s(SECONDS) Sleep((SECONDS) * 1000)
#else

# include <signal.h>
Expand Down Expand Up @@ -429,10 +429,7 @@ main(int argc, char **argv)
}

if (has_arg(argc, argv, "capture-minidump")) {
sentry_value_t event = sentry_value_new_message_event(
SENTRY_LEVEL_INFO, "my-logger", "Hello Minidump!");
sentry_capture_minidump("minidump.dmp", event, 0);
sentry_capture_event(event);
sentry_capture_minidump("minidump.dmp");
}

// make sure everything flushes
Expand Down
7 changes: 3 additions & 4 deletions include/sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -1365,10 +1365,9 @@ SENTRY_API sentry_uuid_t sentry_capture_event(sentry_value_t event);
/**
* Allows capturing independently created minidumps.
*/
SENTRY_API void sentry_capture_minidump(
const char *dump_path, sentry_value_t event, int remove_dump_on_send);
SENTRY_API void sentry_capture_minidump_n(const char *dump_path,
size_t dump_path_len, sentry_value_t event, int remove_dump_on_send);
SENTRY_API void sentry_capture_minidump(const char *dump_path);
SENTRY_API void sentry_capture_minidump_n(
const char *dump_path, size_t dump_path_len);

/**
* Captures an exception to be handled by the backend.
Expand Down
66 changes: 24 additions & 42 deletions src/sentry_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "sentry_tracing.h"
#include "sentry_transport.h"
#include "sentry_value.h"
#include "transports/sentry_disk_transport.h"

#ifdef SENTRY_INTEGRATION_QT
# include "integrations/sentry_integration_qt.h"
Expand Down Expand Up @@ -1176,55 +1177,37 @@ sentry_clear_crashed_last_run(void)
}

void
sentry_capture_minidump(
const char *dump_path, sentry_value_t event, int remove_dump_on_send)
sentry_capture_minidump(const char *dump_path)
{
sentry_capture_minidump_n(dump_path, sentry__guarded_strlen(dump_path),
event, remove_dump_on_send);
sentry_capture_minidump_n(dump_path, sentry__guarded_strlen(dump_path));
}

void
sentry_capture_minidump_n(const char *dump_path, size_t dump_path_len,
sentry_value_t event, int remove_dump_on_send)
sentry_capture_minidump_n(const char *dump_path_str, size_t dump_path_len)
{
sentry_path_t *sentry_dump_path
= sentry__path_from_str_n(dump_path, dump_path_len);
sentry_path_t *dump_path
= sentry__path_from_str_n(dump_path_str, dump_path_len);

if (sentry_dump_path == NULL) {
if (dump_path == NULL) {
SENTRY_WARN(
"sentry_capture_minidump() failed due to null path to minidump");
return;
}

SENTRY_WITH_OPTIONS (options) {
sentry__ensure_event_id(event, NULL);
sentry_envelope_t *envelope = sentry__envelope_new();
if (!envelope || !sentry__envelope_add_event(envelope, event)) {
sentry_envelope_free(envelope);
sentry_value_decref(event);
sentry__path_free(sentry_dump_path);
return;
}
SENTRY_DEBUGF(
"Capturing minidump \"%" SENTRY_PATH_PRI "\"", dump_path->path);

SENTRY_TRACE("adding attachments to envelope");
for (sentry_attachment_t *attachment = options->attachments; attachment;
attachment = attachment->next) {
sentry_envelope_item_t *item = sentry__envelope_add_from_path(
envelope, attachment->path, "attachment");
if (!item) {
continue;
}
sentry__envelope_item_set_header(item, "filename",
#ifdef SENTRY_PLATFORM_WINDOWS
sentry__value_new_string_from_wstr(
#else
sentry_value_new_string(
#endif
sentry__path_filename(attachment->path)));
}
sentry_value_t event = sentry_value_new_event();
sentry_value_set_by_key(
event, "level", sentry__value_new_level(SENTRY_LEVEL_FATAL));

sentry_envelope_item_t *item = sentry__envelope_add_from_path(
envelope, sentry_dump_path, "attachment");
SENTRY_WITH_OPTIONS (options) {
sentry_envelope_t *envelope
= sentry__prepare_event(options, event, NULL, true);

// the minidump is added as an attachment, with type `event.minidump`
sentry_envelope_item_t *item
= sentry__envelope_add_from_path(envelope, dump_path, "attachment");
if (item) {
sentry__envelope_item_set_header(item, "attachment_type",
sentry_value_new_string("event.minidump"));
Expand All @@ -1235,15 +1218,14 @@ sentry_capture_minidump_n(const char *dump_path, size_t dump_path_len,
#else
sentry_value_new_string(
#endif
sentry__path_filename(sentry_dump_path)));
sentry__path_filename(dump_path)));
}

sentry__capture_envelope(options->transport, envelope);
}

if (remove_dump_on_send) {
sentry__path_remove(sentry_dump_path);
}
SENTRY_DEBUGF("Minidump has been captured: \"%" SENTRY_PATH_PRI "\"",
dump_path->path);

sentry__path_free(sentry_dump_path);
}
sentry__path_free(dump_path);
}
40 changes: 14 additions & 26 deletions tests/test_capture_minidump.py
Original file line number Diff line number Diff line change
@@ -1,64 +1,52 @@
import itertools
import json
import os
import time
import uuid
import shutil

import pytest

from . import make_dsn, run, Envelope
from .assertions import (
assert_attachment,
assert_meta,
assert_breadcrumb,
assert_stacktrace,
assert_event,
assert_exception,
assert_inproc_crash,
assert_session,
assert_user_feedback,
assert_minidump,
assert_breakpad_crash,
assert_gzip_content_encoding,
assert_gzip_file_header,
)
from .conditions import has_http, has_breakpad, has_files
from .conditions import has_http

pytestmark = pytest.mark.skipif(not has_http, reason="tests need http")

# fmt: off
auth_header = (
"Sentry sentry_key=uiaeosnrtdy, sentry_version=7, sentry_client=sentry.native/0.7.10"
"Sentry sentry_key=uiaeosnrtdy, sentry_version=7, sentry_client=sentry.native/0.7.11"
)
# fmt: on

def test_capture_minidump(cmake, httpserver, build_args):
build_args.update({"SENTRY_BACKEND": "none"})
tmp_path = cmake(["sentry_example"], build_args)

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

# make sure we are isolated from previous runs
shutil.rmtree(tmp_path / ".sentry-native", ignore_errors=True)

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

run(
tmp_path,
"sentry_example",
["log", "release-env", "capture-minidump"],
["log", "attachment", "capture-minidump"],
check=True,
env=env,
env=dict(os.environ, SENTRY_DSN=make_dsn(httpserver)),
)

assert len(httpserver.log) == 1

req = httpserver.log[0][0]
body = req.get_data()

envelope = Envelope.deserialize(body)

assert_meta(envelope, "🤮🚀")
assert_breadcrumb(envelope)
assert_stacktrace(envelope)
assert_attachment(envelope)

assert_event(envelope)

assert_minidump(envelope)

0 comments on commit 7e56ee4

Please sign in to comment.