React integration
editReact integration
editThis document covers how to use Real User Monitoring JavaScript agent with React applications. Please see our Getting started guide for configuring the Real User Monitoring agent.
Installing Elastic APM React package
editInstall the @elastic/apm-rum-react
package as a dependency to your application:
npm install @elastic/apm-rum-react --save
Instrumenting your React application
editThe React integration package provides two approaches to instrumenting your application:
Instrumenting application routes with @elastic/apm-rum-react >= 2.0.0
editTo instrument the application routes, you can use ApmRoutes
component provided in the package.
ApmRoutes
creates a transaction that has the path of the Route
as its name and has route-change
as its type.
ApmRoutes
only supports applications using version 6
of the
react-router
library.
RouterProvider
instrumentation is not currently supported.
First import ApmRoutes
from the @elastic/apm-rum-react
package:
import { ApmRoutes } from '@elastic/apm-rum-react'
Then, use the ApmRoutes
component from the react-router
library. Every <Route>
wrapped by <ApmRoutes>
will be monitored.
class App extends React.Component { render() { return ( <BrowserRouter> <ApmRoutes> <Route path="/" element={<HomeComponent />} /> <Route path="/about" element={<AboutComponent />} /> </ApmRoutes> </BrowserRouter> ) } }
Instrumenting application routes with @elastic/apm-rum-react < 2.0.0
editTo instrument the application routes, you can use ApmRoute
component provided in the package.
ApmRoute
creates a transaction that has the path of the Route
as its name and has route-change
as its type.
ApmRoute
only supports applications using versions 4
and 5
of the
react-router
library.
First import ApmRoute
from the @elastic/apm-rum-react
package:
import { ApmRoute } from '@elastic/apm-rum-react'
Then, you should replace Route
components from the react-router
library
with ApmRoute
. You can use ApmRoute
in any of the routes that you would like to monitor,
therefore, you don’t have to change all of your routes:
class App extends React.Component { render() { return ( <div> <ApmRoute exact path="/" component={() => ( <Redirect to={{ pathname: '/home' }} /> )} /> <ApmRoute path="/home" component={HomeComponent} /> <Route path="/about" component={AboutComponent} /> </div> ) } }
ApmRoute
only instruments the route if component property is provided, in other cases, e.g. using render
or children
properties,
ApmRoute will only renders the route without instrumenting it,
please instrument the individual component using withTransaction
in these cases instead.
Instrumenting individual React components
editFirst import withTransaction
from the @elastic/apm-rum-react
package:
import { withTransaction } from '@elastic/apm-rum-react'
Then, you can use withTransaction
as a function to wrap your React components:
class AboutComponent extends React.Component { } export default withTransaction('AboutComponent', 'component')(AboutComponent)
withTransaction
accepts two parameters, "transaction name" and "transaction type".
If these parameters are not provided, the defaults documented in Transaction API will be used.
Instrumenting lazy loaded routes
editWhen the route is rendered lazily with components using React.lazy
or a
similar API, it is currently not possible to auto instrument the components
dependencies(JavaScript bundles, API calls, etc) via ApmRoute
because React
suspends the underlying component until the required dependencies are available
which means our transaction is not started till React starts rendering the
underlying component. To instrument these lazy rendered routes and capture the
spans associated with the components, you’ll need to manually instrument the
code with the withTransaction
API.
import React, { Component, Suspense, lazy } from 'react' import { Route, Switch } from 'react-router-dom' import { withTransaction } from '@elastic/apm-rum-react' const Loading = () => <div>Loading</div> const LazyRouteComponent = lazy(() => import('./lazy-component')) function Routes() { return ( <Suspense fallback={Loading()}> <Switch> <Route path="/lazy" component={LazyRouteComponent} /> </Switch> </Suspense> ) } // lazy-component.jsx class LazyComponent extends Component {} export default withTransaction('LazyComponent', 'component')(LazyComponent)