diff --git a/src/databases/Postgres.ts b/src/databases/Postgres.ts index 7f65c9f..aa13f9c 100644 --- a/src/databases/Postgres.ts +++ b/src/databases/Postgres.ts @@ -16,6 +16,13 @@ types.setTypeParser(20, function(val) { return parseInt(val, 10); }); +interface PostgresStats { + activeRequests: number; + avgReadTime: number; + avgWriteTime: number; + avgFailedTime: number; +} + export interface DatabaseConfig { dbSchemaFileName: string, dbSchemaFolder: string, @@ -34,6 +41,10 @@ export class Postgres implements IDatabase { private lastPoolReadFail = 0; activePostgresRequests = 0; + readResponseTime: number[] = []; + writeResponseTime: number[] = []; + failedResponseTime: number[] = []; + maxStoredTimes = 200; constructor(private config: DatabaseConfig) {} @@ -110,6 +121,7 @@ export class Postgres implements IDatabase { throw new Error("Too many active postgres requests"); } + const start = Date.now(); const pendingQueries: PromiseWithState>[] = []; let tries = 0; let lastPool: Pool = null; @@ -128,6 +140,8 @@ export class Postgres implements IDatabase { else if (this.config.postgres.timeout) currentPromises.push(savePromiseState(timeoutPomise(this.config.postgres.timeout))); const queryResult = await nextFulfilment(currentPromises); + this.updateResponseTime(type, start); + this.activePostgresRequests--; switch (type) { case "get": { @@ -156,6 +170,7 @@ export class Postgres implements IDatabase { } } + this.updateResponseTime(type, start, this.failedResponseTime); this.activePostgresRequests--; Logger.error(`prepare (postgres) try ${tries}: ${err}`); } @@ -236,6 +251,25 @@ export class Postgres implements IDatabase { return result; } + private updateResponseTime(type: string, start: number, customArray?: number[]): void { + const responseTime = Date.now() - start; + + const array = customArray ?? (this.isReadQuery(type) ? + this.readResponseTime : this.writeResponseTime); + + array.push(responseTime); + if (array.length > this.maxStoredTimes) array.shift(); + } + + getStats(): PostgresStats { + return { + activeRequests: this.activePostgresRequests, + avgReadTime: this.readResponseTime.length > 0 ? this.readResponseTime.reduce((a, b) => a + b, 0) / this.readResponseTime.length : 0, + avgWriteTime: this.writeResponseTime.length > 0 ? this.writeResponseTime.reduce((a, b) => a + b, 0) / this.writeResponseTime.length : 0, + avgFailedTime: this.failedResponseTime.length > 0 ? this.failedResponseTime.reduce((a, b) => a + b, 0) / this.failedResponseTime.length : 0 + }; + } + highLoad() { return this.activePostgresRequests > this.config.postgres.highLoadThreshold; } diff --git a/src/routes/getStatus.ts b/src/routes/getStatus.ts index 15563b6..270e35a 100644 --- a/src/routes/getStatus.ts +++ b/src/routes/getStatus.ts @@ -44,7 +44,7 @@ export async function getStatus(req: Request, res: Response): Promise loadavg: os.loadavg().slice(1), // only return 5 & 15 minute load average statusRequests, hostname: os.hostname(), - activePostgresRequests: (db as Postgres)?.activePostgresRequests, + postgresStats: (db as Postgres)?.getStats(), redisStats: getRedisStats(), }; return value ? res.send(JSON.stringify(statusValues[value])) : res.send(statusValues);