-// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
+// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
import { type PerformanceEntry, PerformanceObserver, performance } from 'node:perf_hooks'
import type { URL } from 'node:url'
import { secondsToMilliseconds } from 'date-fns'
+import { BaseError } from '../exception/index.js'
import {
ConfigurationSection,
type IncomingRequestCommand,
MessageType,
type RequestCommand,
type Statistics,
+ type StatisticsData,
type StorageConfiguration,
type TimestampedData
} from '../types/index.js'
PerformanceStatistics
>()
- private readonly objId: string
- private readonly objName: string
+ private readonly objId: string | undefined
+ private readonly objName: string | undefined
private performanceObserver!: PerformanceObserver
private readonly statistics: Statistics
private displayInterval?: NodeJS.Timeout
this.objName = objName
this.initializePerformanceObserver()
this.statistics = {
- id: this.objId ?? 'Object id not specified',
- name: this.objName ?? 'Object name not specified',
+ id: this.objId,
+ name: this.objName,
uri: uri.toString(),
createdAt: new Date(),
statisticsData: new Map()
}
public static getInstance (
- objId: string,
- objName: string,
- uri: URL
+ objId: string | undefined,
+ objName: string | undefined,
+ uri: URL | undefined
): PerformanceStatistics | undefined {
+ if (objId == null) {
+ const errMsg = 'Cannot get performance statistics instance without specifying object id'
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
+ throw new BaseError(errMsg)
+ }
+ if (objName == null) {
+ const errMsg = 'Cannot get performance statistics instance without specifying object name'
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
+ throw new BaseError(errMsg)
+ }
+ if (uri == null) {
+ const errMsg = 'Cannot get performance statistics instance without specifying object uri'
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
+ throw new BaseError(errMsg)
+ }
if (!PerformanceStatistics.instances.has(objId)) {
PerformanceStatistics.instances.set(objId, new PerformanceStatistics(objId, objName, uri))
}
return PerformanceStatistics.instances.get(objId)
}
+ public static deleteInstance (objId: string | undefined): boolean {
+ if (objId == null) {
+ const errMsg = 'Cannot delete performance statistics instance without specifying object id'
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
+ throw new BaseError(errMsg)
+ }
+ return PerformanceStatistics.instances.delete(objId)
+ }
+
public static beginMeasure (id: string): string {
const markId = `${id.charAt(0).toUpperCase()}${id.slice(1)}~${generateUUID()}`
performance.mark(markId)
performance.measure(name, markId)
} catch (error) {
if (error instanceof Error && error.message.includes('performance mark has not been set')) {
- /** Ignore */
+ /* Ignore */
} else {
throw error
}
this.stopLogStatisticsInterval()
performance.clearMarks()
performance.clearMeasures()
- this.performanceObserver?.disconnect()
+ this.performanceObserver.disconnect()
}
public restart (): void {
}
private initializePerformanceObserver (): void {
- this.performanceObserver = new PerformanceObserver((performanceObserverList) => {
+ this.performanceObserver = new PerformanceObserver(performanceObserverList => {
const lastPerformanceEntry = performanceObserverList.getEntries()[0]
// logger.debug(
// `${this.logPrefix()} '${lastPerformanceEntry.name}' performance entry: %j`,
}
private logStatistics (): void {
- logger.info(`${this.logPrefix()}`, {
+ logger.info(this.logPrefix(), {
...this.statistics,
- statisticsData: JSONStringifyWithMapSupport(this.statistics.statisticsData)
+ statisticsData: JSON.parse(
+ JSONStringifyWithMapSupport(this.statistics.statisticsData)
+ ) as Map<string | RequestCommand | IncomingRequestCommand, StatisticsData>
})
}
}
}
+ private static readonly logPrefix = (): string => {
+ return logPrefix(' Performance statistics')
+ }
+
private readonly logPrefix = (): string => {
return logPrefix(` ${this.objName} | Performance statistics`)
}