Skip to content

Commit d61acdd

Browse files
vaindPlasmaDev5PlasmaDev5
authored
feat: expose function to send minidumps (#1067)
* feat: programmatic minidump capture This provides a new function that will allow for independently created minidumps to be captured by sentry Resolves: getsentry/sentry-native#1050 * fixed compile errors * Rework of programmatic minidumps based on feedback * Remove unused parameters * Address Lint errors * Address more review feedback * Address Lint errors * Address more lint errors * changed from bool to int due to undefined errors * Address review feedback * Work on addressing feedback, example and test * Fixes to lint errors * Apply comment suggestion * Add empty line to file end * use parameter directly * chore: fix changelog * add capture_minidump_n * feat: capture minidump from path * chore: update changelog * cleanup * linter issues * cleanup, review changes, docs * chore: fixup doc * Update CHANGELOG.md --------- Co-authored-by: PlasmaDev5 <dragpmCASTjosh@gmail.com> Co-authored-by: PlasmaDev5 <dragonCASTjosh@gmail.com>
1 parent ffdf6ed commit d61acdd

File tree

7 files changed

+110
-0
lines changed

7 files changed

+110
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased
44

5+
**Features**:
6+
7+
- Add `sentry_capture_minidump()` to capture independently created minidumps ([#1067](https://github.com/getsentry/sentry-native/pull/1067))
58

69
**Fixes**:
710

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,9 @@ if(SENTRY_BUILD_EXAMPLES)
582582
set_target_properties(sentry_example PROPERTIES FOLDER ${SENTRY_FOLDER})
583583
endif()
584584

585+
add_custom_command(TARGET sentry_example POST_BUILD
586+
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/minidump.dmp" "$<TARGET_FILE_DIR:sentry_example>/minidump.dmp")
587+
585588
add_test(NAME sentry_example COMMAND sentry_example)
586589
endif()
587590

examples/example.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,10 @@ main(int argc, char **argv)
428428
sentry_transaction_finish(tx);
429429
}
430430

431+
if (has_arg(argc, argv, "capture-minidump")) {
432+
sentry_capture_minidump("minidump.dmp");
433+
}
434+
431435
// make sure everything flushes
432436
sentry_close();
433437

include/sentry.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,16 @@ SENTRY_API sentry_user_consent_t sentry_user_consent_get(void);
13621362
*/
13631363
SENTRY_API sentry_uuid_t sentry_capture_event(sentry_value_t event);
13641364

1365+
/**
1366+
* Allows capturing independently created minidumps.
1367+
*
1368+
* This generates a fatal error event, includes the scope and attachments.
1369+
* If the event isn't dropped by a before-send hook, the minidump is attached
1370+
* and the event is sent.
1371+
*/
1372+
SENTRY_API void sentry_capture_minidump(const char *path);
1373+
SENTRY_API void sentry_capture_minidump_n(const char *path, size_t path_len);
1374+
13651375
/**
13661376
* Captures an exception to be handled by the backend.
13671377
*

src/sentry_core.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,3 +1174,60 @@ sentry_clear_crashed_last_run(void)
11741174
sentry__options_unlock();
11751175
return success ? 0 : 1;
11761176
}
1177+
1178+
void
1179+
sentry_capture_minidump(const char *path)
1180+
{
1181+
sentry_capture_minidump_n(path, sentry__guarded_strlen(path));
1182+
}
1183+
1184+
void
1185+
sentry_capture_minidump_n(const char *path, size_t path_len)
1186+
{
1187+
sentry_path_t *dump_path = sentry__path_from_str_n(path, path_len);
1188+
1189+
if (!dump_path) {
1190+
SENTRY_WARN(
1191+
"sentry_capture_minidump() failed due to null path to minidump");
1192+
return;
1193+
}
1194+
1195+
SENTRY_DEBUGF(
1196+
"Capturing minidump \"%" SENTRY_PATH_PRI "\"", dump_path->path);
1197+
1198+
sentry_value_t event = sentry_value_new_event();
1199+
sentry_value_set_by_key(
1200+
event, "level", sentry__value_new_level(SENTRY_LEVEL_FATAL));
1201+
1202+
SENTRY_WITH_OPTIONS (options) {
1203+
sentry_envelope_t *envelope
1204+
= sentry__prepare_event(options, event, NULL, true);
1205+
1206+
if (envelope) {
1207+
// the minidump is added as an attachment, with type
1208+
// `event.minidump`
1209+
sentry_envelope_item_t *item = sentry__envelope_add_from_path(
1210+
envelope, dump_path, "attachment");
1211+
if (item) {
1212+
sentry__envelope_item_set_header(item, "attachment_type",
1213+
sentry_value_new_string("event.minidump"));
1214+
1215+
sentry__envelope_item_set_header(item, "filename",
1216+
#ifdef SENTRY_PLATFORM_WINDOWS
1217+
sentry__value_new_string_from_wstr(
1218+
#else
1219+
sentry_value_new_string(
1220+
#endif
1221+
sentry__path_filename(dump_path)));
1222+
}
1223+
1224+
sentry__capture_envelope(options->transport, envelope);
1225+
1226+
SENTRY_DEBUGF("Minidump has been captured: \"%" SENTRY_PATH_PRI
1227+
"\"",
1228+
dump_path->path);
1229+
}
1230+
}
1231+
1232+
sentry__path_free(dump_path);
1233+
}

tests/fixtures/minidump.dmp

41.4 KB
Binary file not shown.

tests/test_integration_http.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import itertools
22
import json
33
import os
4+
import shutil
45
import time
56
import uuid
67

@@ -573,3 +574,35 @@ def test_transaction_only(cmake, httpserver, build_args):
573574
assert start_timestamp
574575
timestamp = time.strptime(payload["timestamp"], RFC3339_FORMAT)
575576
assert timestamp >= start_timestamp
577+
578+
579+
def test_capture_minidump(cmake, httpserver):
580+
tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "none"})
581+
582+
# make sure we are isolated from previous runs
583+
shutil.rmtree(tmp_path / ".sentry-native", ignore_errors=True)
584+
585+
httpserver.expect_oneshot_request(
586+
"/api/123456/envelope/",
587+
headers={"x-sentry-auth": auth_header},
588+
).respond_with_data("OK")
589+
590+
run(
591+
tmp_path,
592+
"sentry_example",
593+
["log", "attachment", "capture-minidump"],
594+
check=True,
595+
env=dict(os.environ, SENTRY_DSN=make_dsn(httpserver)),
596+
)
597+
598+
assert len(httpserver.log) == 1
599+
600+
req = httpserver.log[0][0]
601+
body = req.get_data()
602+
603+
envelope = Envelope.deserialize(body)
604+
605+
assert_breadcrumb(envelope)
606+
assert_attachment(envelope)
607+
608+
assert_minidump(envelope)

0 commit comments

Comments
 (0)