5. Device clock
Device clocks drift and can be set by hand. The backend needs the device’s idea of “now” at send time to correct every timestamp in a batch.
5.1 On the device
Section titled “5.1 On the device”- MUST send the device time at the moment of sending in the
Apsio-Sent-Atheader, in Unix nanoseconds, as a decimal string. - A retry MUST update
Apsio-Sent-Atto the time of that attempt. It is the one value that changes between retries; the body and the batch id do not. - MUST NOT adjust record timestamps on the device.
- An upload omits
Apsio-Sent-Atonly when no SDK code runs at send time, because the operating system sends it on the SDK’s behalf (a backgroundURLSessionon Apple platforms). Such an upload leaves at a time the SDK cannot know, and MUST omit the header rather than send a stale value, which would make the backend shift every timestamp by the delay; the backend then stores the original times uncorrected. - Every other upload, including one made by SDK code in a background job (a WorkManager
job on Android), MUST set
Apsio-Sent-Atat the time it sends.
5.2 On the backend
Section titled “5.2 On the backend”For each request, the backend computes:
offset = received_at − sent_atwhere received_at is the backend’s own clock when the request arrived and sent_at is
Apsio-Sent-At. For every record in the request it then stores three times:
| Time | Value |
|---|---|
| Original | The record’s timestamp, exactly as sent |
| Observed | received_at |
| Corrected | original + offset when ` |
- A backend MUST store the original and observed times unchanged.
- The 2-minute threshold exists because a small offset is mostly network latency; correcting it would add jitter between batches.
- The same
offsetapplies to every timestamp of a record:timeUnixNanoandobservedTimeUnixNanoof logs, start and end of spans, start and end of metric points, and timestamp attributes such asapsio.session.start_time. - When
Apsio-Sent-Atis missing or not a valid integer, the corrected time equals the original and the backend records that no correction was possible. - A record whose corrected time is more than 1 hour after
received_atis in the future even after correction; a backend MAY clamp it toreceived_atand MUST keep the original.