Skip to content
TraceItX Docs
Documentation

Session vitals

One artifact, one call per player. The Sessions tab fills itself.

Updated

Session Vitals tracks CPU, memory and playback quality across a session and shows them as a timeline under Sessions. It is off by default — enable it per app under the integration’s Session Vitals card. The SDK negotiates the flag on every config refresh; a session starts within one refresh of the toggle flipping on, and stops (sending its final summary) when it flips off.

Setup

// build.gradle.kts — the media3 artifact is optional; core alone still
// records CPU and memory.
implementation("com.traceitx:core:$traceitxVersion")
implementation("com.traceitx:reporter-ui:$traceitxVersion")
implementation("com.traceitx:media3:$traceitxVersion")
TraceItXConfig(
    appId = "txx_app_…",
    sdkKey = "txx_live_…",
    vitals = VitalsConfig(
        enabled = null,            // null = follow the dashboard toggle; false = opt out locally
        sampleRate = null,         // 0.0–1.0; combined with the server rate by min()
        captureSourceQuery = false // keep query strings on stream URLs (signed CDN URLs carry tokens)
    ),
)

Local config can only opt out or lower the rate. It can never enable vitals the dashboard has off.

Tracking a player

import com.traceitx.media3.trackPlayer

val player = ExoPlayer.Builder(context).build()
val handle = TraceItX.trackPlayer(player, name = "main")
// … later
player.release()   // detaches automatically; handle.detach() is also fine

One call registers one AnalyticsListener. From it the timeline gets the source (URL with query stripped, protocol, live flag), startup breakdown (manifest, first fragment, licence, first frame), play/pause/seek/rate, rebuffers, bitrate and resolution changes, DRM key system, fatal and non-fatal errors, and a stats sample every 20 s (buffer ahead, bandwidth estimate, dropped frames). Nothing is recorded per segment.

Calling trackPlayer before the collector has started is fine — the registration is honoured the moment it does. Releasing the player without calling detach() still records a clean player_detach.

Custom entries

TraceItX.trackVitals("ad_break", mapOf("position" to "midroll", "index" to 2))
handle.track("cdn_switch", mapOf("from" to "cdn-a", "to" to "cdn-b"))   // scoped to that player

Any JSON-encodable value, capped at 2 KB serialised. Over the cap it is truncated and flagged, never dropped. Entries logged while no session is running are dropped.

Writing an integration

Implement com.traceitx.vitals.PlayerIntegration and pass it to TraceItX.trackPlayer(integration, name). attach subscribes to your player and emits through the context; snapshot is asked once per sampler tick and must read player state on the player’s own thread; describe re-emits the current source and DRM so a rotated session is self-describing; detach removes every listener. The Media3 integration is the reference.

What it costs

One background thread ticking every 20 s (Process.getElapsedCpuTime() and Debug.getPss()), push-based player listeners, chunks of at most 64 KB flushed every 30 s. The sampler pauses while the app is in the background; player events keep flowing. Vitals are never written to disk and never retried more than once.