query_vitals.
Vitals
The vitals of an app and release, in one view (GET /v1/projects/{projectId}/vitals):
GET /v1/projects/{projectId}/performance/series follows one of them per day or per release:
cold_start_p90, ttid_p90, network_p90, network_error_rate, hang_rate, anr_rate,
slow_frames_per_minute or frozen_frames_per_minute. A performance view covers at most 30
days.
Performance comes from sampled detail: spans and frame counts are sent only from
kept sessions, and counts and percentiles are reweighted by each session’s
sampling rate, so a span from a session kept at a rate of 1/4 counts four times.
App start
Each launch is oneapp.start span, from the start of the process (cold) or of the relaunch
(warm, hot) to the first frame of the first screen.
iOS can start an app’s process before the user opens it (prewarming). A prewarmed launch is
marked
app.start.prewarmed and measured from when the SDK starts, not from the process start,
which can be minutes earlier. Start Apsio as early as possible so the measure covers your own
launch work.
GET /v1/projects/{projectId}/performance/start breaks app start down by release, OS version,
device model or prewarming, with p50, p90, p95 and a histogram per group.
Screens
Each screen created is oneapp.screen.load span, from its creation (an activity’s onCreate,
a view controller loading its view) to its first drawn frame:
- TTID, time to initial display, is measured on its own.
- TTFD, time to full display, is when the screen shows its real content, such as the data it
loaded. Only the app knows that moment, so the app reports it:
reportFullyDrawn()on every SDK. A screen that never reports it has no TTFD; Apsio never uses TTID in its place.
GET /v1/projects/{projectId}/performance/screens lists every screen with its loads, sessions,
TTID and TTFD percentiles, and the hangs and ANRs that happened on it;
performance/screens/detail shows one screen per release and per day, with its 20 slowest loads
and their sessions.
Network
Each HTTP request is a client span with its method, its URL without the query string, its host, status, duration and error type. Request and response bodies and query strings are never recorded.
Requests are grouped by endpoint: the method, the host and a template of the path. The
template is
url.template when the app or its HTTP library sends one. Otherwise Apsio derives it
from the path, replacing every segment that looks like an identifier or personal data (numbers,
UUIDs, long hexadecimal, phone numbers, tokens, email addresses, free text) with {id}, so
GET /orders/1001 and GET /orders/1002 are one endpoint, GET /orders/{id}.
A request failed when it got a 5xx or no response at all. 4xx responses are counted on their
own, since many are expected. GET /v1/projects/{projectId}/network/endpoints lists the
endpoints with their requests, error rates and latency percentiles, and
network/endpoints/detail one endpoint’s statuses, per day and per release, with sample requests
linked to their sessions. An alert can watch an endpoint’s failure rate.
Traces
Requests made while one of your spans is open nest under it, and a span started while another is open becomes its child. To follow a request into your backend, list your own hosts infirstPartyHosts: the SDK then adds a W3C traceparent header to their requests, and only
theirs, never a third party’s.
GET /v1/projects/{projectId}/traces/{traceId} returns the device spans of one trace. Set the
project’s APM link (Settings, or PATCH /v1/orgs/{orgId}/projects/{projectId}) to an https URL
with a {trace_id} placeholder, such as https://app.datadoghq.com/apm/trace/{trace_id}, and
every trace and sample request carries apm_url, the same trace in your APM.
Hangs and ANRs
A hang (iOS) is the main thread blocked for more than 250 ms, seen by the SDK while the app runs in the foreground, without a debugger. It is recorded with the main thread’s stack, taken while it was blocked, and its duration once the thread runs again. An ANR (Android) is the main thread not answering for 5 seconds, recorded with its stack. Both are issues, grouped by the main thread’s frames in your app.- A hang that the app was killed during (by the watchdog, or a force quit) never ends. The SDK writes it to disk while it lasts and sends it at the next launch as unfinished: it counts in the hang rate, but its duration is only a lower bound, so duration percentiles leave it out.
- MetricKit reports hangs too, up to a day later, and they may be the same hangs the SDK saw. Rates and screens count only the hangs the SDK saw while the app ran, so a hang counts once; MetricKit’s add to durations and stacks.
GET /v1/projects/{projectId}/performance/hangs gives hang and ANR session rates per release
and per day, the screen of each hang, and hang durations.
Frames
The SDKs count the frames of the current screen while the app is in the foreground:- a frame is slow when it took longer than the display’s refresh interval for that frame (16.7 ms at 60 Hz, 8.3 ms at 120 Hz);
- it is frozen when it took longer than 700 ms. Slow and frozen do not overlap.
GET /v1/projects/{projectId}/performance/frames gives slow and frozen frames per release and per
screen.
MetricKit
On iOS, MetricKit’s daily reports add what the SDK cannot see from inside the app: launch and hang histograms, memory, CPU and disk, from every user’s day rather than from sampled sessions.GET /v1/projects/{projectId}/metrics/metrickit adds up one app’s histograms per release, with
estimated percentiles.