httpcheck
Fetch a URL and time every stage of it separately, because a slow resolver and a slow server wake up different people.
Parameters
| Parameter | Default | Meaning |
|---|---|---|
urlREQUIRED | http or https. | |
method | GET | |
headers | Map of request headers. | |
body | Request body, sent as-is. | |
expect_status | 200 | Any other status is down. The default is dropped when an assertion targets status; set explicitly, it applies as well. |
body_matches | RE2 pattern the body must match, else down. | |
max_ttfb | Time to first byte above this is degraded. | |
follow_redirects | true | |
assertions | Up to 20 checks on the response. All must pass, else down. See Assertions. | |
auth | none | basic, bearer, mtls or oauth_client_credentials. See Authentication. |
auth_username | User name for basic. | |
client_cert | Client certificate for mtls, inline PEM (one or more certificates), not a path. | |
oauth_token_url | Token endpoint for oauth_client_credentials. | |
oauth_client_id | Client id for oauth_client_credentials. | |
oauth_scopes | List of scopes to request. | |
oauth_params | Map of extra form fields sent to the token endpoint, such as audience. | |
oauth_client_auth | basic | How the client id and secret reach the token endpoint: basic (an Authorization header) or body (form fields). |
expect_status and body_matches work as before. A check without a status assertion behaves exactly as it did.
Assertions
Each assertion has a target, an operator and a value, which is always a string. header and jsonpath also take a property: the header name, or the JSONPath into a JSON body.
| Target | property | Operators |
|---|---|---|
status | equals, not_equals, less_than, greater_than | |
response_time_ms | equals, not_equals, less_than, greater_than | |
header | header name | all six |
jsonpath | JSONPath | all six |
body_sha256 | equals, not_equals |
The six operators are equals, not_equals, contains, matches (an RE2 pattern), less_than and greater_than. response_time_ms is total_ms: from the start of the request until the body has been read. less_than and greater_than compare numbers. body_sha256 takes 64 hex characters, in either case. body_sha256 and jsonpath read at most the first 1 MiB of the body; a larger body fails them.
with:
url: https://api.acme.example/v1/status
assertions:
- {target: status, operator: equals, value: "200"}
- {target: header, property: Content-Type, operator: contains, value: json}
- {target: jsonpath, property: $.database.state, operator: equals, value: ok}
- {target: response_time_ms, operator: less_than, value: "800"}
Assertions run in list order and stop at the first failure. That one makes the run down and is named in the result, numbered from 1, with what the response actually had (a secret the response echoes back shows as [redacted]):
assertion 2 (header Content-Type contains "json") failed: got "text/html"
The event also carries its number as the key failed_assertion (a string, "2") next to detail.
Authentication
auth | Settings | Secret |
|---|---|---|
basic | auth_username | PASSWORD |
bearer | TOKEN | |
mtls | client_cert | CLIENT_KEY, the PEM private key |
oauth_client_credentials | oauth_token_url, oauth_client_id, and optionally oauth_scopes, oauth_params, oauth_client_auth | CLIENT_SECRET |
The secret is never a with parameter. Set from the portal or the API, it is sealed at rest and write-only: reading the check back shows which secrets are set, never their values. A secret is tied to exactly where it is sent: any change to url, oauth_token_url or the method, even only the path, or a change to client_cert, without sending the secret again is refused with a 422. So is adding a region or source to sources: env: sources now include <names> the env was not sealed for; re-supply env (or send {} to clear it). Removing or reordering sources keeps it.
So authentication that needs a secret works only on checks Pingtower assigns to the agent, not on checks in a local agent.yaml. A local check naming one of these auth types is refused when the config loads:
param auth: bearer needs env TOKEN, which only a tower-assigned check carries
With basic, bearer or oauth_client_credentials, an Authorization entry in headers is refused, as is a setting that belongs to another mode. Assertions work the same in both.
With oauth_client_credentials, the agent fetches a token from oauth_token_url and reuses it until 30 seconds before it expires. If the target answers 401, the next run fetches a fresh one. The token request goes through the same network guard as the check itself.
Measurements
| Key | Unit |
|---|---|
dns_ms, connect_ms, tls_ms, ttfb_ms, total_ms | milliseconds, each stage on its own |
body_bytes | bytes |
Rules for it
{"name":"slow-ttfb","match":{"tags":["addon:httpcheck"]},
"conditions":[{"key":"ttfb_ms","op":"gte","value":500}]}
{"name":"probe-down","match":{"tags":["addon:httpcheck"],"min_level":400},
"fire_after":{"count":2,"window_minutes":5,"distinct_sources":true}}