Use another OpenTelemetry client
FuseScope’s browser SDK and
Android SDK are recommended, but not
required. The RUM gateway accepts OTLP from any client and never checks which
SDK sent it. If your app already uses the OpenTelemetry web SDK, point its exporters at
FuseScope and add the attributes below; the Frontend screens then work as with
@fusescope/browser.
Create the application first, as in Set up a web application, to get its public key and allowed origins. The SDK settings, such as the sample rate and consent, are then yours to implement in your client.
Endpoints
Section titled “Endpoints”| Signal | Endpoint |
|---|---|
| Traces | POST <FuseScope URL>/rum/v1/traces |
| Logs | POST <FuseScope URL>/rum/v1/logs |
- Encoding: OTLP/HTTP, with
Content-Type: application/jsonorapplication/x-protobuf.Content-Encoding: gzipis accepted. - Key: the application’s public key in the
FuseScope-RUM-Keyheader. Fornavigator.sendBeacon, which can’t set headers, pass it as thefusescope_rum_keyquery parameter instead. - Size: 4 MiB per request at most, before and after gzip.
- Response: an OTLP export response,
200, in the request’s encoding.
The gateway is not the collector’s OTLP endpoint (port 4318): browsers never talk to the collector directly. It authenticates the key, checks the origin, rate-limits, scrubs URLs, adds the application’s attributes and forwards to the collector.
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
const headers = { 'FuseScope-RUM-Key': 'rum_pub_…' };
const traceExporter = new OTLPTraceExporter({ url: 'https://fusescope.example.com/rum/v1/traces', headers,});const logExporter = new OTLPLogExporter({ url: 'https://fusescope.example.com/rum/v1/logs', headers,});The gateway answers CORS itself, from the application’s Allowed origins:
- The custom header makes every export a non-simple request, so the browser sends an
OPTIONSpreflight first. The gateway allowsPOSTwith the headerscontent-type,content-encodingandfusescope-rum-key, and caches the answer for 24 hours. - Don’t send credentials (
withCredentials, cookies): they aren’t needed and aren’t allowed. - Requests without an
Originheader, such as from a server or a test script, skip the origin check but still need a valid key.
Attributes the screens need
Section titled “Attributes the screens need”The gateway sets these on every resource, so you don’t need to:
fusescope.rum.application.idandfusescope.rum.platform(weborandroid, from the application), always, overwriting any value the client sent;service.nameanddeployment.environment.name, from the application’s name and environment, when the client didn’t set them;event.nameon log records, copied from the record’s event name when the attribute is missing. FuseScope’s log storage keeps only the attribute.
Your client must send the rest:
| Where | Attribute | Used for |
|---|---|---|
| Every span and log record | session.id |
Sessions, session error rate, recent sessions. A random id per visit, shared by the visit’s spans and logs. |
| Every span and log record | fusescope.rum.view.route |
Routes: the route template, such as /product/:id. |
| Resource | service.version |
The Release filter and column. |
| Resource | user_agent.original; on Android device.manufacturer, device.model.name, os.name and os.version |
Browser · OS, or Device · OS on Android, in sessions. |
| Resource | telemetry.distro.name and .version, or telemetry.sdk.name and .version |
The SDK badge. Any name other than @fusescope/browser or io.fuseone.fusescope:android shows as Other client. |
Span named view |
url.path, fusescope.rum.view.route |
Views: one span per page or route the user saw. End it when the user leaves the view or hides the page: its duration is the time on view. |
Span named view |
fusescope.rum.view.loading_type (initial_load or route_change) |
Page loads and route changes in the Views tab. Without it, views are counted apart, marked *. |
| Every span and log record, optional | session.previous_id, user.id |
The after link between sessions, and the user column and search. Hash user.id yourself if it identifies a person. |
Log record, event browser.user_action.click, optional |
fusescope.rum.action.target |
The element named on Click events in the timeline and breadcrumbs. |
| HTTP client spans | http.request.method, http.response.status_code, url.full, with traceparent sent to the backend |
View backend trace in recent sessions. |
Log record, event exception |
exception.type, exception.message, exception.stacktrace, fusescope.rum.error.source (onerror, unhandledrejection or manual) |
Errors, their grouping and the error rate. Send the stack raw, as the browser wrote it: FuseScope symbolicates it with your source maps, looked up by service.version. |
Log record, event rum.vital, Android |
fusescope.rum.vital.name = app_start, fusescope.rum.vital.value (ms), fusescope.rum.vital.rating, start.type (cold, warm or hot) |
App start p75 on the Android overview. |
Log record, event browser.web_vital |
browser.web_vital.name (lcp, inp, cls, fcp, ttfb), browser.web_vital.value, browser.web_vital.rating (good, needs-improvement, poor) |
The vitals, their split bars and Top routes by LCP. Values in milliseconds; CLS unitless. |
The upstream @opentelemetry/browser-instrumentation package emits the
browser.web_vital events and HTTP spans with these names; you add the session, the
route and the view spans. The
SDK’s README
lists every attribute @fusescope/browser sends.
Android
Section titled “Android”A plain OpenTelemetry Android
client, or any OTLP client in an Android app, sends to the same endpoints with the same
FuseScope-RUM-Key header. Create an Android application first, as in
Set up an Android application,
to get its key and allowed package names. Then:
- Set
app.package.nameon the resource, to the app’sapplicationId. The gateway refuses a request when any resource in it has noapp.package.name, or one that is not in Allowed package names. No semantic convention names the package, so OpenTelemetry Android doesn’t send it on its own. - Send no
Originheader. An Android application never serves a browser, so the gateway refuses requests that carry one. OkHttp and the OpenTelemetry Java exporters send none. - Set
service.versionto the app’sversionName, the release you upload R8 mappings for.
val resource = Resource.getDefault().toBuilder() .put("service.version", BuildConfig.VERSION_NAME) .put("app.package.name", BuildConfig.APPLICATION_ID) .build()
val spanExporter = OtlpHttpSpanExporter.builder() .setEndpoint("https://fusescope.example.com/rum/v1/traces") .addHeader("FuseScope-RUM-Key", "rum_pub_…") .build()val logExporter = OtlpHttpLogRecordExporter.builder() .setEndpoint("https://fusescope.example.com/rum/v1/logs") .addHeader("FuseScope-RUM-Key", "rum_pub_…") .build()The gateway maps what OpenTelemetry Android sends onto the RUM model, filling only what the client left unset:
| OpenTelemetry Android sends | The gateway stores |
|---|---|
Log event app.crash |
An exception event with fusescope.rum.error.source = crash. |
Log event device.anr |
An exception event with fusescope.rum.error.source = anr, exception.type = ANR and exception.message = Application Not Responding. |
app.screen.name on a span or log record |
The same value as fusescope.rum.view.route. |
| The record’s event name | The event.name attribute, as for every client. |
Crashes, ANRs and screens therefore show up without extra code. For the rest of the
screens, add what the table in Attributes the screens need
lists: session.id (OpenTelemetry Android sets it), spans named view with
fusescope.rum.view.loading_type, and HTTP client spans with traceparent sent to your
backend. Send exception.stacktrace as Java prints it (Throwable.printStackTrace()
output): FuseScope parses it, retraces it with the R8 mapping of service.version, and
groups it as described in
Grouping Android errors. The
Android SDK’s README lists
every attribute io.fuseone.fusescope:android sends.
Related
Section titled “Related”- Set up a web application: rejected requests.
- OTLP endpoints: sending backend telemetry.