A series of

  1. Sentry-go SDK Chinese Practice Guide
  2. Plan together according to official documents in Sentry For Go
  3. Snuba: Sentry’s new search infrastructure (based on ClickHouse)
  4. Sentry 10 K8S cloud native architecture exploration, fast access to Vue App in 1 minute
  5. Sentry(V20.12.1) K8S cloud native architecture exploration, play forward/back end monitoring and event log big data analysis, high performance + high availability + scalable + scalable cluster deployment
  6. Sentry(V20.12.1) K8S cloud native architecture exploration, Sentry JavaScript SDK three ways to install and load
  7. Sentry(V20.12.1) K8S cloud native architecture exploration, Sentry FOR JAVASCRIPT SDK configuration details
  8. Sentry(V20.12.1) K8S cloud native architecture exploration, Sentry FOR JAVASCRIPT manual capture of event basic usage
  9. Sentry(V20.12.1) K8S cloud native architecture exploration, Sentry FOR JAVASCRIPT Source Maps details
  10. Sentry(V20.12.1) K8S cloud native architecture exploration, Sentry FOR JAVASCRIPT troubleshooting
  11. Sentry(V20.12.1) K8S Cloud native architecture exploration, 1 minute hands-on JavaScript performance monitoring
  12. Sentry(V20.12.1) K8S Cloud Native Architecture Exploration, JavaScript Performance Monitoring management Transactions
  13. Sentry(V20.12.1) K8S Cloud Native Architecture Exploration, sampling Transactions for JavaScript Performance Monitoring
  14. Exploring native architecture in Sentry(V20.12.1) K8S cloud, JavaScript Enriching event information

SDK Fingerprinting

In supported SDKS, you can override the default group of Sentry, which passes the Fingerprint property as an array of strings. The fingerprint array has an unlimited length. This is similar to Fingerprint Rules Functionality, which is always available and can achieve similar results.

Basic Example

In the most basic case, values are passed directly:

function makeRequest(method, path, options) {
  return fetch(method, path, options).catch(function(err) {
    Sentry.withScope(function(scope) {
      // group errors together based on their request and response
      scope.setFingerprint([method, path, String(err.statusCode)]);
      Sentry.captureException(err);
    });
  });
}
Copy the code

You can use variable substitution to populate dynamic values into a fingerprint that is normally computed on the server. For example, you can add the value {{default}} to add the entire normally generated grouping hash to the fingerprint. These values are the same as server-side fingerprint identification. For more information, see Variables.

Group Errors With Greater Granularity

Your application queries Remote Procedure Call Model (RPC) interfaces or external Application Programming Interface (API) services, So the stack trace is usually the same (even if the outgoing request is very different).

The following example further breaks down the default group that Sentry will create (represented by {{default}}) and considers some properties of the error object:

class MyRPCError extends Error {
  constructor(message, functionName, errorCode) {
    super(message);

    // The name of the RPC function that was called (e.g. "getAllBlogArticles")
    this.functionName = functionName;

    // For example a HTTP status code returned by the server.
    this.errorCode = errorCode; } } Sentry.init({ ... .beforeSend: function(event, hint) {
    const exception = hint.originalException;

    if (exception instanceof MyRPCError) {
      event.fingerprint = [
        '{{ default }}'.String(exception.functionName),
        String(exception.errorCode)
      ];
    }

    returnevent; }});Copy the code

Group Errors More Aggressively

Common errors (such as database connection errors) have many different stack traces and never go together.

The following example will completely override the grouping of sentries by omitting {{default}} from the array:

class DatabaseConnectionError extends Error {} Sentry.init({ ... .beforeSend: function(event, hint) {
    const exception = hint.originalException;

    if (exception instanceof DatabaseConnectionError) {
      event.fingerprint = ['database-connection-error'];
    }

    returnevent; }});Copy the code

Fingerprint Rules

The Fingerprint rule (formerly known as server-side Fingerprint) is also configured similar to Stack Trace Rules, but with a slightly different syntax. The matchers are the same, but instead of flipping the flipping flags, they assign a fingerprint, which completely overrides the default group.

These Rules can be set by project in Settings > Projects > [Project] > Issue Grouping > Fingerprint Rules. Group Settings has input fields where you can write custom fingerprint rules. This syntax follows the syntax in Discover Queries. To negate a match, you can precede the expression with an exclamation mark (!). .

All values match, and in the case of stack traces, all frames are considered. If all matches are matched, the fingerprint is applied.

Fingerprinting Config

# 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.
Copy the code

Here is a practical example that combines a specific type of exception:

error.type:DatabaseUnavailable -> system-down
error.type:ConnectionError -> system-down

error.value:"connection error: *" -> connection-error, {{ transaction }}
Copy the code

Matchers

Matchers usually use wildcard syntax. The following matchers can be used:

