build(deps-dev): apply updates
[e-mobility-charging-stations-simulator.git] / src / performance / PerformanceStatistics.ts
index e90595225278d3a926059a2ca3ab7821b800d644..864446c6ce30ee1bad805c65a61eec9b46755e2d 100644 (file)
@@ -1,16 +1,19 @@
 // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
 
-import { type PerformanceEntry, PerformanceObserver, performance } from 'node:perf_hooks'
+import { performance, type PerformanceEntry, PerformanceObserver } from 'node:perf_hooks'
 import type { URL } from 'node:url'
 import { parentPort } from 'node:worker_threads'
 
 import { secondsToMilliseconds } from 'date-fns'
+import { CircularBuffer } from 'mnemonist'
+import { is, mean, median } from 'rambda'
 
 import { BaseError } from '../exception/index.js'
 import {
   ConfigurationSection,
   type IncomingRequestCommand,
   type LogConfiguration,
+  MapStringifyFormat,
   MessageType,
   type RequestCommand,
   type Statistics,
@@ -19,19 +22,16 @@ import {
   type TimestampedData
 } from '../types/index.js'
 import {
-  CircularArray,
+  buildPerformanceStatisticsMessage,
   Configuration,
   Constants,
-  JSONStringifyWithMapSupport,
-  average,
-  buildPerformanceStatisticsMessage,
   extractTimeSeriesValues,
   formatDurationSeconds,
   generateUUID,
-  logPrefix,
+  JSONStringify,
   logger,
+  logPrefix,
   max,
-  median,
   min,
   nthPercentile,
   stdDeviation
@@ -107,7 +107,7 @@ export class PerformanceStatistics {
     try {
       performance.measure(name, markId)
     } catch (error) {
-      if (error instanceof Error && error.message.includes('performance mark has not been set')) {
+      if (is(Error, error) && error.message.includes('performance mark has not been set')) {
         /* Ignore */
       } else {
         throw error
@@ -179,9 +179,9 @@ export class PerformanceStatistics {
       )
     if (performanceStorageConfiguration.enabled === true) {
       logger.info(
-        `${this.logPrefix()} storage enabled: type ${performanceStorageConfiguration.type}, uri: ${
-          performanceStorageConfiguration.uri
-        }`
+        `${this.logPrefix()} storage enabled: type ${
+          performanceStorageConfiguration.type
+        }, uri: ${performanceStorageConfiguration.uri}`
       )
     }
   }
@@ -214,7 +214,7 @@ export class PerformanceStatistics {
     logger.info(this.logPrefix(), {
       ...this.statistics,
       statisticsData: JSON.parse(
-        JSONStringifyWithMapSupport(this.statistics.statisticsData)
+        JSONStringify(this.statistics.statisticsData, undefined, MapStringifyFormat.object)
       ) as Map<string | RequestCommand | IncomingRequestCommand, StatisticsData>
     })
   }
@@ -267,33 +267,40 @@ export class PerformanceStatistics {
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     this.statistics.statisticsData.get(entry.name)!.minTimeMeasurement = min(
       entry.duration,
-      this.statistics.statisticsData.get(entry.name)?.minTimeMeasurement ?? Infinity
+      this.statistics.statisticsData.get(entry.name)?.minTimeMeasurement ?? Number.POSITIVE_INFINITY
     )
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     this.statistics.statisticsData.get(entry.name)!.maxTimeMeasurement = max(
       entry.duration,
-      this.statistics.statisticsData.get(entry.name)?.maxTimeMeasurement ?? -Infinity
+      this.statistics.statisticsData.get(entry.name)?.maxTimeMeasurement ?? Number.NEGATIVE_INFINITY
     )
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     this.statistics.statisticsData.get(entry.name)!.totalTimeMeasurement =
       (this.statistics.statisticsData.get(entry.name)?.totalTimeMeasurement ?? 0) + entry.duration
-    this.statistics.statisticsData.get(entry.name)?.measurementTimeSeries instanceof CircularArray
-      ? this.statistics.statisticsData
-        .get(entry.name)
-        ?.measurementTimeSeries?.push({ timestamp: entry.startTime, value: entry.duration })
-      : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-        (this.statistics.statisticsData.get(entry.name)!.measurementTimeSeries =
-          new CircularArray<TimestampedData>(Constants.DEFAULT_CIRCULAR_BUFFER_CAPACITY, {
-            timestamp: entry.startTime,
-            value: entry.duration
-          }))
+    if (
+      !(
+        this.statistics.statisticsData.get(entry.name)?.measurementTimeSeries instanceof
+        CircularBuffer
+      )
+    ) {
+      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+      this.statistics.statisticsData.get(entry.name)!.measurementTimeSeries =
+        new CircularBuffer<TimestampedData>(
+          Array<TimestampedData>,
+          Constants.DEFAULT_CIRCULAR_BUFFER_CAPACITY
+        )
+    }
+    this.statistics.statisticsData.get(entry.name)?.measurementTimeSeries?.push({
+      timestamp: entry.startTime,
+      value: entry.duration
+    })
     const timeMeasurementValues = extractTimeSeriesValues(
       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      this.statistics.statisticsData.get(entry.name)!.measurementTimeSeries!
+      this.statistics.statisticsData.get(entry.name)!
+        .measurementTimeSeries as CircularBuffer<TimestampedData>
     )
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    this.statistics.statisticsData.get(entry.name)!.avgTimeMeasurement =
-      average(timeMeasurementValues)
+    this.statistics.statisticsData.get(entry.name)!.avgTimeMeasurement = mean(timeMeasurementValues)
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     this.statistics.statisticsData.get(entry.name)!.medTimeMeasurement =
       median(timeMeasurementValues)