Frontend observability troubleshooting ¶
Content Security Policy (CSP) ¶
If your application uses a Content Security Policy, the browser blocks Faro's requests to the collector unless you allow them.
Add the collector endpoint to connect-src:
connect-src 'self' https://telemetry.nav.no https://telemetry.ekstern.dev.nav.no;Symptoms: No data appears in Grafana. Browser console shows errors like Refused to connect to '...' because it violates the following Content Security Policy directive: "connect-src ...".
CORS errors with trace propagation ¶
When using trace propagation, the browser sends a traceparent header to your backend. If your backend doesn't allow this header in CORS, the request may fail or the header is silently dropped.
Symptoms: Trace propagation doesn't work (no linked backend spans), or API requests fail with CORS errors in the browser console.
Fix: Add traceparent to Access-Control-Allow-Headers on your backend:
Access-Control-Allow-Headers: Content-Type, traceparentNo data in Grafana ¶
If you've deployed Faro but don't see data:
- Check the browser console — look for errors from Faro or network errors to the collector endpoint
- Check the Network tab — filter for requests to the collector URL. You should see POST requests with a
2xxresponse - Check the collector URL — make sure it matches your environment (dev vs prod). See collector endpoints
- Check CSP — see above
- Check sampling — if you set
sessionTracking.samplingRate, your session might not be sampled. Try setting it to1.0temporarily - Wait a moment — data can take up to a minute to appear in Grafana
Sourcemaps not resolving ¶
If error stack traces show minified positions instead of source code:
-
Check that your app is on the CDN — sourcemap resolution only works for bundles served from
cdn.nav.no. Server-rendered apps (Next.js, Remix) serving assets from the pod are not supported -
Check that sourcemaps are deployed — your
.mapfiles must be on the CDN alongside the JS bundle. See Upload the bundle and sourcemaps to the CDN -
Check that the browser loads the JS from the CDN — resolution only triggers for frames whose file is served from the CDN. If your HTML references bundles served from your pod, uploading the maps to the CDN has no effect. See My app runs in a container
-
Check
sourceMappingURL— open your deployed JS bundle in a browser and look for//# sourceMappingURL=at the bottom. If it's missing, check your bundler config -
Check the path — the
sourceMappingURLmight be a relative path that doesn't resolve correctly from the collector's perspective
See Sourcemaps for build configuration details and the end-to-end walkthrough.
High data volume ¶
If Faro generates more data than you need:
- Reduce session sampling — set
sessionTracking.samplingRateto a value between0and1(e.g.,0.1for 10% of sessions) - Disable console capture — pass
captureConsole: falsetogetWebInstrumentations(), particularly if your app produces a lot of console output - Remove tracing — if you don't need browser traces, don't install
@grafana/faro-web-tracing. This also saves ~500kB in bundle size - Use a feature flag — only initialize Faro for a subset of users
See Performance tuning for configuration examples.
Faro not initializing ¶
If initializeFaro() throws or Faro doesn't start:
- Check the import — make sure you import from
@grafana/faro-web-sdk, not a different package - Check
'use client'— in Next.js App Router, the file that callsinitializeFaromust have'use client'at the top. Faro can't run in React Server Components - Check for double initialization — if Faro is already initialized, calling
initializeFaroagain throws. Guard withif (faro.api) return; - Check bundler externals — if you use
nais.jsauto-configuration, make sure the file is excluded from bundling. Otherwise the bundler replaces it with local dev values