Clients
This page is for administrators. Every dashboard tab, every page built on the SDK (such as a plant page on its own domain) and every script with an open live connection holds one /sync WebSocket. The Clients page lists them while they are open, with what each has done since it connected.
The Clients page
Open Gateway, then Clients. The list refreshes every 2 seconds. Anyone who is not an administrator sees "Only administrators can see who is connected."
Columns: Who (the user's name and email, or the API key's name), Where (the site it came in through and its address), Browser, Connected (how long), Subscriptions, Sent, Writes and State. Selecting a row opens a panel:
| Block | Facts |
|---|---|
| Connection | Site (the host the socket came through, such as app.scadex.io), Address (the client's IP as the reverse proxy reports it in X-Real-Ip or X-Forwarded-For, else the socket's own), Origin, Browser (the full user agent), Connected, Account (the principal id: a user id or apikey:<id>), Email |
| Traffic | Subscriptions, Sent and Received (messages and bytes, with the current rate per second), Last sent, Last received, Waiting to send (queued, not yet written to the socket), Dropped (frames thrown away because the client read too slowly) |
| Writes | Writes and Refused (writes the role or a replay refused) |
| Feeds | Alarms (following the alarm list, or off), Replay (watching a replay of the past, or live) |
The panel can also list the connection's subscriptions: each tag path, since when, how many values the gateway sent for it and when the last one went.
A connection whose Dropped count grows is reading too slowly; a slow client loses its oldest queued frames rather than slowing the runtime, and one that falls too far behind is disconnected. Each user may hold 32 sockets and each socket 10,000 subscriptions; see Live data.
What a connection shows about itself
The gateway records, at the upgrade request: the principal, how it authenticated (session for a cookie, apiKey for a key), the session id, the remote address, user agent, Origin, the host (X-Forwarded-Host or the request's host) and the time. Counters are kept per socket from then on and are read without stopping it. Everything is in memory and gone when the socket closes; there is no history of past connections.
The @gateway.clients tags
The same facts, minus the address and the full user agent, are published as read-only diagnostic tags so a screen can show who is connected. Anyone who can read tags can read these, which is why the address and user agent stay on the admin-only page.
| Tag | Meaning |
|---|---|
@gateway.clients.count | Open sockets |
@gateway.clients.users | Distinct principals |
@gateway.clients.subscriptions | Subscriptions over all sockets |
@gateway.clients.<id>.user | The user's email or the key's name |
@gateway.clients.<id>.role | The role at connect time |
@gateway.clients.<id>.auth | session or apiKey |
@gateway.clients.<id>.site | The host it came through |
@gateway.clients.<id>.browser | "Chrome 156 on Windows" style summary of the user agent |
@gateway.clients.<id>.connectedAt | ISO-8601 |
@gateway.clients.<id>.connectedFor | Seconds (s) |
@gateway.clients.<id>.subscriptions, .messagesIn, .messagesOut, .bytesIn (B), .bytesOut (B), .writes, .writesRefused, .dropped | Counters since connect |
@gateway.clients.<id>.alarms, .replay | Booleans |
<id> is a short id made for the socket (c followed by 10 hex characters), so each connection is a folder that appears when it opens and disappears when it closes. Like the other @gateway diagnostic tags these live in memory, are read-only and have no history; see Logs and diagnostics.
Limits
- Open connections only; nothing is kept once a socket closes.
- The page shows, it does not act: there is no button to disconnect a client or end a session. Deleting a user or revoking a key does that within 30 seconds.
- Counters restart with the socket, not with the gateway's day.
API
Both routes need the admin role. The full reference is in Admin API.
| Route | Purpose |
|---|---|
GET /api/v1/admin/clients | {at, clients: [...]} with id, principalId, authKind, name, email, role, remoteAddress, userAgent, origin, host, connectedAt, subscriptions, messagesIn, messagesOut, bytesIn, bytesOut, writes, writesRefused, dropped, queuedChars, alarms, replay, lastIn, lastOut |
GET /api/v1/admin/clients/{id}/subscriptions | {at, subscriptions: [{path, since, updates, lastUpdate}]}; 404 once the connection has closed |