Stack Trace Rules

If you use stack traces for grouping, the stack trace rules (previously known as grouping enhancements) influence the data that's fed into the grouping algorithm. These rules can be configured on a per-project basis under Settings > Projects > [project] > Issue Grouping > Stack Trace Rules.

Each line is a single rule; one or multiple match expressions are followed by one or multiple actions to be executed when all expressions match. All rules are executed from top to bottom on all frames in the stack trace.

The syntax for stack trace rules is similar to:

Copied
matcher-name:expression other-matcher:expression ... action1 action2 ...

The syntax follows the syntax from Discover queries. If you want to negate the match, you can prefix the expression with an exclamation mark (!).

The following is a practical example of how this looks:

Copied
# mark all functions in the std namespace to be outside the app
family:native stack.function:std::*       -app

# mark all code in node modules not to be in app
stack.abs_path:**/node_modules/**         -app

# remove all generated javascript code from all grouping
stack.abs_path:**/generated/**.js         -group

Matchers

Multiple matchers can be defined in a line. The following matchers are available:

family

Matches on the general platform family, which currently includes javascript, native and other. Comma separate rules to apply them to multiple platforms.

Copied
family:javascript,native stack.abs_path:**/generated/**  -group

stack.abs_path

alias: path

This matcher is case insensitive with Unix glob behavior on a path in a stack trace. The path separators are normalized to /. As a special rule, if the filename is relative, it still matches on **/.

Copied
# match on all files under `project` with a `.c` extension
stack.abs_path:**/project/**.c` +app

# matches on vendor/foo without sub folders
stack.abs_path:**/vendor/foo/*.c` -app

# matches on `foo.c` as well as `foo/bar.c`.
stack.abs_path:**/*.gen.c` -group

stack.module

alias: module

Module is similar to path but matches on the module. This is not used for Native but it is used for JavaScript, Python, and similar platforms. Matches are case sensitive, and normal globbing is available. Note that modules are not packages, which can be confusing for Native environments.

stack.function

alias: function

Matches on a function in a stack trace, and is case sensitive with normal globbing.

Copied
stack.function:myproject_* +app
stack.function:malloc      -group

stack.package

alias: package

Matches on a package in a stack trace. The package is the container that contains a function or module. This is a .jar, a .dylib or similar. The same matching rules as for path apply. For example, this is typically an absolute path.

Copied
stack.package:**/libcurl.dylib -group

app

Matches on the current state of the in-app flag of a stack trace frame. yes means the frame is in-app, no means it's not.

Actions

There are two types of actions: flag and variables setting.

  1. A flag identifies the action to be taken if all matchers match and uses these prefixes:
  • + sets the flag
  • - unsets the flag
  • ^ applies to frames above the matching frame (toward the crash)
  • v applies to frames below the matching frame (away from the crash)

As an example, -group ^-group removes the matching frame and all frames above it from the grouping.

  • app: marks or unmarks a frame in-app
  • group: adds or removes a frame from grouping
  1. variables: Variables can be set (variable=value). Currently, there is just one:
  • max-frames: sets the total number of frames to be considered for grouping. The default is 0, which means "all frames." If set to 3, only the top three frames are considered.

If a line is prefixed with a hash (#), it's a comment and ignored.

Copied
stack.abs_path:**/node_modules/** -group
stack.abs_path:**/app/utils/requestError.jsx -group
stack.abs_path:**src/getsentry/src/getsentry/** +app

family:native max-frames=3

stack.function:fetchSavedSearches v-group
stack.abs_path:**/app/views/**.jsx stack.function:fetchData ^-group

family:native stack.function:SpawnThread v-app -app
family:native stack.function:_NSRaiseError ^-group -app
family:native stack.function:std::* -app
family:native stack.function:core::* -app

Recommendations

These recommendations will greatly improve your out-of-the-box grouping experience.

Mark in-app Frames

To proactively improve your experience, help Sentry determine which frames in your stack trace are "in-app" (part of your own application) and which are not. The SDK defines the default rules, but in many cases, this can be improved on the server as well. In particular, for languages where server-side processing is necessary (for example, Native C, C++, or JavaScript), it's better to override this on the server.

The sentry-cocoa SDK always marks public frameworks such as UIKitCore, CoreFoundation, GraphicsServices, and so forth as not inApp. Before version 7.0.0, the sentry-cocoa SDK marks all private frameworks and the main executable inside the application bundle as inApp. Since version 7.0.0, the sentry-cocoa SDK sets the inApp flag only for frames originating from the main executable by using the CFBundleExecutable. For private frameworks, such as Sentry, dynamic and static frameworks differ. If you are not familiar with these terms, we recommend reading Dynamic Library Programming Topics.

Dynamic Frameworks

If you use dynamic frameworks, such as, for example, Sentry, the SDK marks these as not inApp. In case you have a private framework that should be inApp, you can use inAppInclude or inAppExclude of the SentryOptions.

Copied
import Sentry

SentrySDK.start { options in
    options.dsn = "https://examplePublicKey@o0.ingest.sentry.io/0"

    // The SDK marks all frameworks starting with MyBusinessLogic as inApp
    options.add(inAppInclude: "MyBusinessLogic")

    // The SDK marks all frameworks starting with MyFramework as not inApp
    options.add(inAppExclude: "MyFramework")
}
Static Frameworks

When using static frameworks, the frameworks end up in the main executable. Therefore, the SDK currently can't detect if a frame of the main executable originates from your application or a private framework and marks all of them as inApp. To improve your experience, use the below explained stack trace rules on the server to tell Sentry which should be marked as not inApp.

Stack Trace Rules

The following marks frames from libdispatch starting with _dispatch_ as inApp.

Copied
stack.function:_dispatch_*  +app

You can also achieve the same result by marking other frames not inApp. The following sample marks functions from the classes DataRequest and DownloadRequest as not inApp.

Copied
stack.function:DataRequest*  -app
stack.function:DownloadRequest*  -app

Cut Stack Traces

In many cases, you want to remove the top or bottom of the stack trace. For instance, many code bases use a common function to generate an error. In this case, the error machinery will appear as part of the stack trace.

For example, if you use Rust, you likely want to remove some frames that are related to panic handling:

Copied
stack.function:std::panicking::begin_panic       ^-app -app ^-group
stack.function:core::panicking::begin_panic      ^-app -app ^-group

Here we tell the system that all frames from begin-panic to the crash location are not part of the application (including the panic frame itself). All frames above are, in all cases, irrelevant for grouping.

Likewise, you can also remove the base of a stack trace. This is particularly useful if you have different main loops that drive an application:

For example, if you use Rust, you likely want to remove some frames that are related to panic handling:

Copied
stack.function:std::panicking::begin_panic       ^-app -app ^-group
stack.function:core::panicking::begin_panic      ^-app -app ^-group

Stack Trace Frame Limits

This isn't useful for all projects, but it can work well for large applications with many crashes. The default strategy is to consider most of the stack trace relevant for grouping. This means that every different stack trace that leads to a crashing function will cause a different group to be created. If you do not want that, you can force the groups to be much larger by limiting how many frames should be considered.

For instance, if any of the frames in the stack trace refer to a common external library, you could tell the system only to consider the top N frames:

Copied
# always only consider the top 1 frame for all native events
family:native max-frames=1

# if the bug is in proprietarymodule.so, only consider top 2 frames
family:native stack.package:**/proprietarymodule.so  max-frames=2

# these are functions we want to consider much more of the stack trace for
family:native stack.function:KnownBadFunction1  max-frames=5
family:native stack.function:KnownBadFunction2  max-frames=5
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) to suggesting an update ("yeah, this would be better").