Skip to main content

Sending RUM Data to base14

This is a data-model reference for sending mobile RUM telemetry to base14 Scout. Use it when you build your own instrumentation (rather than using a prebuilt SDK like scout_flutter) and need to know exactly which spans and attributes each RUM view expects.

RUM data is plain OpenTelemetry: every value is a standard resource or span attribute, so it lines up with any traces and logs you already send to Scout. Each RUM feature is powered by a span with a specific span.name and a specific set of attributes - get the names and attribute placement right and the corresponding view populates automatically.


Transport

SettingValue
ProtocolOTLP - traces sent to .../v1/traces
EndpointThe OTLP URL base14 provides for your account, e.g. https://rum.<region>.base14.io/<ingest-id>/otlp
AuthAuthorization: Bearer <token> header (base14 provisions the token)

Identity and Attribute Placement

Read this section before wiring up any spans - most integration problems come from putting an attribute on the wrong scope, or letting an identity value drift between builds.

service.name is fixed

service.name is a resource attribute and is your app's identity in base14. Agree the value with base14 and keep it constant across builds and environments. Use service.version for build axes and environment for deployment axes - never encode those into service.name, or your data fragments into many "apps".

[R] resource vs [S] span

Throughout this guide:

  • [R] marks a resource attribute - set once per export on the OpenTelemetry Resource.
  • [S] marks a span attribute - set per span.

Putting a span key on the resource (or vice versa) is the most common reason a view comes up empty.

Duration units are not uniform

Most durations are in seconds, but app startup is in milliseconds.

AttributeUnit
screen.load_timeseconds
view.time_spentseconds
long_task.durationseconds
anr.durationseconds
app_startup.durationmilliseconds
warning

app_startup.duration is the one exception - it is in milliseconds. Sending it in seconds makes every startup look ~1000x too fast.


Shared Attribute Sets

To avoid repeating the same lists on every span, this guide refers to two shared sets.

Standard resource set [R]

Unless a span says otherwise, it carries these resource attributes:

service.name, service.version, environment,
os.name, os.version,
device.manufacturer, device.model.name,
network.connection.type

Crash-related spans (error, native_crash, app_crash) add:

host.arch, app.version, app.build, app.bundle_id

Standard session identity [S]

Unless a span says otherwise, it carries this identity block:

session.id, session.start_time, session.sampled,
session.sample_rate, session.type,
user.id, user.anonymous_id,
screen.name
  • session.start_time - ISO-8601; constant for the session's whole life.
  • user.id / user.anonymous_id - send at least one. The crash Affected Users panel is populated from these, so set them on crash spans too.

Spans

Each span is recognized by its exact span.name. All RUM spans use SpanKind = Internal.

screen_view

A screen or route was shown.

  • Resource: standard set
  • Span: standard identity, plus:
AttributeDescription
view.idUnique id for this view instance
view.loading_typeinitial_load or route_change
view.is_activeWhether the view is currently active
view.referrerThe previous screen/route

Powers: screen list and per-screen stats, session screen counts, active users.

screen_load

Time to display a screen.

  • Resource: standard set
  • Span: standard identity, plus:
AttributeDescription
screen.load_timeLoad time in seconds (float)

Powers: average and p95 screen-load time per screen.

view_session

Time spent on a screen. Emit when leaving it.

  • Resource: standard set
  • Span: standard identity, plus:
AttributeDescription
view.time_spentTime on screen in seconds (float)

Powers: average time-spent per screen.

long_task

A main-thread block / jank event.

  • Resource: standard set
  • Span: standard identity, plus:
AttributeDescription
long_task.durationBlock duration in seconds
long_task.thresholdThreshold that classified it, in seconds
display.scroll.max_depthMax scroll depth reached
display.scroll.max_depth_scroll_topScroll-top at max depth
display.scroll.max_scroll_heightMax scrollable height
display.scroll.max_scroll_height_time_msTime to reach max height (ms)

Powers: long-task counts per screen; session timeline.

http.request

A network request.

Span name and dual keys

The span name must be exactly http.request (not http), or no network data is recorded. Send both keys in each pair below with the same value - different views read different names. Request latency is taken from the span's own start/end time, so set those correctly.

  • Resource: standard set
  • Span: standard identity, plus:
Attribute(s)Description
url.full and http.urlFull URL (same value in both)
http.request.method and http.methodMethod (same value in both)
http.response.status_code and http.status_codeStatus (same value in both)
http.duration_msLatency in ms
http.response.body.sizeResponse body size
http.errorError flag/message, if the request failed

Powers: network dashboard (top endpoints, error rate, latency p50/p95/p99); session timeline.

app_startup

A cold or warm start.

  • Resource: standard set
  • Span: standard identity, plus:
AttributeDescription
app_startup.typecold or warm
app_startup.durationStartup time in milliseconds (not seconds)

Powers: average cold/warm start, cold/warm counts.

error

A handled or unhandled error (JS / Dart / app-level). app_crash is treated as the same javascript kind as error and shares this attribute set (grouped by error.message).

  • Resource: standard set + crash additions
  • Span: standard identity, plus:
AttributeDescription
error.messageTitle and grouping key - keep it stable (no timestamps/ids)
error.typeError type/class
error.stack_traceFull stack trace
error.handledWhether the error was caught
error.libraryLibrary/framework that raised it
breadcrumbsJSON array of {time, type, message}
dart.build_idDart build id (for symbol resolution)

Powers: crash list, crash detail, crash-free rate, per-user error counts.

native_crash

A native crash (signal / Mach / exit-info / JVM). Grouped and addressed by (crash.type, crash.reason).

  • Resource: standard set + crash additions
  • Span: standard identity, plus the crash keys and detail below.

Crash keys (grouping):