error.type

  • alias: type
  • Matches the exception type (exception name). Matching is done in case sensitive form.
error.type:ZeroDivisionError -> zero-division
error.type:ConnectionError -> connection-error
Copy the code

error.value

  • alias: value
  • Matches the outlier. Errors or exceptions usually have easy-to-understand descriptions (values). The matcher allows case-insensitive matching.
error.value:"connection error (code: *)" -> connection-error
error.value:"could not connect (*)" -> connection-error
Copy the code

message

  • Matches log messages. It also automatically checks for other outliers because they are hard to separate. Matching is case insensitive.
message:"system encountered a fatal problem: *" -> fatal-log
Copy the code

logger

  • Matches the logger name, which is useful for grouping all logger messages together. This match is case sensitive.
logger:"com.myapp.mypackage.*" -> mypackage-logger
Copy the code

level

  • Matched at the log level. Matching is case insensitive.
logger:"com.myapp.FooLogger" level:"error" -> mylogger-error
Copy the code

tags.tag_name

  • Matches the value of tag tag_name. This is useful for filtering certain types of events. For example, you can isolate events caused by a particular server:
tags.server_name:"canary-*.mycompany.internal" -> canary-events
Copy the code

stack.abs_path

  • alias: path
  • Matches on the path of the event and is case insensitive. It uses path traversal semantics, which means*Does not match the slash, and支那Matching. Please note that this matcher is inabs_pathfilenameBecause the SDK can be very inconsistent about how to support these values. If a glob matches any of these values, it is considered a match.
stack.abs_path:"**/my-utils/*.js" -> my-utils, {{ error.type }}
Copy the code

stack.module

  • alias: module
  • withstack.abs_pathSimilar, but matches the module name. Matches are case sensitive, and the usual rules apply (*Also matches the slash).
stack.module:"*/my-utils/*" -> my-utils, {{ error.type }}
Copy the code

stack.function

  • alias: function
  • Check to see if any of the functions in the stack trace match globally. Match case sensitive:
stack.function:"my_assertion_failed" -> my-assertion-failed
Copy the code

stack.package

  • alias: package
  • Matches the frame’s “package”. This is usually the name of the Debug Symbol /object file that contains the frame. If any frame matches the target file, it will match.
stack.package:"**/libcurl.dylib" -> libcurl
stack.package:"**/libcurl.so" -> libcurl
Copy the code

family

  • Used for “scope” matcher. The following families exist: for any type of JavaScript eventjavascriptFor any type of Native eventnative. Any other platform is calledother.
family:native ! stack.module:"myproject::*" -> not-from-my-projectCopy the code

app

  • Check whether the frame is in the application. Especially useful in combination with other matchers. The possible values are zeroyesno:
app:yes stack.function:"assert" -> assert
Copy the code

Combining Matchers

When multiple matchers are combined, they all need to match. Matchers running on frame must all be applied to the same frame; Otherwise, they are not considered matches.

For example, if there is a match on both the function name and module name, then there is a match only if the frame matches on both the function name and module name. It is not enough for a frame to just match the function name, even if the other frame itself matches the module name.

# 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
Copy the code

Variables

On the right side of fingerprint, you can use constant values and variables. Variables are automatically replaced and have the same name as matchers, but they may be populated differently.

Variables are enclosed in double curly braces ({{variable_name}}).

{{ default }}

  • This will populate the default fingerprint that would be generated by normal grouping operations. This is useful if you want to subdivide an existing group in another way:
stack.function:"query_database" -> {{ default }}, {{ transaction }}
Copy the code

{{ transaction }}

  • This fills the transaction name into the Transaction. It forces the creation of a group for each transaction:
error.type:"ApiError" -> api-error, {{ transaction }}
Copy the code

{{ error.type }}

  • alias: {{ type }}
  • This will fill in the name of the error that occurred. When using · Chained Exceptions ·, it will be the most recently thrown error. This forces each ·transaction· to create a group:
stack.function:"evaluate_script" -> script-evaluation, {{ error.type }}
Copy the code

{{ stack.function }}

  • alias: {{ function }}
  • This will populate the name of the functionality “crashing Frame,” also known as the topmost frame in the application code.
error.type:"ScriptError" -> script-evaluation, {{ stack.function }}
Copy the code

{{ stack.module }}

  • alias: {{ module }}
  • This will fill in the module name of “Crashing Frame,” also called the topmost frame in the application code.
error.type:"ScriptError" -> script-evaluation, {{ stack.module }}
Copy the code

{{ stack.package }}

  • alias: {{ package }}
  • This will fill in the package name of “crashing Frame,” also known as the topmost frame in the application code.
stack.function:"assert" -> assertion, {{ stack.package }}
Copy the code

{{ logger }}

  • This will fill in the name of the logger that caused the event.
message:"critical connection error*" -> connection-error, {{ logger }}
Copy the code

