The original address: blog. Sentry. IO / 2019/09/26 /…

Original author:

Release time: June 26, 2019

This article by Jian Yue SimpRead transcoding, original address blog. Sentry. IO

Let’s take a look at how Sentry can be used to detect crashes in native applications and fix them in a short time…….

Whether it’s a computer game, an Internet of things device, or a high-performance backend, you’re likely to develop the app in a native language. By far the most popular options for native application development are C and C++. Ok, maybe not the most popular, but definitely the most common. Some might even say “inevitable”.

Unfortunately, equally inevitable is the occasional application crash; Segmental failures and bus errors are probably familiar to you. Let’s look at how Sentry can be used to detect these crashes and fix them in a short time.

Select the correct client

First, pick a client that can capture crash reports and send them to Sentry. Sentry has long supported the popular Google Crashpad and Google Breakpad libraries. If your application already uses one of these libraries, or if you are familiar with how to set them up, you should be fine. Just set the upload URL to our MinidumPendpoint and you’ll see the crash.

With our new native SDK, you have a better option. It comes in three versions and is perfectly suited to your needs.

  1. Standalone: Captures custom information and errors, and adds breadcrumbs. While this is the most basic distribution, you can customize the signals you want to process and provide your own stack walk library. Our standalone SDK provides maximum flexibility, but also requires you to handle crashes yourself.
  2. Using Crashpad: Based on a separate SDK, this version ships and wraps Google Crashpad to catch crashes. You can still add breadcrumbs and capture custom messages, but you can also get a free mini-dump of crashed apps. This works best on Windows and macOS.
  3. Use Breakpad: As an alternative to Crashpad, this version ships and packs Google Breakpad to catch crashes. Otherwise, it’s the same. We recommend using this version on Linux.

If you are familiar with our other SDKS, you will immediately recognize the code required to initialize the SDK. In the following example, we initialize the Crashpad version for a Windows application and pass the executable path of the handler.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sentry.h"

int main(void) {
    sentry_options_t *options = sentry_options_new();

    // The handler is a Crashpad-specific background process
    sentry_options_set_handler_path(options, "bin/Release/crashpad_handler.exe");

    // This is where Minidumps and attachments live before upload
    sentry_options_set_database_path(options, "sentry-db");
    sentry_options_add_attachment(options, "application.log".".. /ce32ff7a.log");

    // Initialize the SDK and start the Crashpad handler
    sentry_init(options);

    // Capture a custom message
    sentry_value_t event = sentry_value_new_event();
    sentry_value_set_by_key(event, "message",
                            sentry_value_new_string("Hello World!"));
    sentry_capture_event(event);

    // Make sure everything flushes before exiting
    sentry_shutdown();
}
Copy the code

On our release page, you can download the source and build files for the bundled SDK. For Windows, we have a Microsoft Visual Studio 2017 solution for you. You can start with the solution directly, add your own files, or drag and drop the project into an existing solution.

For macOS and Linux, we distribute Makefiles of build libraries, utilities, and sample programs. You can integrate them into your existing build process, or use them individually to build binaries and copy them over.

If our distribution does not contain the project files you need, the premake file allows you to generate a custom project or make changes to build Settings. The Official ReadMe contains more information about integrating and customizing SDKS.

Add context information for debugging

Now that you have added the SDK, you can use its API to add information that will help you debug problems. The SDK’s _value API_ allows you to create arbitrarily complex values from several primitives.

// create an object and add a string value
sentry_value_t object = sentry_value_new_object();
sentry_value_set_by_key(object, "key", sentry_value_new_string("value"));

// add that object into the list
sentry_value_t list = sentry_value_new_list();
sentry_value_append(list, object);

// ...
Copy the code

Internally, the SDK handles memory management for strings, objects, and lists. As long as you always allocate the return values of these functions, you don’t need to worry about memory leaks. And all of these functions are thread-safe.

Let’s take a look at the most common attribute additions.

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("some_name"));
sentry_set_user(user);
Copy the code

This adds a user (with a given identifier and name) to all future events or minidumps. The user information is stored until overwritten by another call to sentry_set_user and immediately applied to all future events.