AttributeDescription
crash.typeGrouping key
crash.reasonGrouping key / title
crash.stack_traceNative stack trace

Crash detail (send what the platform provides):

GroupAttributes
Report / identitycrash.timestamp, crash.report_id, crash.last_screen, crash.previous_session_id, crash.started_at, crash.status, crash.error_type, crash.subreason
Signal / Mach (Apple)crash.signal, crash.signal_code, crash.signal_address, crash.mach_exception, crash.mach_code, crash.mach_subcode, crash.nsexception_name, crash.exception_type, crash.exception_code, crash.cpp_exception_name, crash.fault_address_register, crash.exception_syndrome_register, crash.os_reason_code, crash.os_reason_name
Thread / processcrash.thread, crash.thread_name, crash.process_name, crash.queue, crash.pid, crash.tid, crash.uid, crash.ppid, crash.process_uptime_secs, crash.importance
Memorycrash.pss_kb, crash.rss_kb, crash.hang_duration_ms
Device / OS / buildcrash.cpu_arch, crash.machine, crash.os_name, crash.os_version, crash.kernel_version, crash.kernel, crash.device_model, crash.abi, crash.build_fingerprint, crash.build_type, crash.region_format
App versioncrash.app_version, crash.application_version, crash.application_build_version, crash.bundle_id
Android exit-infocrash.exit_status, crash.death_timestamp_ms
Heavy blobs (raw JSON / text)crash.tombstone, crash.binary_images_json, crash.registers_json, crash.callstack_tree_json, crash.memory_map, crash.registers
Breadcrumbsbreadcrumbs - JSON array of {time, type, message}

Powers: native crash list and detail, crash-free rate, affected devices/users, frequency over time, top crashing screens, post-crash recovery flag.

app_crash

An app-level crash. Handled together with error (the javascript crash kind), grouped by error.message.

  • Resource: standard set + crash additions
  • Span: standard identity, plus:
AttributeDescription
error.messageTitle and grouping key - keep it stable
crash.typeCrash type
crash.last_screenScreen active when the crash occurred

anr

Application Not Responding (Android). Grouped and scoped by screen.name.

  • Resource: standard set
  • Span: standard identity, plus:
AttributeDescription
anr.durationANR duration in seconds
anr.thresholdThreshold that classified it, in seconds
anr.main_thread_stackMain-thread stack at the freeze
anr.thread_countNumber of threads captured
anr.threads_jsonAll-threads dump (JSON)

Powers: ANR list/detail, ANR duration by app-version/OS/device.

user_interaction

A tap/click, for the session timeline.

  • Resource: service.name, environment, os.name, device.model.name
  • Span: session.id, session.start_time, user.id, user.anonymous_id, screen.name, plus:
AttributeDescription
user_interaction.targetTapped element's label (mobile)
user_interaction.target.typeElement type
target_elementTapped element (web)
target_xpathElement xpath (web)
user_interaction.typee.g. tap
user_interaction.target.name_sourceSource of the target's name
user_interaction.target.permanent_idStable element id
user_interaction.target.x / .yTap coordinates
user_interaction.idUnique id for the interaction

Powers: session timeline (tap events).

app_vital

FBC / interaction-to-next-view vitals, for the session timeline.

  • Resource: service.name, environment, os.name
  • Span: session.id, session.start_time, user.id, user.anonymous_id, screen.name, plus:
AttributeDescription
vital.namee.g. fbc, inv
vital.typestartup or navigation
vital.duration_msDuration in ms
vital.from_screenSource screen
vital.to_screenDestination screen

Powers: session timeline (vitals).

frozen_frame

A frozen frame, for the session timeline.

  • Span: session.id, session.start_time, user.id, user.anonymous_id, screen.name, plus:
AttributeDescription
frozen_frame.durationFrozen-frame duration

Powers: session timeline.

web_vital

Core Web Vitals (web), for the session timeline.

  • Span: session.id, session.start_time, user.id, user.anonymous_id, plus:
AttributeDescription
web.vital.nameVital name (e.g. LCP, CLS)
web.vital.valueMeasured value
web.vital.ratingRating bucket (good / needs-improvement / poor)

Powers: session timeline.


Minimum Viable Payload

To get RUM working with the smallest possible surface:

On every export (resource):

service.name, environment, service.version,
os.name, os.version,
device.model.name, device.manufacturer,
network.connection.type

On every span:

session.id, session.start_time, session.sampled
user.id or user.anonymous_id

Mirror the user identity onto crash spans so Affected Users counts work.

Emit at least these spans:

  • screen_view - with screen.name
  • app_startup - with app_startup.type and app_startup.duration (ms)
  • http.request - with span duration set and the HTTP key pairs from http.request
  • error and/or native_crash - with a stable error.message / crash.reason

Add screen_load, view_session, long_task, and anr for full screen-performance and stability coverage.


Common Mistakes

SymptomCause and fix
Data fragments into many "apps"A changing service.name per build/env. Keep it fixed; use environment / service.version for those axes.
A view is emptyResource keys on the span, or span keys on the resource. service.version / os.* / device.* are [R]; session.* / user.* / screen.name / per-span fields are [S].
Crash Affected Users emptyThe panel reads user.id / user.anonymous_id. Set them on crash spans too.
Every startup looks ~1000x too fastapp_startup.duration sent in seconds - it must be milliseconds.
No network data / partial network viewsOnly one HTTP naming convention sent. Send both url.full + http.url, http.request.method + http.method, http.response.status_code + http.status_code, and set the span's own duration.
Crashes don't group (one row each)Unstable error.message / crash.reason containing timestamps or ids. Keep titles stable.
No network data at allSpan named http instead of http.request.
Session never registersMissing or unparseable session.start_time. Send valid ISO-8601.

Was this page helpful?