feat: add sessions stats endpoint

This commit is contained in:
Carlos Valente
2024-10-20 22:19:33 +02:00
committed by Carlos Valente
parent 71c468d069
commit 82810f1cb1
8 changed files with 71 additions and 3 deletions
@@ -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) {
@@ -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(
@@ -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 });
@@ -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();
@@ -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);
@@ -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
@@ -19,10 +19,13 @@ 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 {
@@ -30,6 +33,10 @@ export function dispatchFromAdapter(type: string, payload: unknown, _source?: 'o
}
}
export function getLastRequest() {
return lastRequest;
}
type ActionHandler = (payload: unknown) => { payload: unknown };
const actionHandlers: Record<string, ActionHandler> = {
@@ -293,6 +293,10 @@ class RuntimeService {
return success;
}
public getRuntimeState() {
return { playback: runtimeState.getState().timer.playback };
}
/**
* starts event matching given ID
* @param {string} eventId
@@ -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;
+1
View File
@@ -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';