@amadeus-it-group/ngrx-devtool 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -561,18 +561,23 @@ class PerformanceTrackerService {
561
561
  thresholds = DEFAULT_THRESHOLDS;
562
562
  firstActionTime = null;
563
563
  measureRenderTime(actionType, reducer, callback) {
564
- const startTime = performance.now();
564
+ const renderStartTime = performance.now();
565
+ const reducerStartTime = performance.now();
565
566
  const nextState = reducer();
567
+ const reducerTime = parseFloat((performance.now() - reducerStartTime).toFixed(2));
568
+ const stateSize = this.getSerializedSize(nextState);
566
569
  if (!this.isBrowser) {
567
- callback(0);
570
+ callback(0, reducerTime, stateSize);
568
571
  return nextState;
569
572
  }
570
573
  afterNextRender(() => {
571
- const renderTime = parseFloat((performance.now() - startTime).toFixed(2));
574
+ const renderTime = parseFloat((performance.now() - renderStartTime).toFixed(2));
572
575
  const entry = {
573
576
  actionType,
574
577
  timestamp: Date.now(),
575
578
  renderTime,
579
+ reducerTime,
580
+ stateSize,
576
581
  };
577
582
  this.entries.push(entry);
578
583
  if (this.firstActionTime === null) {
@@ -581,7 +586,7 @@ class PerformanceTrackerService {
581
586
  if (this.entries.length > ENTRIES_MAX_SIZE) {
582
587
  this.entries = this.entries.slice(-ENTRIES_TRIM_SIZE);
583
588
  }
584
- callback(renderTime);
589
+ callback(renderTime, reducerTime, stateSize);
585
590
  }, { injector: this.injector });
586
591
  return nextState;
587
592
  }
@@ -611,17 +616,26 @@ class PerformanceTrackerService {
611
616
  getAggregatedStats() {
612
617
  const stats = this.getStats();
613
618
  const actionTypeStats = this.getActionTypeStats();
619
+ const reducerTimes = this.entries.map(entry => entry.reducerTime ?? entry.renderTime);
620
+ const avgReducerTime = reducerTimes.length
621
+ ? reducerTimes.reduce((total, time) => total + time, 0) / reducerTimes.length
622
+ : 0;
623
+ const maxReducerTime = reducerTimes.length ? Math.max(...reducerTimes) : 0;
624
+ const slowestReducer = this.entries.reduce((slowest, entry) => !slowest || (entry.reducerTime ?? entry.renderTime) > (slowest.reducerTime ?? slowest.renderTime)
625
+ ? entry
626
+ : slowest, null);
627
+ const currentStateSize = this.entries.at(-1)?.stateSize ?? 0;
614
628
  const elapsedTime = this.firstActionTime
615
629
  ? (Date.now() - this.firstActionTime) / 1000
616
630
  : 1;
617
631
  return {
618
632
  totalActions: stats.totalActions,
619
- avgReducerTime: stats.avgRenderTime,
620
- maxReducerTime: stats.maxRenderTime,
621
- slowestAction: stats.slowestAction,
622
- currentStateSize: 0,
633
+ avgReducerTime,
634
+ maxReducerTime,
635
+ slowestAction: slowestReducer?.actionType ?? null,
636
+ currentStateSize,
623
637
  actionsPerSecond: stats.totalActions / Math.max(elapsedTime, 1),
624
- performanceScore: this.calculatePerformanceScore(stats),
638
+ performanceScore: this.calculatePerformanceScore(avgReducerTime, maxReducerTime),
625
639
  actionTypeStats,
626
640
  };
627
641
  }
@@ -665,36 +679,46 @@ class PerformanceTrackerService {
665
679
  getActionTypeStats() {
666
680
  const statsMap = new Map();
667
681
  for (const entry of this.entries) {
682
+ const reducerTime = entry.reducerTime ?? entry.renderTime;
668
683
  const existing = statsMap.get(entry.actionType);
669
684
  if (existing) {
670
685
  existing.count++;
671
- existing.totalTime += entry.renderTime;
686
+ existing.totalTime += reducerTime;
672
687
  existing.avgTime = existing.totalTime / existing.count;
673
- existing.maxTime = Math.max(existing.maxTime, entry.renderTime);
688
+ existing.maxTime = Math.max(existing.maxTime, reducerTime);
674
689
  existing.lastExecuted = entry.timestamp;
675
690
  }
676
691
  else {
677
692
  statsMap.set(entry.actionType, {
678
693
  count: 1,
679
- totalTime: entry.renderTime,
680
- avgTime: entry.renderTime,
681
- maxTime: entry.renderTime,
694
+ totalTime: reducerTime,
695
+ avgTime: reducerTime,
696
+ maxTime: reducerTime,
682
697
  lastExecuted: entry.timestamp,
683
698
  });
684
699
  }
685
700
  }
686
701
  return statsMap;
687
702
  }
688
- calculatePerformanceScore(stats) {
703
+ calculatePerformanceScore(avgReducerTime, maxReducerTime) {
689
704
  let score = 100;
690
- if (stats.avgRenderTime > this.thresholds.maxReducerTime) {
691
- score -= Math.min(30, (stats.avgRenderTime - this.thresholds.maxReducerTime) * 2);
705
+ if (avgReducerTime > this.thresholds.maxReducerTime) {
706
+ score -= Math.min(30, (avgReducerTime - this.thresholds.maxReducerTime) * 2);
692
707
  }
693
- if (stats.maxRenderTime > this.thresholds.maxReducerTime * 2) {
694
- score -= Math.min(20, (stats.maxRenderTime - this.thresholds.maxReducerTime * 2) / 2);
708
+ if (maxReducerTime > this.thresholds.maxReducerTime * 2) {
709
+ score -= Math.min(20, (maxReducerTime - this.thresholds.maxReducerTime * 2) / 2);
695
710
  }
696
711
  return Math.max(0, Math.round(score));
697
712
  }
713
+ getSerializedSize(value) {
714
+ try {
715
+ const serialized = JSON.stringify(value);
716
+ return serialized === undefined ? 0 : new TextEncoder().encode(serialized).byteLength;
717
+ }
718
+ catch {
719
+ return 0;
720
+ }
721
+ }
698
722
  maxSeverity(a, b) {
699
723
  const order = { low: 0, medium: 1, high: 2 };
700
724
  return order[a] >= order[b] ? a : b;
@@ -1330,14 +1354,14 @@ function createDevToolMetaReducer(wsUrlOrConfig = DEFAULT_WS_URL) {
1330
1354
  const timestamp = new Date().toISOString();
1331
1355
  let nextState;
1332
1356
  if (enablePerf) {
1333
- nextState = performanceTracker.measureRenderTime(action.type, () => reducer(state, action), (renderTime) => {
1357
+ nextState = performanceTracker.measureRenderTime(action.type, () => reducer(state, action), (renderTime, reducerTime, stateSize) => {
1334
1358
  const message = {
1335
1359
  type: 'STATE_CHANGE',
1336
1360
  action,
1337
1361
  prevState,
1338
1362
  nextState,
1339
1363
  timestamp,
1340
- renderPerformance: { renderTime }
1364
+ renderPerformance: { renderTime, reducerTime, stateSize }
1341
1365
  };
1342
1366
  webSocketService.send(message);
1343
1367
  });