React.js App Instrumentation
Follow the steps below to auto-instrument your React.js web app. When complete, your app will start emitting traces to Lakerunner.
-
Install the OpenTelemetry dependencies:
npm install --save @opentelemetry/instrumentation npm install --save @opentelemetry/auto-instrumentations-web npm install --save @opentelemetry/sdk-trace-web npm install --save @opentelemetry/context-zone npm install --save @opentelemetry/resources npm install --save @opentelemetry/semantic-conventions npm install --save @opentelemetry/exporter-trace-otlp-http -
Initialize the instrumentation.
If your application has signed-in user state, initialize instrumentation when the user profile is available so that user information is included in
fetchspans.import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web'; import { ZoneContextManager } from '@opentelemetry/context-zone'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { registerInstrumentations } from '@opentelemetry/instrumentation'; import { resourceFromAttributes } from '@opentelemetry/resources'; import { BatchSpanProcessor, WebTracerProvider, } from '@opentelemetry/sdk-trace-web'; import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'; useEffect(() => { if (userProfile) { const resource = resourceFromAttributes({ [ATTR_SERVICE_NAME]: 'your-service-name', 'deployment.environment.name': 'local', // local/dev/staging/prod }); const tracerProvider = new WebTracerProvider({ resource, spanProcessors: [ new BatchSpanProcessor( new OTLPTraceExporter({ url: window.location.origin + '/otlp/v1/traces', // See Step 3 below }), ), ], }); tracerProvider.register({ contextManager: new ZoneContextManager(), }); registerInstrumentations({ tracerProvider, instrumentations: [ getWebAutoInstrumentations({ '@opentelemetry/instrumentation-user-interaction': { enabled: false, }, '@opentelemetry/instrumentation-document-load': { enabled: false, }, '@opentelemetry/instrumentation-fetch': { enabled: true, semconvStabilityOptIn: 'http', ignoreNetworkEvents: true, applyCustomAttributesOnSpan(span) { span.setAttribute('user.email', userProfile.email); span.setAttribute('user.id', userProfile.userId); }, }, }), ], }); } }, [userProfile]); -
Set up a backend endpoint to proxy traces.
Proxying through your own backend ensures you don’t expose your Cardinal API key in browser code.
Example Express route handler:
app.post('/otlp/v1/traces', async (req, res) => { try { const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT; if (!!otlpEndpoint) { const response = await fetch(otlpEndpoint + '/v1/traces', { method: 'POST', body: JSON.stringify(req.body), headers: { 'Content-Type': 'application/json', 'x-cardinalhq-api-key': process.env.CARDINALHQ_API_KEY, }, }); return res.status(response.status).send(); } return res.status(200).send(); } catch (err) { logger.error(err, 'Error proxying web traces'); // Handle error } });Set these environment variables on the backend:
export OTEL_EXPORTER_OTLP_ENDPOINT="https://otelhttp.intake.<your-region>.aws.cardinalhq.io" export CARDINALHQ_API_KEY="your-api-key" # Set your API keyTo get an API key, follow the steps in the Overview.
-
Run your application:
npm run start # Or your application's start script -
Validate that Lakerunner is receiving data.
Open pages in the app that make
fetchcalls. Wait a few minutes, then query for your service in the Cardinal dashboard.
PostHog Integration
Use PostHog for session replay recordings?
Update the applyCustomAttributesOnSpan function in your browser instrumentation to add a posthog.session_replay_url attribute to spans:
import { usePostHog } from 'posthog-js/react';
const postHog = usePostHog();
// In your `useEffect` hook from above...
applyCustomAttributesOnSpan(span) {
// ... user attributes
span.setAttribute(
'posthog.session_replay_url',
postHog.get_session_replay_url({
withTimestamp: true,
timestampLookBack: 30,
}),
);
},Spans now carry a link to the PostHog session recording, which surfaces in downstream alerts and notifications.
Reach out to support@cardinalhq.io for support or to ask questions not answered in our documentation.