{{ level }}

  • This populates the name of the log level used to create the event.
message:"connection error*" -> connection-error, {{ logger }}, {{ level }}
Copy the code

{{ tags.tag_name }}

  • This populates the value of the tag in fingerprint, for example, you can use Fingerprint to split the event by server name or similar.
message:"connection error*" -> connection-error, {{ tags.server_name }}
Copy the code

Stack Trace Rules

If a stack trace is used for grouping, stack trace rules (formerly known as grouping enhancement) affect the data entered into the algorithm. You can configure these Rules for each project by going to Settings > Projects > [Project] > Issue Grouping > Stack Trace Rules.

Each line is a rule; When all expressions match, one or more matching expressions are followed by one or more actions to be performed. All rules are executed from top to bottom on all frames in the stack trace.

The syntax for the stack trace rule looks like this:

matcher-name:expression other-matcher:expression ... action1 action2 ...
Copy the code

This syntax follows the syntax in Discover Queries. To negate a match, you can precede the expression with an exclamation mark (!). .

Here’s an example in action:

# 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
Copy the code

Matchers

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

family

  • Matches the universal Platform family, currently including javascript, Native, and Other. The comma-separated rule applies them to multiple platforms.
family:javascript stack.abs_path:**/generated/**  -group
Copy the code

stack.abs_path

  • alias: path
  • The matcher is case insensitive to the behavior of Unix globs on paths in the stack trace. The path separator is normalized to /. As a special rule, if the file name is relative, it still matches on **/.
# 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
Copy the code

stack.module

  • alias: module
  • Module is similar to path, but matches Module. It does not work with Native, but with JavaScript, Python, and similar platforms. Matching is case sensitive, and regular wildcards are available. Please note that modules are not packages, which can be confusing to Native environments.

stack.function

  • alias: function
  • Matches the functions in the stack trace and is case-sensitive using normal wildcards.
stack.function:myproject_* +app
stack.function:malloc      -group
Copy the code

stack.package

  • alias: package
  • Match package in stack trace.packageIs includedfunctionmoduleThe container. This is a.jar, a.dylib or something like that. The matching rule is the same as path. For example, this is usually an absolute path.
stack.package:**/libcurl.dylib -group
Copy the code

app

  • withstack trace frameMatches the current state of the in-app tag.yesIndicates that the frame is an intra-application frame,noNo.

Actions

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

Flag identifies the action to take when all matchers match and use the following prefix:

  • +Set up theflag
  • -Cancel the setupflag
  • ^Applies to frames above the matching frame (going to crash).
  • vApplies to frames below matching frames (away from crashes).

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

  • app: Marks or unmarks the frame within the application
  • group: Adds or removes frames from a group

Variables: You can set variables (variable=value). Currently there is only one:

  • max-frames: Sets the total number of frames to group. The default value is 0, which means all frames. If set to 3, only the first three frames are considered.

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

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
Copy the code

Recommendations

These suggestions 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 the stack trace are “in-application” (belonging to your own application) and which are not. The SDK defines the default rules, but in many cases, they can also be improved on the server. Especially for languages that require server-side processing (for example, Native C, C++, or JavaScript), it is best to override it on the server.

stack.function:myapplication::* +app
Copy the code

You can do the same by marking other frames “not in-app”. However, if this is the case, you should make sure to set all frames to “in-app” first to override the defaults:

app:no                   +app
stack.function:std::*    -app
stack.function:boost::*  -app
Copy the code

You need to force all frames to be in the application first, because the client SDK or earlier processing may have set some defaults.

Cut Stack Traces

In many cases, you want to remove the top or bottom of the stack trace. For example, many code bases use generic functions to generate errors. In this case, the error mechanism will show up as part of the stack trace.

For example, if you use Rust, you might want to remove some frames associated with Panic handling:

stack.function:std::panicking::begin_panic       ^-app -app ^-group
stack.function:core::panicking::begin_panic      ^-app -app ^-group
Copy the code

Here, we tell the system that all frames from begin-Panic to the crash position are not part of the application (including panic frames themselves). In all cases, all of the above frames are independent of the grouping.

Similarly, you can remove the base of the stack trace. This feature is especially useful if you have a different main loop to drive the application:

For example, if you use Rust, you might want to remove some frames associated with Panic handling:

stack.function:std::panicking::begin_panic       ^-app -app ^-group
stack.function:core::panicking::begin_panic      ^-app -app ^-group
Copy the code

This is not suitable for all projects, but it works well for many large applications that crash. The default strategy is to consider most stack traces associated with the grouping. This means that each different stack trace that causes a crash will result in the creation of a different group. If you don’t want this, you can force larger groups by limiting the number of frames that should be considered.

For example, if any frame in the stack trace points to a common external library, you can tell the system to consider only top N frames:

# 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
Copy the code