You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Introduces report_unhandled_exception API for runtime-detected crashes (unhandled exceptions, errors) that are not triggered by OS signals
NOTICE: currently, the exception stack is put in the experimental field. This is a bit counter intuitive since it feels like the exception stack is being put somewhere where people won't look at first, but it is planned to make runtime stacks a first class citizen for crash reports, so this field will be surfaced upwards soon (this quarter)
Overview
This feature allows language runtimes (Ruby, Python, etc.) to report crashes detected at the runtime level, such as unhandled exceptions, through the existing crashtracker infrastructure. The runtime calls a single API, providing the error type, message, and a stack trace. libdatadog then handles the full data collection flow: native unwinding, profiler state (counters, spans, traces), process info, /proc/self/maps, and formatting/uploading via the receiver.
The crash report message is formatted as: Process was terminated due to an unhandled exception of type '{error_type}'. Message: "{error_message}"
The runtime-provided stack goes into experimental.runtime_stack, while the native backtrace captured by libdatadog goes into error.stack. No sig_info or ucontext is collected since no signal is involved.
Prerequisite: The application must have already called ddog_crasht_init() to prime the crashtracker for signal-based crash tracking. This API reuses the stored config, metadata, and receiver configuration.
What was existing that changed
Receiver protocol: Added DD_CRASHTRACK_BEGIN_ERROR_KIND / DD_CRASHTRACK_END_ERROR_KIND block. The receiver now parses an explicit error kind from the collector instead of hardcoding UnixSignal. Old receivers gracefully ignore the new block and default to UnixSignal (backward compatible).
No collector fork: Unlike the signal path which forks a collector child (signal handler constraints), this path writes directly to the receiver socket from normal execution context.
Crash ping readiness: is_ping_ready() now accepts error.kind.is_some() as an alternative to sig_info.is_some(), so crash pings fire for unhandled exception reports too.
Backtrace helper: Extracted emit_absolute_addresses_for_frame() as a shared helper used by both the signal-path and caller-path backtrace emitters.
FFI usage example
// Prerequisite: crashtracker must already be initialized via ddog_crasht_init()// 1. Build the runtime stack traceddog_crasht_StackTraceNewResultstack_result=ddog_crasht_StackTrace_new();
// check stack_result...ddog_Handle_StackTrace*stack=&stack_result.ok;
ddog_crasht_StackFrameNewResultframe_result=ddog_crasht_StackFrame_new();
ddog_Handle_StackFrame*frame=&frame_result.ok;
ddog_crasht_StackFrame_with_function(frame, DDOG_CHARSLICE_C("MyApp.handleRequest"));
ddog_crasht_StackFrame_with_file(frame, DDOG_CHARSLICE_C("app.rb"));
ddog_crasht_StackFrame_with_line(frame, 42);
ddog_crasht_StackTrace_push_frame(stack, frame, false);
// 2. Report the unhandled exceptionddog_VoidResultresult=ddog_crasht_report_unhandled_exception(
DDOG_CHARSLICE_C("RuntimeError"), // error_typeDDOG_CHARSLICE_C("something went wrong"), // error_messagestack// runtime_stack (consumed)
);
Current API requires runtimes to manually extract all this information and send the ping/report, which is all work that can be done on the libdatadog side.
Additional Notes
Anything else we should know when reviewing?
How to test the change?
Describe here in detail how the change can be validated.
This report tracks Clippy allow annotations for specific rules, showing how they've changed in this PR. Decreasing the number of these annotations generally improves code quality.
gyuheon0h
changed the title
Implement interface for runtimes to report unhandlex exception
feat(crashtracking)!: add interface for runtimes to report unhandled exception
Feb 13, 2026
gyuheon0h
changed the title
feat(crashtracking)!: add interface for runtimes to report unhandled exception
feat(crashtracking): add interface for runtimes to report unhandled exception
Feb 13, 2026
❌ Patch coverage is 56.01173% with 150 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.89%. Comparing base (34a9f1c) to head (3d82593). ⚠️ Report is 6 commits behind head on main.
The reason will be displayed to describe this comment to others. Learn more.
Good point
I am capturing the native stack trace, since we can capture that information anyways
I am putting the runtime stacks in the experimental section, because that is where runtime stacks go currently, vs native stack.
However, I think we should move the runtime stack section to error. Feels like we should have both native and runtime stacks in the error, since both should be supported as first class citizens soon.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
TLDR
report_unhandled_exceptionAPI for runtime-detected crashes (unhandled exceptions, errors) that are not triggered by OS signalsNOTICE: currently, the exception stack is put in the experimental field. This is a bit counter intuitive since it feels like the exception stack is being put somewhere where people won't look at first, but it is planned to make runtime stacks a first class citizen for crash reports, so this field will be surfaced upwards soon (this quarter)
Overview
This feature allows language runtimes (Ruby, Python, etc.) to report crashes detected at the runtime level, such as unhandled exceptions, through the existing crashtracker infrastructure. The runtime calls a single API, providing the error type, message, and a stack trace. libdatadog then handles the full data collection flow: native unwinding, profiler state (counters, spans, traces), process info,
/proc/self/maps, and formatting/uploading via the receiver.The crash report message is formatted as:
Process was terminated due to an unhandled exception of type '{error_type}'. Message: "{error_message}"The runtime-provided stack goes into
experimental.runtime_stack, while the native backtrace captured by libdatadog goes intoerror.stack. Nosig_infoorucontextis collected since no signal is involved.Prerequisite: The application must have already called
ddog_crasht_init()to prime the crashtracker for signal-based crash tracking. This API reuses the stored config, metadata, and receiver configuration.What was existing that changed
DD_CRASHTRACK_BEGIN_ERROR_KIND/DD_CRASHTRACK_END_ERROR_KINDblock. The receiver now parses an explicit error kind from the collector instead of hardcodingUnixSignal. Old receivers gracefully ignore the new block and default toUnixSignal(backward compatible).is_ping_ready()now acceptserror.kind.is_some()as an alternative tosig_info.is_some(), so crash pings fire for unhandled exception reports too.emit_absolute_addresses_for_frame()as a shared helper used by both the signal-path and caller-path backtrace emitters.FFI usage example
Example output
Motivation
Current API requires runtimes to manually extract all this information and send the ping/report, which is all work that can be done on the libdatadog side.
Additional Notes
Anything else we should know when reviewing?
How to test the change?
Describe here in detail how the change can be validated.