Skip to content

Commit

Permalink
feat: add sessions stats endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
cpvalente committed Oct 20, 2024
1 parent 71c468d commit 82810f1
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 3 deletions.
9 changes: 9 additions & 0 deletions apps/server/src/adapters/WebsocketAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class SocketServer implements IAdapter {

private wss: WebSocketServer | null;
private readonly clients: Map<string, Client>;
private lastConnection: Date | null = null;

constructor() {
if (instance) {
Expand All @@ -58,6 +59,7 @@ export class SocketServer implements IAdapter {
path: '',
});

this.lastConnection = new Date();
logger.info(LogOrigin.Client, `${this.clients.size} Connections with new: ${clientId}`);

ws.send(
Expand Down Expand Up @@ -171,6 +173,13 @@ export class SocketServer implements IAdapter {
});
}

getStats() {
return {
connectedClients: this.clients.size,
lastConnection: this.lastConnection,
};
}

private sendClientList(): void {
const payload = Object.fromEntries(this.clients.entries());
this.sendAsJson({ type: 'client-list', payload });
Expand Down
12 changes: 11 additions & 1 deletion apps/server/src/api-data/session/session.controller.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { getErrorMessage } from 'ontime-utils';
import { ErrorResponse, GetInfo } from 'ontime-types';
import { ErrorResponse, GetInfo, SessionStats } from 'ontime-types';

import type { Request, Response } from 'express';

import * as sessionService from './session.service.js';

export async function getSessionStats(_req: Request, res: Response<SessionStats | ErrorResponse>) {
try {
const stats = await sessionService.getSessionStats();
res.status(200).send(stats);
} catch (error) {
const message = getErrorMessage(error);
res.status(500).send({ message });
}
}

export async function getInfo(_req: Request, res: Response<GetInfo | ErrorResponse>) {
try {
const info = await sessionService.getInfo();
Expand Down
3 changes: 2 additions & 1 deletion apps/server/src/api-data/session/session.router.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import express from 'express';

import { getInfo } from './session.controller.js';
import { getInfo, getSessionStats } from './session.controller.js';

export const router = express.Router();

router.get('/', getSessionStats);
router.get('/info', getInfo);
26 changes: 25 additions & 1 deletion apps/server/src/api-data/session/session.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
import { GetInfo } from 'ontime-types';
import { GetInfo, SessionStats } from 'ontime-types';

import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
import { publicFiles } from '../../setup/index.js';
import { getNetworkInterfaces } from '../../utils/networkInterfaces.js';
import { socket } from '../../adapters/WebsocketAdapter.js';
import { getLastRequest } from '../../api-integration/integration.controller.js';
import { getLastLoadedProject } from '../../services/app-state-service/AppStateService.js';
import { runtimeService } from '../../services/runtime-service/RuntimeService.js';

const startedAt = new Date();

/** Gathers information related to runtime */
export async function getSessionStats(): Promise<SessionStats> {
const { connectedClients, lastConnection } = socket.getStats();
const lastRequest = getLastRequest();
const projectName = await getLastLoadedProject();
const { playback } = runtimeService.getRuntimeState();

return {
startedAt: startedAt.toISOString(),
connectedClients,
lastConnection: lastConnection !== null ? lastConnection.toISOString() : null,
lastRequest: lastRequest !== null ? lastRequest.toISOString() : null,
projectName,
playback,
timezone: startedAt.getTimezoneOffset(),
};
}

/**
* Adds business logic to gathering data for the info endpoint
Expand Down
7 changes: 7 additions & 0 deletions apps/server/src/api-integration/integration.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,24 @@ import { willCauseRegeneration } from '../services/rundown-service/rundownCacheU
import { handleLegacyMessageConversion } from './integration.legacy.js';

const throttledUpdateEvent = throttle(updateEvent, 20);
let lastRequest: Date | null = null;

export function dispatchFromAdapter(type: string, payload: unknown, _source?: 'osc' | 'ws' | 'http') {
const action = type.toLowerCase();
const handler = actionHandlers[action];
lastRequest = new Date();

if (handler) {
return handler(payload);
} else {
throw new Error(`Unhandled message ${type}`);
}
}

export function getLastRequest() {
return lastRequest;
}

type ActionHandler = (payload: unknown) => { payload: unknown };

const actionHandlers: Record<string, ActionHandler> = {
Expand Down
4 changes: 4 additions & 0 deletions apps/server/src/services/runtime-service/RuntimeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ class RuntimeService {
return success;
}

public getRuntimeState() {
return { playback: runtimeState.getState().timer.playback };
}

/**
* starts event matching given ID
* @param {string} eventId
Expand Down
12 changes: 12 additions & 0 deletions packages/types/src/api/ontime-controller/BackendResponse.type.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import type { OSCSettings } from '../../definitions/core/OscSettings.type.js';
import type { OntimeRundown } from '../../definitions/core/Rundown.type.js';
import type { Playback } from '../../definitions/runtime/Playback.type.js';
import type { MaybeString } from '../../utils/utils.type.js';

export type NetworkInterface = {
name: string;
address: string;
};

export interface SessionStats {
startedAt: string;
connectedClients: number;
lastConnection: MaybeString;
lastRequest: MaybeString;
projectName: string;
playback: Playback;
timezone: number;
}

export interface GetInfo {
networkInterfaces: NetworkInterface[];
version: string;
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export type {
ProjectFileListResponse,
MessageResponse,
RundownPaginated,
SessionStats,
} from './api/ontime-controller/BackendResponse.type.js';
export type { RundownCached, NormalisedRundown } from './api/rundown-controller/BackendResponse.type.js';

Expand Down

0 comments on commit 82810f1

Please sign in to comment.