Native

The Sentry Native SDK is intended for C and C++. However, since it builds as a dynamic library and exposes C-bindings, it can be used by any language that supports interoperability with C, such as the Foreign Function Interface (FFI).

Sentry also offers higher-level SDKs for platforms with built-in support for native crashes:

In case you would like to use Sentry with a third-party framework directly without using the Native SDK, see the following resources:

The Sentry Native SDK has built-in support for both Google Breakpad and Google Crashpad, see the Integrations below.

Integrating the SDK

The Native SDK currently supports Windows, macOS, Linux, and Android.

Building the SDK

To build the SDK, download the latest release of the SDK from the Releases page. The SDK is managed as a CMake project, which additionally supports several configuration options, such as the backend to use.

For example, CMake can be used like this (on macOS):

Copied
# configure the cmake build into the `build` directory, with crashpad (on macOS)
$ cmake -B build -D SENTRY_BACKEND=crashpad
# build the project
$ cmake --build build --parallel
# install the resulting artifacts into a specific prefix
$ cmake --install build --prefix install
# which will result in the following (on macOS):
$ exa --tree install
install
├── bin
│  └── crashpad_handler
├── include
│  └── sentry.h
└── lib
   ├── libsentry.dylib
   └── libsentry.dylib.dSYM

Connecting the SDK to Sentry

After completing the project setup in Sentry, it shows the Data Source Name (DSN). It looks similar to a standard URL, and contains all configuration for the SDK.

Import and initialize the Sentry SDK early in your application setup:

Copied
#include <sentry.h>

int main(void) {
  sentry_options_t *options = sentry_options_new();
  sentry_options_set_dsn(options, "PUBLIC_DSN");
  sentry_init(options);

  /* ... */

  // make sure everything flushes
  sentry_shutdown();
}

Alternatively, the DSN can be passed as SENTRY_DSN environment variable during runtime. This can be especially useful for server applications.

Verifying Your Setup

Now that SDK setup is complete, verify that all configuration is correct. Start by capturing a manual event:

Copied
sentry_capture_event(sentry_value_new_message_event(
  /*   level */ SENTRY_LEVEL_INFO,
  /*  logger */ "custom",
  /* message */ "It works!"
));

Once the event is captured, it will show up on the Sentry dashboard.

Capturing Events

The Native SDK exposes a Value API to construct values like Exceptions, User objects, Tags, and even entire Events. There are several ways to create an event.

Manual Events

To create and capture a manual event, follow these steps:

  1. Create an event value using sentry_value_new_event. This internally creates an object value and initializes it with common event attributes, like a timestamp and event_id.
  2. Add custom attributes to the event, like a message or an exception.
  3. Send the event to Sentry by invoking sentry_capture_event.

In a more complex example, it looks like this:

Copied
sentry_value_t event = sentry_value_new_event();
sentry_value_set_by_key(event, "message", sentry_value_new_string("Hello!"));

sentry_value_t screen = sentry_value_new_object();
sentry_value_set_by_key(screen, "width", sentry_value_new_int32(1920));
sentry_value_set_by_key(screen, "height", sentry_value_new_int32(1080));

sentry_value_t extra = sentry_value_new_object();
sentry_value_set_by_key(extra, "screen_size", screen);

sentry_value_set_by_key(event, "extra", extra);
sentry_capture_event(event);

For the full list of supported values, see Event Payloads and linked documents.

Exceptions

To capture an error or exception condition, create events containing an exception object. It needs to contain at least a value and type:

Copied
#include <sentry.h>

sentry_value_t exc = sentry_value_new_object();
sentry_value_set_by_key(exc, "type", sentry_value_new_string("Exception"));
sentry_value_set_by_key(exc, "value", sentry_value_new_string("Error message."));

sentry_value_t event = sentry_value_new_event();
sentry_value_set_by_key(event, "exception", exc);
sentry_capture_event(event);

This exception does not contain a stack trace, which must be added separately.

Message Events

To simplify creating events, there are shorthand functions that construct prepopulated event objects. The most important one is sentry_value_new_message_event. The logger and message parameters are each optional.

Copied
sentry_value_t event = sentry_value_new_message_event(
  /*   level */ SENTRY_LEVEL_INFO,
  /*  logger */ "custom",
  /* message */ "It works!"
);

Application Crashes

By default, the Native SDK intercepts crash signals and unhandled exceptions to send crash reports to Sentry. Depending on the backend, the crash report can be sent as a conventional event or as a native crash report file. On Windows, Linux, and macOS, the default backends send binary Minidump files. Sentry processes them to extract stack traces and exception information into a readable crash report.

For more information on Minidumps and the limits that apply, see What is a Minidump.

Uploading Debug Information

To allow Sentry to fully process native crashes and provide you with symbolicated stack traces, you need to upload Debug Information Files (sometimes also referred to as Debug Symbols or just Symbols). We recommend uploading debug information during your build or release process.

For all libraries where you'd like to receive symbolication, you need to provide debug information. This includes dependencies and operating system libraries. If you are not sure which files are required, go to Project Settings > Processing Issues, which shows a list of all the necessary files and instructions to retrieve them.