sentry_value_t default_crumb = sentry_value_new_breadcrumb(0."hello, world");
sentry_add_breadcrumb(default_crumb);
Copy the code

This adds a breadcrumb and is included in each subsequent event. The SDK keeps a window for _100_ nearest breadcrumbs.

sentry_set_transaction("startup");
sentry_set_level(SENTRY_LEVEL_WARNING);
sentry_set_tag("mode"."demo");
Copy the code

This sets the tag and other basic event properties. As with user information, these attributes are applied before being overwritten. Of course, you’re not limited to these attributes. See Event Payload Docs for a more complete list of all supported attributes and interfaces for creating custom events.

Provides debugging information to Sentry

Now that your application is ready to send data to Sentry, it’s time to build. To process crash reports, Sentry requires debugging information that allows us to extract stack traces and tokenize stack frames into function names and line numbers.

The easiest way to provide debugging information to Sentry is to use sentry-CLI upload. This little assistant scans compatible files and uploads them to your project. You can run it during your build or release.

$ sentry-cli upload-dif /path/to/files 
> Found 2 debug information files 
> Prepared debug information files for upload 
> Uploaded 2 missing debug information files 
> File processing complete:

     OK 3003763b-afcb-4a97-aae3-28de8f188d7c-1
        (crash.exe; x86_64 executable)
     OK 3003763b-afcb-4a97-aae3-28de8f188d7c-1
        (crash.pdb; x86_64 debug companion)
Copy the code

There are two important points to note.

  1. Always upload debugging information and the same built executable that you deploy or distribute to users. Sentry uses unique identifiers that change with each build to match crash reports.
  2. Check whether all available debugging information has been uploaded. Sentry will analyze the uploaded file, and in theDebug FilesSet the screen to display the information contained therein. For best results, check for _”debug” in your uploaded files.and“Unwind” _.

If you are unsure which files contain usable information, you can also use Sentry-CLI to check their contents. This is especially useful on Linux, where generating and stripping debugging information is slightly more complicated than on other platforms.

$ sentry-cli difutil check path/to/file

Debug Info File Check
  Type: elf debug companion
  Contained debug identifiers:
    > 924e148f-3bb7-06a0-74c1-36f42f08b40e (x86_64)
  Contained debug information:
    > symtab, debug
  Usable: yes
Copy the code

Configuring the symbol Server

If you can’t upload your debug files to us, or have them stored in a different location, we’ve taken care of that for you. We are pleased to announce that symbol Server is now no longer a preview. You can easily configure them on the _ debug file _ Settings screen.

Out of the box, Sentry gives you a list of built-in symbol servers that contain system libraries or debug files for popular third-party frameworks. By default, _iOS_ and _Microsoft_ are enabled, which gives you the function names for both platforms. Other examples include graphical drivers for _Nvidia_ and _AMD_, the _Unity_ project, and Github’s _Electron_ framework.

Once you select the repository from the list, Sentry immediately applies the debug files for these servers to all new crash reports and events received. Also, you can remove servers from the list at any time and Sentry will no longer use their debug files.

If your organization is in the _Business_ or _Enterprise_ program, you can even add custom servers to this list. If you are running your own symbol server, this is probably of most interest to you. We currently support HTTP servers that speak symbolic server protocols, Amazon S3 buckets, and Google Cloud Storage buckets. In this way, we are fully compatible with the servers used by The Microsoft debugger and support the same query paths used by LLDB and GDB.

Sentry is compatible with all major debug file library layouts and supports a variety of compression formats. See our documentation for all supported features for more information. Of course, we’re here to help if you run into difficulties, so if you have questions about custom symbol servers, please contact our amazing support engineers.

Reduce noise with custom grouping

Now that crash reports are pouring in, it’s time to focus on the exciting part: suppressing the bugs. Don’t get us wrong, we’re not saying bugs are exciting. But you have to agree that there is a pleasant, almost therapeutic feeling when a problem is finally solved.

