Skip to main content

Module diagnostics

Module diagnostics 

Source
Expand description

JSON diagnostics contract.

Every constant in diagnostics::route is a GET endpoint returning 200 OK JSON on success.

§Routes and Parameters

requestJSON responseparameter source
GET /internal/diagnostics/summaryone diagnostics::DiagnosticsSummaryResponsenone
GET /internal/diagnostics/roomsarray of diagnostics::DiagnosticsRoomSummarynone
GET /internal/diagnostics/workersarray of diagnostics::DiagnosticsWorkerSummarynone
GET /internal/diagnostics/rooms/{uuid}one diagnostics::DiagnosticsRoomDetailuuid from the rooms response
GET /internal/diagnostics/rooms/{uuid}/usersarray of diagnostics::DiagnosticsUserSummaryuuid from the rooms response
GET /internal/diagnostics/rooms/{uuid}/users/{id}one diagnostics::DiagnosticsUserDetailuuid from rooms and userKey from room users
GET /internal/diagnostics/node-graph/rooms/{uuid}{ "nodes": [], "edges": [] }uuid from the rooms response
GET /internal/diagnostics/node-graph/rooms/{uuid}/users/{id}{ "nodes": [], "edges": [] }uuid from rooms and userKey from room users

userId may be a JSON number or string. userKey is always the string to put into {id}. URL-encode both path values before substitution.

§Summary Request and Response over HTTPS

GET /internal/diagnostics/summary HTTP/1.1
Host: o-sfu-observability.internal
Authorization: Bearer <diagnostics-token>
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{
  "roomsActive": 1,
  "publicationsActive": 1,
  "recordingRoomsActive": 0,
  "usersActive": 2,
  "subscriptionsActive": 1,
  "transport": {
    "connectedUsers": 2,
    "disconnectedUsers": 0,
    "totalUsers": 2,
    "unknownUsers": 0
  }
}

§JavaScript Fetch Example

const origin = "https://o-sfu-observability.internal";
const headers = {
  Authorization: `Bearer ${process.env.DIAGNOSTICS_AUTH_TOKEN}`,
};

async function getJson(path) {
  const response = await fetch(`${origin}${path}`, { headers });
  if (!response.ok) {
    throw new Error(`${response.status} ${await response.text()}`);
  }
  return response.json();
}

async function main() {
  const rooms = await getJson("/internal/diagnostics/rooms");
  const roomUuid = encodeURIComponent(rooms[0].uuid);
  const room = await getJson(`/internal/diagnostics/rooms/${roomUuid}`);
  const users = await getJson(`/internal/diagnostics/rooms/${roomUuid}/users`);
  const userKey = encodeURIComponent(users[0].userKey);
  const graph = await getJson(
    `/internal/diagnostics/node-graph/rooms/${roomUuid}/users/${userKey}`,
  );

  console.log(room.summary, room.users, room.sources);
  console.log(graph.nodes, graph.edges);
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

The rooms response has this shape.

[
  {
    "createDate": "2026-07-15T10:20:30.000Z",
    "mediaWorkerId": 0,
    "publicationCount": 1,
    "recordingState": {
      "recording": false,
      "audio": false,
      "transcription": false,
      "video": false
    },
    "remoteAddress": "203.0.113.10",
    "sourceCount": 1,
    "userCount": 2,
    "subscriptionCount": 1,
    "transport": {
      "connectedUsers": 2,
      "disconnectedUsers": 0,
      "totalUsers": 2,
      "unknownUsers": 0
    },
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "webRtcEnabled": true
  }
]

The room users response has this shape.

[
  {
    "audioIncomingBitrateBps": 32000,
    "cameraIncomingBitrateBps": 600000,
    "connectionId": 91,
    "health": "connected",
    "incomingBitrateBps": 632000,
    "mediaWorkerId": 0,
    "publicationCount": 2,
    "roomId": "550e8400-e29b-41d4-a716-446655440000",
    "screenIncomingBitrateBps": 0,
    "subscriptionCount": 1,
    "userId": 42,
    "userKey": "42"
  }
]

The response structs below list every field in each payload. Wire names are camelCase unless a field documents an exception.

User detail is room-scoped because the same user key can be active in several rooms.

Modules§

route
Diagnostics GET routes.

Structs§

DiagnosticsRoomDetail
DiagnosticsRoomSummary
DiagnosticsSummaryResponse
DiagnosticsUserDetail
DiagnosticsUserSummary
DiagnosticsWorkerSummary