In addition to Debug Information Files, Sentry needs Call Frame Information (CFI) to extract accurate stack traces from minidumps of optimized release builds. CFI is usually part of the executables and not copied to debug symbols. Unless you are uploading Breakpad symbols, be sure to also include the binaries when uploading files to Sentry.

For more information on uploading debug information and their supported formats, see Debug Information Files.

Releases

A release is a version of your code that you deploy to an environment. When you give Sentry information about your releases, you unlock many new features:

  • Determine the issue and regressions introduced in a new release
  • Predict which commit caused an issue and who is likely responsible
  • Resolve issues by including the issue number in your commit message
  • Receive email notifications when your code gets deployed

After configuring your SDK, setting up releases is a 2-step process:

  1. Create Release and Associate Commits
  2. Tell Sentry When You Deploy a Release

For more information, see Releases Are Better With Commits.

To configure the SDK to send release information, set the release during initialization:

Copied
  sentry_options_t *options = sentry_options_new();
  sentry_options_set_release(options, "my-unique-release-1.0.0");

Release Health

Monitor the health of releases by observing user adoption, usage of the application, percentage of crashes, and session data. Release health will provide insight into the impact of crashes and bugs as it relates to user experience, and reveal trends with each new issue through the release details, graphs, and filters.

To benefit from the health data, you must use at least version 0.4.0 of the Native SDK. Metrics collection for release health is, by default, enabled, unless you specifically disabled collecting in the initialization options for the SDK.

Copied
sentry_options_t *options = sentry_options_new();
// Session tracking is enabled by default. To disable:
sentry_options_set_auto_session_tracking(options, 0);
sentry_init(options);

The SDK automatically starts a new session when it is initialized via sentry_init, and will end that session automatically when the SDK is shut down via sentry_shutdown, or explicitly by calling sentry_end_session. The SDK currently tracks only one concurrent session and will end the running session when using sentry_start_session.

For more details, see the full documentation on Release Health.

Identification of the User

By default, the SDK will try to use the id, email, or username properties of the object set via sentry_set_user as the session’s distinct identifier. While this ID contains personally identifiable information, and is transmitted to the sentry backend, the ID will not persist server-side.

Known Limitations

When using the Crashpad backend on macOS, the duration and status of crashes sessions can not be reliably determined, and may be classified as abnormal exits instead.

Context

Sentry supports additional context with events. Often this context is shared among any issue captured in its lifecycle, and includes the following components:

Structured Contexts
Structured contexts are typically set automatically.

User
Information about the current actor.

Tags
Key/value pairs which generate breakdown charts and search filters.

Level
An event's severity.

Fingerprint
A value used for grouping events into issues.

Unstructured Extra Data
Arbitrary unstructured data which the Sentry SDK stores with an event sample.

Context information is attached to every event until explicitly removed or overwritten.

Extra Context

In addition to the structured contexts that Sentry understands, you can send arbitrary key/value pairs of data which the Sentry SDK will store alongside the event. These are not indexed, and the Sentry SDK uses them to add additional information about what might be happening.

sentry_set_extra takes the name of the extra value as first parameter, and the value as sentry_value_t as second parameter:

Copied
sentry_value_t screen = sentry_value_new_object();
sentry_value_set_by_key(screen, "width", sentry_value_new_int32(1920));
sentry_value_set_by_key(screen, "height", sentry_value_new_int32(1080));
sentry_set_extra("screen_size", screen);

Capturing the User

Sending users to Sentry will unlock many features, primarily the ability to drill down into the number of users affecting an issue, as well as to get a broader sense about the quality of the application.

Copied
sentry_value_t user = sentry_value_new_object();
sentry_value_set_by_key(user, "id", sentry_value_new_int32(42));
sentry_value_set_by_key(user, "username", sentry_value_new_string("John Doe"));
sentry_set_user(user);

Users consist of a few critical pieces of information which are used to construct a unique identity in Sentry. Each of these is optional, but one must be present for the Sentry SDK to capture the user:

id
Your internal identifier for the user.

username
The user's username. Generally used as a better label than the internal ID.

email
An alternative, or addition, to a username. Sentry is aware of email addresses and can show things like Gravatars, unlock messaging capabilities, and more.

ip_address
The IP address of the user. If the user is unauthenticated, providing the IP address will suggest that this is unique to that IP. If available, we will attempt to pull this from the HTTP request data.

Additionally, you can provide arbitrary key/value pairs beyond the reserved names, and the Sentry SDK will store those with the user.

Tagging Events

Tags are key/value pairs assigned to events that can be used for breaking down issues or quick access to finding related events.

Copied
sentry_set_tag("server_name", "caroline");

For more information, see the Tagging Events section in Context.

Setting the Level

You can set the severity of an event to one of five values (sorted from most severe to least severe): fatal, error, warning, info, and debug. The default level is error.

Copied
sentry_set_level(SENTRY_LEVEL_WARNING);

Setting the Fingerprint

Sentry uses a fingerprint to decide how to group errors into issues.

For some very advanced use cases, you can override the Sentry default grouping using the fingerprint attribute. In supported SDKs, this attribute can be passed with the event information and should be an array of strings.

