Fingerprint Rules
This feature is only applicable for error issues. Other categories of issues (such as performance issues) do not support this feature.
Fingerprint rules (previously known as server-side fingerprinting) are also configured with a config similar to stack trace rules, but the syntax is slightly different. The matchers are the same, but instead of flipping flags, a
These rules can be configured on a per-
- Identify the match logic for grouping issues together.
- Set the match logic and the fingerprint for it.
The syntax follows the syntax from Discover queries. If you want to negate the match, prefix the expression with an exclamation mark (!
).
Sentry attempts to match against all values that are configured in the fingerprint. In the case of stack traces, all frames are considered. If the event data matches all the values in a line for a matcher and expression, then the fingerprint is applied. When there are multiple rules that match the event, the first matching rule in the list is applied.
# You can use comments to explain the rules. Rules themselves follow the
# following syntax:
matcher:expression -> list of values
# The list of values can be hardcoded or substituted values.
Below is a practical example, which groups exceptions of a specific type together:
error.type:DatabaseUnavailable -> system-down
error.type:ConnectionError -> system-down
error.value:"connection error: *" -> connection-error, {{ transaction }}
Now, all the events with the error type DatabaseUnavailable
or ConnectionError
will be grouped into an issue with the type system-down
. In addition, all events with the error value connection error
will be grouped by their transaction name. So, for example, if your transactions /api/users/foo/
and /api/events/foo/
—both with the value connection error
—crash the same way, Sentry will create two issues, regardless of stack trace or any other default grouping method.
Matchers
Matchers allow you to use glob patterns.
If you want to create a rule that includes brackets [ ]
, braces { }
or a literal *
, escape them with a backslash; that is, \[
, \]
, \{
, \}
or \*
.
The following matchers are available:
error.type
alias: type
Matches on an exception type (exception name). The match is performed as a case sensitive glob.
error.type:ZeroDivisionError -> zero-division
error.type:ConnectionError -> connection-error
error.value
alias: value
Matches on the exception value. Errors or exceptions often have human-readable descriptions (values) associated with them. This matcher allows a case insensitive match.
error.value:"connection error (code: *)" -> connection-error
error.value:"could not connect (*)" -> connection-error
message
Matches on a log message. It will also automatically check for the additional exception value as they can be hard to keep apart. The matching is case insensitive.
message:"system encountered a fatal problem: *" -> fatal-log
logger
Matches on the name of the logger, which is useful to combine all messages of a logger together. This match is case sensitive.
logger:"com.myapp.mypackage.*" -> mypackage-logger
level
Matches on the log level. The match is case insensitive.
logger:"com.myapp.FooLogger" level:"error" -> mylogger-error
tags.tag_name
Matches on the value of the tag tag_name
. This can be useful to filter down certain types of events. For instance, you can separate events caused by a specific server:
tags.server_name:"canary-*.mycompany.internal" -> canary-events
stack.abs_path
alias: path
Matches on the path of an event and is case insensitive. It uses path globbing semantics, which means that *
does not match a slash, but **
does. Note that this matcher matches on both abs_path
and filename
as SDKs can be quite inconsistent about how these values are supported. If the glob matches on either of these values, it's considered a match.
stack.abs_path:"**/my-utils/*.js" -> my-utils, {{ error.type }}
stack.module
alias: module
Similar to stack.abs_path
but matches on the module name instead. The match is case sensitive and regular globbing rules apply (*
also matches slashes).
stack.module:"*/my-utils/*" -> my-utils, {{ error.type }}
stack.function
alias: function
Checks if any of the functions in the stack trace match the glob. The match is case sensitive:
stack.function:"my_assertion_failed" -> my-assertion-failed
stack.package
alias: package
Matches on the "package" of a frame. This is typically the name of the debug symbol/object file that contains a frame. If any of the frames match this object file, then it matches.
stack.package:"**/libcurl.dylib" -> libcurl
stack.package:"**/libcurl.so" -> libcurl
family
Used to "scope" down the matcher. The following families exist: javascript
for any type of JavaScript event, native
for any type of Native event. Any other platform is called other
.
family:native !stack.module:"myproject::*" -> not-from-my-project
app
Checks if the frame is in-app or not. It is particularly useful when combined with another matcher. Possible values are yes
and no
:
app:yes stack.function:"assert" -> assert
Combining Matchers
When multiple matchers are combined, they all need to match. Matchers that operate on frames must all apply to the same frame; otherwise, they are not considered a match.
For instance, if you match on both the function name and module name, then a match only exists if a frame matches both the function name and the module name. It's not enough for a frame to match only with the function name, even if another frame would match the module name by itself.
# this matches if a frame exists with a specific function and module name
# and also a specific error type is thrown
error.type:ConnectionError stack.function:"connect" stack.module:"bot" -> bot-error
Variables
On the right-hand side of the
Variables are enclosed in double braces ({{ variable_name }}
).
{{ default }}
This fills in the default
stack.function:"query_database" -> {{ default }}, {{ transaction }}
{{ transaction }}
This fills in the name of the transaction into the
error.type:"ApiError" -> api-error, {{ transaction }}
{{ error.type }}
alias: {{ type }}
This fills in the name of the error that occurred. When chained exceptions are used, it will be the most recently thrown error. This will force the creation of a group per error type:
stack.function:"evaluate_script" -> script-evaluation, {{ error.type }}
{{ error.value }}
alias: {{ value }}
This fills in the stringified value of the error that occurred. When chained exceptions are used, it will be the most recently thrown error. Note that this can produce really bad groups when error values are frequently changing.
error.type:"ScriptError" -> script-evaluation, {{ error.value }}
{{ stack.function }}
alias: {{ function }}
This fills in the function name of the "crashing frame," also known as the application code's topmost frame.
error.type:"ScriptError" -> script-evaluation, {{ stack.function }}
{{ stack.abs_path }}
alias: {{ path }}
This fills in the path of the "crashing frame," also known as the application code's topmost frame.
error.type:"ScriptError" -> script-evaluation, {{ stack.abs_path }}
{{ stack.filename }}
This is like stack.abs_path
but will only fill in the relative file name:
error.type:"ScriptError" -> script-evaluation, {{ stack.filename }}
{{ stack.module }}
alias: {{ module }}
This fills in the module name of the "crashing frame," also known as the application code's topmost frame.
error.type:"ScriptError" -> script-evaluation, {{ stack.module }}
{{ stack.package }}
alias: {{ package }}
This fills in the package name (object file) of the "crashing frame," also known as the application code's topmost frame.
stack.function:"assert" -> assertion, {{ stack.package }}
{{ logger }}
This fills in the name of the logger that caused an event.
message:"critical connection error*" -> connection-error, {{ logger }}
{{ level }}
This fills in the name of the log level that was used to create an event.
message:"connection error*" -> connection-error, {{ logger }}, {{ level }}
{{ tags.tag_name }}
This fills in the value of a tag into the
message:"connection error*" -> connection-error, {{ tags.server_name }}
{{ message }}
This fills in the message of the event (similar to error.value
but for
captured messages). Note that this can produce groups with poor data quality if
messages are changing frequently:
logger:"com.foo.auditlogger.*" -> audit-log, {{ message }}
Custom Titles
When you use fingerprinting to group events together it can sometimes be useful to also change the default title of the event. Normally the title of the event is the exception type and value (or the top most function names for certain platforms). When you group by custom rules this title can often be misleading. For instance if you group a logger together you might want to name the group after that logger. This can be accomplished by setting the title
attribute like this:
logger:my.package.* level:error -> error-logger, {{ logger }} title="Error from Logger {{ logger }}"
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").