The autoinstrumentation directive

The React instrumentation offers a directive allowing you to easily instrument your functional components, class components and hooks.

The directive's schema is "use trace [API] [Name]" such that:

  • [API] (default value: dev) which must be either:
    • dev (which would cause the instrumentation to call into the Ottrelite Development API from the core package)
    • otel, which would cause it to use the OpenTelemetry JS SDK; in such case, you need to set up the OpenTelemetry SDK in your application and then probably you will also want to set up Ottrelite Interop layer with OTEL
  • [Name], which is optional and is the name of the component being traced; if not passed, Ottrelite will attempt to use your component's name - the details of how it is resolved are described in the function components, hooks and class components doc pages
TIP

Both parameters are optional, meaning that the shortest you can do is "use trace" which is equivalent to "use trace dev <resolved component name>".

If you pass only one parameter, the hook will first give priority to the [API] parameter; if the values does not match the possible options, then this argument will be treated as the [Name] parameter.

Class components

NOTE

As seen in the examples below, the components include an explicit implementation of shouldComponentUpdate to prevent unnecessary re-renders. This is a common practice in React to optimize performance, but it is not compulsory - the instrumentation would still work without it. However, in such case, it would be expected that most likely the instrumentation would produce many entries, for invocations of the component which didn't actually result in an update to the shadow tree.

import _ from 'lodash';
import { Component } from 'react';

export class TracedClassComponent extends Component<ExternallyDrivenComponentProps> {
  render() {
    'use trace';

    ...

    return (
      ...
    );
  }

  shouldComponentUpdate(
    nextProps: Readonly<ExternallyDrivenComponentProps>,
    nextState: Readonly<{}>,
    nextContext: any
  ): boolean {
    // only rerender if props have changed
    return (
      !_.isEqual(this.props, nextProps) ||
      !_.isEqual(this.state, nextState) ||
      !_.isEqual(this.context, nextContext)
    );
  }
}
WARNING

The name of the tracer is used to create a unique OTEL tracer, so make sure it is unique across your application.

With an explicit Tracer name:

import _ from 'lodash';
import { Component } from 'react';

export class TracedClassComponent extends Component<ExternallyDrivenComponentProps> {
  render() {
    'use trace dev TestLibTracedClassComponent';

    ...

    return (
      ...
    );
  }

  shouldComponentUpdate(
    nextProps: Readonly<ExternallyDrivenComponentProps>,
    nextState: Readonly<{}>,
    nextContext: any
  ): boolean {
    // only rerender if props have changed
    return (
      !_.isEqual(this.props, nextProps) ||
      !_.isEqual(this.state, nextState) ||
      !_.isEqual(this.context, nextContext)
    );
  }
}

What will be the name of the tracer?

Declaration styleName
Explicit name from the string after "use trace"The passed string
named className of the class
anonymous className of the assignment target identifier
Need to boost your app's performance?
We help React Native teams enhance speed, responsiveness, and efficiency.