If you wish to append information, thus making the grouping slightly less aggressive, you can do that as well by adding the special string {{default}} as one of the items.

For code samples, see Grouping & Fingerprints.

For more information, see Aggregate Errors with Custom Fingerprints.

Advanced Usage

Advanced Configuration

The Native SDK sets the options when you first initialize the SDK:

Copied
sentry_options_t *options = sentry_options_new();

sentry_options_set_environment(options, "Production");
sentry_options_set_release(options, "5fd7a6cd");
sentry_options_set_debug(options, 1);

sentry_init(options);

For more information, see:

To receive more information on actions leading up to an exception or crash, the SDK can record breadcrumbs that are automatically added to every event. The most recent breadcrumbs are kept in a buffer.

You can manually add breadcrumbs using sentry_add_breadcrumb:

Copied
#include <sentry.h>

sentry_value_t crumb = sentry_value_new_breadcrumb("default", "Authenticated user");
sentry_value_set_by_key(crumb, "category", sentry_value_new_string("auth"));
sentry_value_set_by_key(crumb, "level", sentry_value_new_string("info"));
sentry_add_breadcrumb(crumb);

For more information, see:

Filter Events & Custom Logic

Sentry exposes a before_send callback which can be used to filter out information or add additional context to the event object. The callback must conform to the sentry_event_function_t signature.

Copied
#include <sentry.h>

sentry_value_t strip_sensitive_data(sentry_value_t event, void *hint) {
  /* modify event here or return NULL to discard the event */
  return event;
}

int main(void) {
  sentry_options_t *options = sentry_options_new();
  sentry_options_set_before_send(options, strip_sensitive_data);
  sentry_init(options);

  /* ... */
}

The callback is executed in the same thread as the call to sentry_capture_event. Work performed by the function may thus block the executing thread. For this reason, consider avoiding heavy work in before_send.

For more information, see:

Transports

The Native SDK uses Transports to send event payloads to Sentry. The default transport depends on the target platform:

  • Windows: WinHTTP
  • Linux: Curl
  • macOS: Curl

To specify a custom transport, use the sentry_options_set_transport function and supply a transport that implements the sentry_transport_t interface.

Copied
#include <sentry.h>

void custom_transport(sentry_envelope_t *envelope, void *state) {
  /*
   * Send the event here. If the transport requires state, such as an HTTP
   * client object or request queue, it can be specified in the `state`
   * parameter when configuring the transport. It will be passed as second
   * argument to this function.
   * The transport takes ownership of the `envelope`, and must free it once it
   * is done.
   */
  sentry_envelope_free(envelope);
}

int main(void) {
  void *transport_state = 0;

  sentry_options_t *options = sentry_options_new();
  sentry_transport_t *transport = sentry_transport_new(custom_transport);
  sentry_transport_set_state(transport, transport_state);

  sentry_options_set_transport(options, transport);
  sentry_init(options);

  /* ... */
}

The transport is invoked in the same thread as the call to sentry_capture_event. Consider to offload network communication to a background thread or thread pool to avoid blocking execution.

Integrations

Integrations extend the functionality of the SDK for some common frameworks and libraries. Similar to plugins, they extend the functionality of the Sentry SDK.

The Native SDK can use different backends that are responsible for capturing crashes. The backend is configured at build-time, using the SENTRY_BACKEND CMake option, with support for the following options:

  • crashpad, which is the default on Windows and macOS,
  • breakpad, which is the default on Linux,
  • inproc, the default on Android, and
  • none, that disables capturing crashes altogether.

Google Crashpad

Crashpad is an open-source multiplatform crash reporting system written in C++ by Google. It supports macOS, Windows, and Linux, and features an uploader to submit Minidumps to a configured URL right when the process crashes.

To use the Crashpad backend with the Native SDK, configure the CMake build with the SENTRY_BACKEND=crashpad option. This will automatically create a crashpad_handler executable alongside the sentry library.

Copied
$ cmake -B build -D SENTRY_BACKEND=crashpad

The SDK will automatically look for a crashpad_handler executable in the same directory as the running application. It will also use the .sentry-native directory as its database by default, relative to the current working directory of your application. This location temporarily hosts Minidumps before they are uploaded to Sentry.

Both of these paths can be customized like this:

Copied
sentry_options_t *options = sentry_options_new();
sentry_options_set_handler_path(options, "path/to/crashpad_handler");
sentry_options_set_database_path(options, "sentry-db-directory");
sentry_init(options);

The crashpad handler executable must be shipped alongside your application so that it can be launched when initializing the SDK. The path is evaluated according to shell lookup rules at runtime.

It is advised to specify both the path to the crashpad_handler executable as well as the path to the database directory manually.

Event Attachments

Besides the Minidump file, Sentry can optionally store additional files uploaded in the same request, such as log files. Learn more about these in Attachments.

To add an attachment, the path to the file has to be configured when initializing the SDK. It will monitor the file and upload it along with any event or crash that is sent to Sentry:

Copied
sentry_options_add_attachment(options, "/var/server.log");
You can edit this page on GitHub.