> ## Documentation Index
> Fetch the complete documentation index at: https://docs.use.observer/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure WebSocket probes

> Connect to a ws:// or wss:// endpoint and measure handshake latency, round-trip latency, or connection success.

WebSocket probes open a connection to a `ws://` or `wss://` endpoint on
the configured interval and report one of: time to open the connection,
time to receive a reply to a message you send, or a plain 1/0 for
whether the socket opened at all.

Use this for realtime backends that don't answer a normal HTTP probe:
streaming APIs, chat gateways, collaborative-editing servers, GraphQL
subscriptions, and anything that lives behind a WebSocket upgrade.

## What it measures

The probe connects, optionally sends one message and waits for a reply,
then closes the connection cleanly. It measures wall-clock time at the
agent. The connection is always closed after the measurement, so the
probe does not hold open sockets against your endpoint.

The agent uses an application message to measure round-trip time, not a
protocol-level ping. The standard WebSocket client API does not expose
ping/pong control frames, so the endpoint must echo or respond to a
message you define.

## Configuration shape

A handshake-latency probe needs only a URL:

```json theme={null}
{
  "url": "wss://stream.example.com/socket",
  "interpretation": "handshake_latency",
  "timeout_ms": 10000
}
```

A round-trip probe sends a message and waits for a matching reply:

```json theme={null}
{
  "url": "wss://stream.example.com/socket",
  "interpretation": "round_trip_latency",
  "ping_mode": "message",
  "send_message": "{\"op\":\"ping\"}",
  "expect_message": "\"op\":\"pong\"",
  "timeout_ms": 10000
}
```

## Field reference

| Field | Default | Notes |
| - | - | - |
| `url` | required | Must start with `ws://` or `wss://`. |
| `interpretation` | `handshake_latency` | What the metric value represents. See below. |
| `timeout_ms` | `10000` | Deadline for the whole probe (open, and reply when round-trip), 100 to 30000 ms. |
| `ping_mode` | `none` | `message` sends `send_message` after open. The metric form sets this for you when you pick round-trip; set it to `message` yourself only when writing the config through the API. |
| `send_message` | none | Round-trip only. The text sent once the socket opens. Required for round-trip. |
| `expect_message` | none | Round-trip only. Substring the reply must contain. Leave blank to accept any reply. |
| `protocols` | none | Optional subprotocol offer, sent as `Sec-WebSocket-Protocol`. |
| `headers` | none | Optional non-secret headers sent with the opening handshake (for example `Origin`). Credential-looking names such as `Authorization` or `Cookie` are rejected here; use `header_refs`. |
| `header_refs` | none | Secret handshake headers. Maps a header name to the **name** of an env var on the agent host. Agent 1.6.0 and later. See [Authentication](#authentication). |

## Interpretations

| Interpretation | Value | Threshold idea |
| - | - | - |
| `handshake_latency` | Milliseconds from connect to open. | Healthy: under 200, Unhealthy: over 1000 |
| `round_trip_latency` | Milliseconds from sending the message to a matching reply. Needs `send_message`. | Healthy: under 200, Unhealthy: over 1000 |
| `connection_success` | `1` if the socket opened, else `0`. Reports no\_data only for a missing or invalid `header_refs` variable. | Healthy: over 0, Unhealthy: under 1 |

Pick `connection_success` for "can a client connect at all", `handshake_latency`
for connection setup health, and `round_trip_latency` when the endpoint
echoes or answers a known message and you care about responsiveness.

## Authentication

For an endpoint that needs a token or session cookie, put the header in
`header_refs`. Each entry maps a header name to the **name of an
environment variable on the agent host**. The agent reads the value at
probe time and sends it with the opening handshake. Observer stores only
the variable name, never the token.

```json theme={null}
{
  "url": "wss://stream.example.com/socket",
  "interpretation": "handshake_latency",
  "headers": { "Origin": "https://app.example.com" },
  "header_refs": { "Authorization": "OBSERVER_STREAM_TOKEN" }
}
```

```bash theme={null}
export OBSERVER_STREAM_TOKEN="Bearer eyJhbGciOi..."
```

The env var holds the full header value, including any `Bearer `
prefix. Variable names must be `UPPER_SNAKE_CASE`, and a header can be
in `headers` or `header_refs`, not both. If the variable is unset or
blank the probe reports `no_data` with `header_ref_missing` (this
applies to `connection_success` too) and does not connect. The agent
never logs secret header values or includes them in results.

In the metric form, add a header row and turn on **Secret**, then enter
the variable name instead of a value.

<Info>
  **Agent version**

  `header_refs` requires agent 1.6.0 or later. Agents at 1.5.0 or older
  do not recognise the field and report `invalid_config` for any probe
  that uses it.
</Info>

`wss://` terminates TLS at the endpoint (or its load balancer). The
probe does not perform client-certificate authentication. If you need
mutual TLS, place it behind a sidecar that terminates mTLS, or use the
HTTP probe's mTLS support against a parallel HTTP health route.

## Reason codes

* `ws_open_failed`: the socket never opened. The endpoint refused the
  connection, rejected the handshake, or the URL is wrong. The raw error
  detail is in the metric's metadata. With `connection_success` this
  reports `0` instead of no\_data.
* `ws_handshake_timeout`: the connection did not open within
  `timeout_ms`. The endpoint may be slow, unreachable, or not speaking
  WebSocket on that path.
* `ws_reply_timeout`: the socket opened and the message was sent, but no
  reply arrived in time (round-trip only). Confirm the endpoint responds
  to `send_message`.
* `ws_closed_early`: the endpoint closed the connection before sending
  the awaited reply. The close code is in the metadata.
* `ws_reply_mismatch`: a reply arrived but did not contain
  `expect_message`. Check the endpoint's response format.
* `header_ref_missing`: an env var named in `header_refs` is not set (or
  is blank) on the agent host. The probe does not connect.
* `header_ref_invalid`: an env var named in `header_refs` holds a line
  break or control character, which is not allowed in a header.

## Troubleshooting

* **`ws_open_failed` against a working browser client.** Browsers send an
  `Origin` header and sometimes a subprotocol. If the endpoint requires
  either, set `headers` (`Origin: https://yourapp.example`) and
  `protocols` to match what the browser sends.
* **`ws_reply_timeout` but the endpoint does respond.** The endpoint may
  send a server greeting before it accepts input, or expect a specific
  first frame. Set `send_message` to the exact handshake the protocol
  expects, and `expect_message` to a substring of the known response.
* **Round-trip latency looks higher than expected.** Round-trip latency
  counts only the message round trip, from send to matching reply. Connect
  time is not included; a high value reflects how long the endpoint takes
  to answer.
* **`wss://` fails but `ws://` works.** A TLS problem at the endpoint.
  Check the certificate with a TLS certificate probe against the same
  host and port.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.