Observability
This guide demonstrates the built-in observability capabilities provided by Teleportal, including Prometheus metrics endpoints, structured logging with LogTape, and server event hooks for custom monitoring.
What it demonstrates
Section titled “What it demonstrates”- Accessing the
/healthendpoint for server health checks - Accessing the
/metricsendpoint for Prometheus-compatible metrics - Accessing the
/statusendpoint for server status information - Configuring structured logging with LogTape
- Listening to server events for custom monitoring workflows
Server Setup
Section titled “Server Setup”import { Server } from "teleportal/server";import { getMetricsHandler, getHealthHandler, getStatusHandler } from "teleportal/http";
const server = new Server({ storage: async (ctx) => { // Your storage implementation return documentStorage; },});
// Expose observability endpointsapp.get("/metrics", getMetricsHandler(server));app.get("/health", getHealthHandler(server));app.get("/status", getStatusHandler(server));Metrics Endpoint
Section titled “Metrics Endpoint”The /metrics endpoint returns Prometheus-formatted metrics:
curl http://localhost:3000/metricsMetrics include:
teleportal_sessions_active: Current number of active document sessions (gauge)teleportal_clients_active: Current number of active clients (gauge)teleportal_documents_opened_total: Total documents opened (counter)teleportal_messages_total: Total messages processed, labeled bytype(counter)teleportal_messages_total_all: Total messages processed across all types, single series (counter)teleportal_message_duration_seconds: Message processing duration, labeled bytype(histogram)
Health Endpoint
Section titled “Health Endpoint”The /health endpoint returns server health status:
curl http://localhost:3000/healthResponse:
{ "status": "healthy", "timestamp": "2024-01-01T00:00:00.000Z", "checks": {}, "uptime": 3600}The endpoint always returns status: "healthy" with an empty checks object and the process uptime in seconds. The monitoring module defines only the HealthStatus and StatusData types – it does not implement any dependency health probes. checks is a placeholder you can populate by extending the server if you need liveness signals for downstream dependencies (storage, PubSub, etc.).
Status Endpoint
Section titled “Status Endpoint”The /status endpoint returns detailed operational status:
curl http://localhost:3000/statusResponse:
{ "nodeId": "node-123", "activeClients": 10, "activeSessions": 5, "pendingSessions": 0, "totalMessagesProcessed": 1000, "totalDocumentsOpened": 50, "messageTypeBreakdown": { "doc": 500, "awareness": 300, "rpc": 200 }, "rateLimitExceededTotal": 0, "rateLimitBreakdown": {}, "rateLimitTopOffenders": [], "rateLimitRecentEvents": [], "totalDocumentSizeBytes": 1048576, "documentsOverWarningThreshold": 0, "documentsOverLimit": 0, "uptime": 3600, "timestamp": "2024-01-01T00:00:00.000Z"}The messageTypeBreakdown is keyed by wire message type (doc, awareness, presence, rpc, ack) – milestone and file operations are carried over rpc, not distinct message types.
Structured Logging with LogTape
Section titled “Structured Logging with LogTape”Teleportal uses LogTape for structured logging. Following LogTape’s library guidelines, Teleportal does not configure any sinks itself – your application must set up LogTape before starting the server.
Configuring LogTape
Section titled “Configuring LogTape”import { configure, getConsoleSink, getFileSink } from "@logtape/logtape";
await configure({ sinks: { console: getConsoleSink(), file: getFileSink("teleportal.log"), }, filters: {}, loggers: [ { category: ["teleportal"], sinks: ["console", "file"], lowestLevel: "info", }, ],});Log Categories
Section titled “Log Categories”Teleportal emits all of its logs under a single category:
["teleportal", "server"]– every wide event (one structured log line per logical operation): connections, errors, message processing, and session lifecycle. Each wide event carries the environment context{ service: "teleportal" }merged in.
Because LogTape uses hierarchical categories, configuring the ["teleportal"] category (as shown above) captures these logs. Per LogTape’s library guidelines, Teleportal configures no sinks of its own – your application owns sink and level configuration.
What gets logged
Section titled “What gets logged”The server emits wide events – single structured log lines that capture the full context of an operation. Each wide event includes environment context (service name, node ID) merged with operation-specific fields such as document IDs, client IDs, message types, error details, and timing information.
Server Events
Section titled “Server Events”The Server extends Observable and emits typed events you can listen to for custom monitoring, alerting, or integration with external systems.
Listening to Events
Section titled “Listening to Events”import { Server } from "teleportal/server";
const server = new Server({ /* ... */});
server.on("document-load", (data) => { console.log("Document loaded:", data.documentId); console.log("Encrypted:", data.encrypted);});
server.on("client-connect", (data) => { console.log("Client connected:", data.clientId);});
server.on("client-disconnect", (data) => { console.log("Client disconnected:", data.clientId); console.log("Reason:", data.reason);});
server.on("document-size-warning", (data) => { // Trigger an alert when a document grows too large alerting.warn(`Document ${data.documentId} is ${data.sizeBytes} bytes`);});Available Events
Section titled “Available Events”Document events: document-load, document-unload, milestone-created, milestone-deleted, milestone-restored, document-delete, document-size-warning, document-size-limit-exceeded
Client events: client-connect, client-disconnect, client-message
Lifecycle events: before-server-shutdown, after-server-shutdown
See the Server documentation for the full event list and payload types.
Next Steps
Section titled “Next Steps”- Server - Server configuration, events, and monitoring details