|
| 1 | +To get started with performance monitoring using Sentry's JavaScript SDK, first install the `@sentry/apm` package: |
| 2 | + |
| 3 | +```bash |
| 4 | +npm install --save @sentry/apm |
| 5 | +``` |
| 6 | + |
| 7 | +Next, initialize the integration in your call to `Sentry.init`: |
| 8 | + |
| 9 | +```jsx |
| 10 | +import * as Sentry from '@sentry/browser'; |
| 11 | +import { Integrations as ApmIntegrations } from '@sentry/apm'; |
| 12 | +Sentry.init({ |
| 13 | + dsn: '"___PUBLIC_DSN___"', |
| 14 | + release: 'my-project-name@' + process.env.npm_package_version, |
| 15 | + integrations: [ |
| 16 | + new ApmIntegrations.Tracing(), |
| 17 | + ], |
| 18 | + tracesSampleRate: 0.25, // must be present and non-zero |
| 19 | +}); |
| 20 | +``` |
| 21 | + |
| 22 | +Performance data is transmitted using a new event type called "transactions," which you can learn about in [Distributed Tracing](/performance-monitoring/distributed-tracing/#traces-transactions-and-spans). **To capture transactions, you must install the performance package and configure your SDK to set the `tracesSampleRate` configuration to a nonzero value.** The example configuration above will transmit 25% of captured transactions. |
| 23 | + |
| 24 | +Learn more about sampling in [Using Your SDK to Filter Events](/error-reporting/configuration/filtering/). |
| 25 | + |
| 26 | +**JavaScript** |
| 27 | + |
| 28 | +To access our tracing features, you will need to install our Tracing package `@sentry/apm`: |
| 29 | + |
| 30 | +```bash |
| 31 | +$ npm install @sentry/browser |
| 32 | +$ npm install @sentry/apm |
| 33 | +``` |
| 34 | + |
| 35 | +Alternatively, instead of npm packages, you can use our pre-built CDN bundle that combines both `@sentry/browser` and `@sentry/apm`: |
| 36 | + |
| 37 | +```html |
| 38 | +<script src="https://browser.sentry-cdn.com/{% sdk_version sentry.javascript.browser %}/bundle.apm.min.js" crossorigin="anonymous"></script> |
| 39 | +``` |
| 40 | + |
| 41 | +**Automatic Instrumentation** |
| 42 | + |
| 43 | +For `@sentry/browser`, we provide an integration called `Tracing` that does |
| 44 | +automatic instrumentation creating `pageload` and `navigation` transactions |
| 45 | +containing spans for XHR/fetch requests and Performance API entries such as |
| 46 | +marks, measures, and resource timings. |
| 47 | + |
| 48 | +The `Tracing` integration is specific to `@sentry/browser` and does not work |
| 49 | +with `@sentry/node`. |
| 50 | + |
| 51 | +The `Tracing` integration resides in the `@sentry/apm` package. You can add it to your `Sentry.init` call: |
| 52 | + |
| 53 | +```javascript |
| 54 | +import * as Sentry from '@sentry/browser'; |
| 55 | +import { Integrations as ApmIntegrations } from '@sentry/apm'; |
| 56 | + |
| 57 | +Sentry.init({ |
| 58 | + dsn: '___PUBLIC_DSN___', |
| 59 | + integrations: [ |
| 60 | + new ApmIntegrations.Tracing(), |
| 61 | + ], |
| 62 | + tracesSampleRate: 0.25, |
| 63 | +}); |
| 64 | +``` |
| 65 | + |
| 66 | +*NOTE:* The `Tracing` integration is available under `Sentry.Integrations.Tracing` when using the CDN bundle. |
| 67 | + |
| 68 | +To send traces, you will need to set the `tracesSampleRate` to a nonzero value. The configuration above will capture 25% of your transactions. |
| 69 | + |
| 70 | +You can pass many different options to the `Tracing` integration (as an object of the form `{optionName: value}`), but it comes with reasonable defaults out of the box. |
| 71 | + |
| 72 | +For all possible options, see [TypeDocs](https://getsentry.github.io/sentry-javascript/interfaces/apm.tracingoptions.html). |
| 73 | + |
| 74 | +**tracingOrigins Option** |
| 75 | + |
| 76 | +The default value of `tracingOrigins` is `['localhost', /^\//]`. The JavaScript SDK will attach the `sentry-trace` header to all outgoing XHR/fetch requests whose destination contains a string in the list or matches a regex in the list. If your frontend is making requests to a different domain, you will need to add it there to propagate the `sentry-trace` header to the backend services, which is required to link transactions together as part of a single trace. |
| 77 | + |
| 78 | +*Example:* |
| 79 | + |
| 80 | +- A frontend application is served from `example.com` |
| 81 | +- A backend service is served from `api.example.com` |
| 82 | +- The frontend application makes API calls to the backend |
| 83 | +- Therefore, the option needs to be configured like this: `new ApmIntegrations.Tracing({tracingOrigins: ['api.example.com']})` |
| 84 | +- Now outgoing XHR/fetch requests to `api.example.com` will get the `sentry-trace` header attached |
| 85 | + |
| 86 | +*NOTE:* You need to make sure your web server CORS is configured to allow the `sentry-trace` header. The configuration might look like `"Access-Control-Allow-Headers: sentry-trace"`, but this depends a lot on your setup. If you do not whitelist the `sentry-trace` header, the request might be blocked. |
| 87 | + |
| 88 | +**beforeNavigation Option**s |
| 89 | + |
| 90 | +{% version_added 5.18.0 %} |
| 91 | + |
| 92 | +For `pageload` and `navigation` transactions, the `Tracing` integration uses the browser's `window.location` API to generate a transaction name. To customize the name of the `pageload` and `navigation` transactions, you can supply a `beforeNavigation` option to the `Tracing` integration. This option allows you to pass in a function that takes in the location at the time of navigation and returns a new transaction name. |
| 93 | + |
| 94 | +`beforeNavigation` is useful if you would like to leverage the routes from a custom routing library like `React Router` or if you want to reduce the cardinality of particular transactions. |
| 95 | + |
| 96 | +```javascript |
| 97 | +import * as Sentry from '@sentry/browser'; |
| 98 | +import { Integrations as ApmIntegrations } from '@sentry/apm'; |
| 99 | +Sentry.init({ |
| 100 | + dsn: '___PUBLIC_DSN___', |
| 101 | + integrations: [ |
| 102 | + new ApmIntegrations.Tracing({ |
| 103 | + beforeNavigate: (location) => { |
| 104 | + // The normalizeTransactionName function uses the given URL to |
| 105 | + // generate a new transaction name. |
| 106 | + return normalizeTransactionName(location.href); |
| 107 | + }, |
| 108 | + }), |
| 109 | + ], |
| 110 | + tracesSampleRate: 0.25, |
| 111 | +}); |
| 112 | +``` |
| 113 | + |
| 114 | +**Manual Instrumentation** |
| 115 | + |
| 116 | +To manually instrument certain regions of your code, you can create a transaction to capture them. |
| 117 | +This is valid for both JavaScript Browser and Node and works independently of the `Tracing` integration. |
| 118 | + |
| 119 | +```javascript |
| 120 | +const transaction = Sentry.startTransaction({name: 'test-transaction'}); |
| 121 | +const span = transaction.startChild({op: 'functionX'}); // This function returns a Span |
| 122 | +// functionCallX |
| 123 | +span.finish(); // Remember that only finished spans will be sent with the transaction |
| 124 | +transaction.finish(); // Finishing the transaction will send it to Sentry |
| 125 | +``` |
| 126 | + |
| 127 | +Here is a different example. If you want to create a transaction for a user interaction on your page, you need to do the following: |
| 128 | + |
| 129 | +```javascript |
| 130 | +// Let's say this function is invoked when a user clicks on the checkout button of your shop |
| 131 | +shopCheckout() { |
| 132 | + // This will create a new Transaction for you |
| 133 | + const transaction = Sentry.startTransaction('shopCheckout'); |
| 134 | + |
| 135 | + // Assume this function makes an xhr/fetch call |
| 136 | + const result = validateShoppingCartOnServer(); |
| 137 | + |
| 138 | + const span = transaction.startChild({ |
| 139 | + data: { |
| 140 | + result |
| 141 | + }, |
| 142 | + op: 'task', |
| 143 | + description: `processing shopping cart result`, |
| 144 | + }); |
| 145 | + processAndValidateShoppingCart(result); |
| 146 | + span.finish(); |
| 147 | + |
| 148 | + transaction.finish(); |
| 149 | +} |
| 150 | +``` |
| 151 | + |
| 152 | +This example will send a transaction `shopCheckout` to Sentry. The transaction will contain a `task` span that measures how long `processAndValidateShoppingCart` took. Finally, the call to `transaction.finish()` will finish the transaction and send it to Sentry. |
| 153 | + |
| 154 | +**Adding Additional Spans to the Transaction** |
| 155 | + |
| 156 | +The next example contains the implementation of the hypothetical `processItem ` function called from the code snippet in the previous section. Our SDK can determine if there is currently an open transaction and add to it all newly created spans as child operations. Keep in mind that each individual span needs to be manually finished; otherwise, that span will not show up in the transaction. |
| 157 | + |
| 158 | +```javascript |
| 159 | +function processItem(item, transaction) { |
| 160 | + const span = transaction.startChild({ |
| 161 | + op: "http", |
| 162 | + description: "GET /" |
| 163 | + }) |
| 164 | + |
| 165 | + return new Promise((resolve, reject) => { |
| 166 | + http.get(`/items/${item.id}`, (response) => { |
| 167 | + response.on('data', () => {}); |
| 168 | + response.on('end', () => { |
| 169 | + span.setTag("http.status_code", response.statusCode); |
| 170 | + span.setData("http.foobarsessionid", getFoobarSessionid(response)); |
| 171 | + span.finish(); |
| 172 | + resolve(response); |
| 173 | + }); |
| 174 | + }); |
| 175 | + }); |
| 176 | +} |
| 177 | +``` |
0 commit comments