176 lines
5.6 KiB
Markdown
176 lines
5.6 KiB
Markdown
# Instrumentation guide
|
|
|
|
This document describes the recommended instrumentation contract for this
|
|
receiver. It is available at `/instrumentation.md` so frontend and backend
|
|
agents can read it before integrating telemetry.
|
|
|
|
## Shared identity
|
|
|
|
Use the same values across all signals from one deployed application:
|
|
|
|
- `service.name`: stable application name, for example `checkout-web`.
|
|
- `service.release`: immutable deploy identifier, for example
|
|
`2026.09.18-a1b2c3`.
|
|
- `service.environment`: `production`, `staging`, or `development`.
|
|
|
|
The release must exactly match the source-map upload release.
|
|
|
|
## Browser frontend
|
|
|
|
Load the RUM script and initialize it once, before the application starts:
|
|
|
|
```html
|
|
<script src="https://otel.example.com/static/otel-rum.js"></script>
|
|
<script>
|
|
const rum = OtelRUM.init({
|
|
serviceName: "checkout-web",
|
|
release: "2026.09.18-a1b2c3",
|
|
environment: "production",
|
|
baseUrl: "https://otel.example.com"
|
|
});
|
|
</script>
|
|
```
|
|
|
|
The collector captures uncaught errors, unhandled promise rejections, failed
|
|
HTTP requests, breadcrumbs, Web Vitals, and optional trace context. Correlate
|
|
frontend requests with backend spans when possible:
|
|
|
|
```js
|
|
fetch("/api/orders", { headers: rum.traceHeaders() });
|
|
```
|
|
|
|
For manually handled errors:
|
|
|
|
```js
|
|
try {
|
|
riskyOperation();
|
|
} catch (error) {
|
|
rum.captureException(error, { "feature.name": "checkout" });
|
|
}
|
|
```
|
|
|
|
Do not put secrets, tokens, or sensitive customer data in breadcrumbs or
|
|
custom attributes.
|
|
|
|
## React error boundaries
|
|
|
|
Rendering errors are not reliably caught by global `window.onerror` handlers.
|
|
Report them from an error boundary and render a recovery screen:
|
|
|
|
```tsx
|
|
import React from "react";
|
|
|
|
export class AppErrorBoundary extends React.Component<
|
|
{ children: React.ReactNode },
|
|
{ error: Error | null }
|
|
> {
|
|
state = { error: null as Error | null };
|
|
|
|
static getDerivedStateFromError(error: Error) {
|
|
return { error };
|
|
}
|
|
|
|
componentDidCatch(error: Error, info: React.ErrorInfo) {
|
|
window.OtelRUM?.last?.captureException(error, {
|
|
"exception.type": "ReactErrorBoundary",
|
|
"react.component_stack": info.componentStack,
|
|
});
|
|
}
|
|
|
|
render() {
|
|
if (this.state.error) {
|
|
return <button onClick={() => this.setState({ error: null })}>Retry</button>;
|
|
}
|
|
return this.props.children;
|
|
}
|
|
}
|
|
```
|
|
|
|
Use the same pattern in your application, including a user-visible fallback
|
|
for individual views and the application root.
|
|
|
|
## Backend instrumentation
|
|
|
|
Instrument backend services with an OpenTelemetry SDK or auto-instrumentation
|
|
and export OTLP to this receiver:
|
|
|
|
- OTLP/gRPC: `otel.example.com:4317`
|
|
- OTLP/HTTP traces: `https://otel.example.com/v1/traces`
|
|
- OTLP/HTTP metrics: `https://otel.example.com/v1/metrics`
|
|
- OTLP/HTTP logs: `https://otel.example.com/v1/logs`
|
|
|
|
Set the resource attributes on every provider/exporter:
|
|
|
|
```text
|
|
service.name=checkout-api
|
|
service.release=2026.09.18-a1b2c3
|
|
service.environment=production
|
|
```
|
|
|
|
Create spans around inbound requests, database calls, external HTTP calls,
|
|
queue operations, and important business operations. Record HTTP status,
|
|
route, method, and exception details. Mark failed spans with an error status.
|
|
The receiver derives backend issues from error spans and ERROR/FATAL logs.
|
|
|
|
If HTTP ingest authentication is enabled, provide `OTEL_INGEST_KEY` as the
|
|
`X-Otel-Ingest-Key` header or `key` query parameter. Keep that key server-side;
|
|
browser clients should not receive it.
|
|
|
|
For non-interactive agents that need to query protected debug endpoints, use a
|
|
separate `OTEL_AGENT_TOKEN` service token. Send it as
|
|
`X-Otel-Agent-Token: $OTEL_AGENT_TOKEN`; do not put it in browser code or
|
|
telemetry payloads.
|
|
|
|
## Source maps
|
|
|
|
Build the frontend with the same immutable release used by RUM. The command
|
|
and output directory depend on your build tool; the example below assumes a
|
|
standard `dist/` output:
|
|
|
|
```sh
|
|
export RELEASE="2026.09.18-a1b2c3"
|
|
VITE_APP_RELEASE="$RELEASE" npm run build
|
|
```
|
|
|
|
After deployment, upload the contents of each generated JavaScript map to the
|
|
public multipart endpoint. No repository checkout or upload script is needed.
|
|
`source` must match the generated bundle URL/path captured in the browser
|
|
stack, while `file=@...` reads the local source-map file contents:
|
|
|
|
```sh
|
|
curl --fail-with-body --silent --show-error \
|
|
-X POST "https://otel.example.com/api/sourcemaps" \
|
|
-F "release=$RELEASE" \
|
|
-F "source=/assets/app-HASH.js" \
|
|
-F "file=@dist/assets/app-HASH.js.map;type=application/json"
|
|
```
|
|
|
|
For example, if the deployed JavaScript is available at
|
|
`https://app.example.com/assets/main-abc123.js`, upload its matching map with
|
|
`source=/assets/main-abc123.js`. The source-map filename on the build machine
|
|
does not need to match the URL, but the `source` field must.
|
|
|
|
Maps are parsed and retained server-side. Issue responses include a resolved
|
|
stack when `service.release` and the generated bundle path match. Original
|
|
source files and map contents are never returned by the API.
|
|
|
|
The Docker build removes `.map` files from production images by default. For
|
|
development or staging, public maps can be enabled for Chrome DevTools:
|
|
|
|
```sh
|
|
PUBLIC_SOURCEMAPS=true ./build.sh
|
|
```
|
|
|
|
Public maps expose application source code and should not be enabled in
|
|
production unless that is intentional.
|
|
|
|
## Verification checklist
|
|
|
|
1. Trigger a controlled frontend exception.
|
|
2. Trigger a controlled backend error span or ERROR log.
|
|
3. Confirm both appear under Issues as separate frontend/backend issues.
|
|
4. Confirm the issue sample contains the expected release.
|
|
5. Confirm a mapped frontend stack shows original file and line information.
|
|
6. Confirm trace IDs connect frontend requests to backend traces where headers
|
|
were propagated.
|