Skip to content

Response Metadata

Each response record includes structured metadata for DNS resolution, TLS session details, redirect tracking, and a full timing breakdown.


DNS metadata

The dns object is always present on a response record. It captures the addresses resolved for the call's hostname.

Field Type Description
resolvedIps array of strings All addresses returned by the OS resolver, in order. Never omitted; at minimum a single-element array.
resolvedIp string \| null The address the executor actually connected to. Typically resolvedIps[0], but may differ if the executor iterated through addresses after a connect failure.
{
  "resolvedIps": ["93.184.216.34", "2606:2800:220:1:248:1893:25c8:1946"],
  "resolvedIp": "93.184.216.34"
}

The executor populates these fields and nothing more. It performs no interpretation (no geolocation, no blocklist checks) -- that is extension territory.


TLS metadata

The tls object is present for HTTPS calls and null for plain HTTP.

Field Type Description
protocol string Negotiated TLS protocol version, e.g. "TLSv1.2", "TLSv1.3".
cipher string Negotiated cipher suite name, e.g. "TLS_AES_256_GCM_SHA384".
alpn string \| null Negotiated ALPN protocol (e.g. "h2", "http/1.1") or null if no ALPN was negotiated.
certificate object \| null Peer certificate metadata, or null when the runtime cannot expose it.

TLS example

{
  "protocol": "TLSv1.3",
  "cipher": "TLS_AES_256_GCM_SHA384",
  "alpn": "h2"
}
{
  "protocol": "TLSv1.3",
  "cipher": "TLS_AES_256_GCM_SHA384",
  "alpn": "h2",
  "certificate": {
    "subject": {
      "cn": "api.example.com"
    },
    "subjectAltNames": [
      "DNS:api.example.com",
      "DNS:www.example.com"
    ],
    "issuer": {
      "cn": "R3"
    },
    "notBefore": "2024-01-01T00:00:00Z",
    "notAfter": "2024-07-01T00:00:00Z"
  }
}

Certificate fields

When certificate is not null, it contains:

Field Type Description
subject object Subject distinguished name. Always includes cn (common name). May include additional fields.
subjectAltNames array of strings SAN entries as DNS:name or IP:addr tokens.
issuer object Issuer distinguished name. Always includes cn. May include additional fields.
notBefore string (ISO 8601) Certificate validity start (UTC).
notAfter string (ISO 8601) Certificate validity end (UTC).

When certificate is null

When the executor is configured with rejectInvalidCerts: false, some runtimes cannot expose the parsed certificate. In that case certificate is null, but protocol, cipher, and alpn are still populated. The tls object itself is never omitted for HTTPS calls -- only certificate within it may be null.

Plain HTTP

For plain HTTP calls, tls is null and tlsMs is 0:

{
  "status": 200,
  "statusText": "OK",
  "bodyPath": "/probe_runs/abc/call_0_response.txt",
  "responseTimeMs": 85,
  "tls": null
}
{
  "status": 200,
  "statusText": "OK",
  "headers": {
    "content-type": "text/plain"
  },
  "bodyPath": "/probe_runs/abc/call_0_response.txt",
  "responseTimeMs": 85,
  "dnsMs": 8,
  "connectMs": 22,
  "tlsMs": 0,
  "ttfbMs": 70,
  "transferMs": 15,
  "sizeBytes": 128,
  "dns": {
    "resolvedIps": [
      "10.0.0.5"
    ],
    "resolvedIp": "10.0.0.5"
  },
  "tls": null
}

Redirect tracking

The redirects field on each call record is an ordered array of URLs followed during the request. It is an empty array when the call issued no redirects.

{
  "redirects": [
    "https://example.com/old-path",
    "https://example.com/new-path",
    "https://example.com/final"
  ]
}

The array is populated even when a REDIRECTS_MAX_LIMIT hard-fail occurs, so you can inspect the chain that led to the failure.

Redirect following is controlled by the call config:

{
  "config": {
    "redirects": { "follow": true, "max": 10 }
  }
}

When follow is false, no redirects are followed and the array is always empty.


Timing breakdown

Every response record includes a set of timing fields that break down the total response time into phases. All values are integers in milliseconds.

Field Description
responseTimeMs Total response time from request start to response complete.
dnsMs Time spent on DNS resolution.
connectMs Time spent establishing the TCP connection.
tlsMs Time spent on TLS handshake. 0 for non-HTTPS calls.
ttfbMs Time to first byte -- from sending the request to receiving the first byte of the response.
transferMs Time spent transferring the response body.
sizeBytes Total response body size in bytes.

Timing example

{
  "responseTimeMs": 145,
  "dnsMs": 12,
  "connectMs": 34,
  "tlsMs": 28,
  "ttfbMs": 98,
  "transferMs": 47,
  "sizeBytes": 1024
}

These timing fields are also available as assertion scopes in the Lace language (e.g. .expect(dns: 100) asserts that DNS resolution took at most 100ms).