Sentry helps you by categorizing events as unique problems, which provides an overview of the state of your application.

  • Which crashes happen the most?
  • In the latest version, the crash still happens despite my fixes?
  • What issues are affecting my most important users?

Problem grouping is done automatically in the background by Sentry. To group problems, Sentry looks at the relevant parts of the error and stack trace to find problems with similar events. While we use reasonable defaults for this kind of matching, it can sometimes go wrong. For this reason, you can fine-tune groups with custom rules.

First, make sure you use the latest version of the grouping algorithm. You can upgrade to the latest algorithms and basic configurations under _ Project Settings > Group Configuration _. We are constantly improving the grouping logic, but you can choose when to apply changes to prevent new problems from suddenly interfering with your workflow.

Sometimes Sentry may still consider grouping stack frames that are not important to you. Common namespaces such as “STD” or “boost “are hidden and ignored by default, but frameworks from other libraries may still be considered. You can fine-tune this by adding custom grouping enhancements. These allow you to override which frames are considered _in-app_ and which are included in _grouping_. By default, only frameworks within an application are considered for grouping.

So how exactly does this work? Let’s assume that your application is always called through a function run_loop and ends up calling a function call_external to assign to third-party code. To exclude all frameworks under RUN_loop and above call_external, add the following grouping enhancement.

platform:native function:call_external ^-group ^-app
platform:native function:run_loop v-group v-app
Copy the code

Grouping rules can be matched on the frame and then perform some actions. ^ Specify that this action applies to all of the above frames, -group and -app are actions that exclude frames from grouping and application frame display, respectively.

Let’s look at a different example. What if we don’t want to see any framework from the Google :: Breakpad namespace? Very simple.

platform:native function:google::breakpad::* -app
Copy the code

You can reduce the stack trace to the basics needed to debug the problem. Of course, there are more matchers and actions to configure, so check out our grouping documentation for the full details.

One more thing: Source Context

As a little cherry on top, let’s add the source code context. What’s better than seeing the offending code directly in your stack trace, right? All you have to do is upload the source code to Sentry.

Don’t worry, you’re not alone here. The Sentry CLI makes it easy to process your debug files, search for relevant source code, and create a bundle that contains all the necessary metadata. If you upload the debug files directly from the build system, it’s as simple as passing –include-sources in the upload command.

$ sentry-cli upload-dif --include-sources path > ... OK 3003763b-afcb-4a97-aae3-28de8f188d7c-1 (crash.exe; X86_64 executable file) OK 3003763b-afCb-4a97-aAE3-28de8f188d7c-1 (crash.pdb; X86_64 debug mate) OK 3003763b-afCB-4a97-aAE3-28de8f188d7C-1 (crash.pdb; X86_64 source code package)Copy the code

Later, you’ll notice that the source package and your debug file appear together in Settings and share the same identifier. This is how Sentry matches the correct version of your source code with incoming events and crashes. No matter how complex your build process is — using submodules, symbolic links, or generated files — there will always be a source context.

It is important to run this command on the same machine as the build. The Sentry CLI uses absolute paths stored in debug files to ensure that the correct source code is bundled. If your build process does not run an upload immediately, you can choose to generate a bundle file at build time without uploading.

$ sentry-cli difutil bundle-sources /path/to/debug_file
Copy the code

This will create a source code bundle ZIP next to the debug file that can be uploaded using upload-dif. This way, you can upload the source code along with your debug files at a later time.

What’s next?

From here, the entire Sentry platform is at your service. Link your version control system to receive suspicious submissions, integrate with project management tools such as JIRA to extend your workflow, or use Discover to perform advanced analysis of your events.

We are pleased to provide first-class error monitoring for native applications. Because crashes can be one of the most frustrating experiences for users and developers, it is critical to capture as much background information as possible to quickly resolve these errors.

Many of the features introduced in this article have been a long time in the making. We’re excited to hear about the unique application you’re building, and our team can’t wait to get feedback from your engineers.

As always, you are more than welcome to post on our forum or contact our support engineers with questions.

From Sentry, with ⌨️ and ❤️


www.deepl.com translation