@nxtedition/lib 28.0.11 → 28.0.13

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.
Files changed (2) hide show
  1. package/app.js +322 -307
  2. package/package.json +3 -3
package/app.js CHANGED
@@ -30,7 +30,6 @@ import { makeCouch } from './couch.js'
30
30
  import { makeTemplateCompiler } from '@nxtedition/template'
31
31
  import { makeDeepstream } from './deepstream.js'
32
32
  import * as rxjs from 'rxjs'
33
- import rx from 'rxjs/operators'
34
33
  import hashString from './hash.js'
35
34
  import { makeTrace } from './trace.js'
36
35
  import { compose, createServer } from './http.js'
@@ -615,40 +614,40 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
615
614
  compiler = makeTemplateCompiler({ ds, logger, ...appConfig.compiler })
616
615
  }
617
616
 
618
- const monitorProviders = {}
617
+ const monitorProviders = {
618
+ stats$: new rxjs.BehaviorSubject({}),
619
+ status$: new rxjs.BehaviorSubject({ messages: [] }),
620
+ }
619
621
 
620
- let stats$
621
622
  if (appConfig.stats) {
623
+ let stats$
624
+
622
625
  if (typeof appConfig.stats.subscribe === 'function') {
623
626
  stats$ = appConfig.stats
624
627
  } else if (typeof appConfig.stats === 'function') {
625
628
  stats$ = rxjs.timer(0, 10e3).pipe(
626
- rx.exhaustMap(() => {
629
+ rxjs.exhaustMap(() => {
627
630
  const ret = appConfig.stats({ ds, couch, logger })
628
631
  return ret?.then || ret?.subscribe ? ret : rxjs.of(ret)
629
632
  }),
630
633
  )
631
634
  } else if (typeof appConfig.stats === 'object') {
632
- stats$ = rxjs.timer(0, 10e3).pipe(rx.map(() => appConfig.stats))
635
+ stats$ = rxjs.timer(0, 10e3).pipe(rxjs.map(() => appConfig.stats))
633
636
  } else {
634
- stats$ = rxjs.timer(0, 10e3).pipe(rx.map(() => ({})))
637
+ stats$ = rxjs.timer(0, 10e3).pipe(rxjs.map(() => ({})))
635
638
  }
636
639
 
637
640
  let statsMap
638
641
 
639
642
  const startTime = Date.now()
640
- stats$ = stats$.pipe(
641
- rx.map((x) => ({
642
- ...x,
643
- uptime: Date.now() - startTime,
644
- timestamp: Date.now(),
645
- })),
646
- rx.auditTime(1e3),
647
- rx.withLatestFrom(
648
- rxjs.timer(0, 1e3).pipe(
649
- rx.map(() => performance.eventLoopUtilization?.()),
650
- rx.pairwise(),
651
- rx.map(([elu1, elu2]) => {
643
+
644
+ appDestroyers.unshift(
645
+ rxjs
646
+ .timer(0, 1e3)
647
+ .pipe(
648
+ rxjs.map(() => performance.eventLoopUtilization?.()),
649
+ rxjs.pairwise(),
650
+ rxjs.map(([elu1, elu2]) => {
652
651
  const mem = process.memoryUsage()
653
652
  const cpu = process.cpuUsage()
654
653
 
@@ -660,24 +659,27 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
660
659
  arrayBuffers: mem.arrayBuffers,
661
660
  containerLimit: getContainerMemoryLimit(),
662
661
  containerUsage: getContainerMemoryUsage(),
663
- totalHeapTotal: 0,
664
- totalHeapUsed: 0,
665
- totalExternal: 0,
666
- totalArrayBuffers: 0,
667
662
  }
668
663
 
669
664
  const http = {
670
665
  userAgent,
671
666
  pending: globalThis._nxt_lib_http_pending?.size,
672
- totalPending: 0,
673
667
  }
674
668
 
675
669
  const undici = {
676
670
  sockets: globalThis.__undici_sockets?.size ?? 0,
677
- totalSockets: 0,
678
671
  }
679
672
 
680
673
  if (statsMap) {
674
+ memory.totalHeapTotal = 0
675
+ memory.totalHeapUsed = 0
676
+ memory.totalExternal = 0
677
+ memory.totalArrayBuffers = 0
678
+
679
+ http.totalPending = 0
680
+
681
+ undici.totalSockets = 0
682
+
681
683
  for (const stats of statsMap.values()) {
682
684
  memory.totalHeapTotal += stats.memory?.heapTotal ?? 0
683
685
  memory.totalHeapUsed += stats.memory?.heapUsed ?? 0
@@ -690,7 +692,10 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
690
692
  }
691
693
  }
692
694
 
695
+ const now = Date.now()
693
696
  return {
697
+ uptime: now - startTime,
698
+ timestamp: now,
694
699
  ds: ds?.stats,
695
700
  couch: couch?.stats,
696
701
  lag: toobusy?.lag(),
@@ -706,45 +711,56 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
706
711
  undici,
707
712
  }
708
713
  }),
709
- ),
710
- ),
711
- rx.map(([serviceStats, appStats]) => ({
712
- ...appStats,
713
- [serviceName]: serviceStats,
714
- })),
715
- rx.retryWhen((err$) =>
716
- err$.pipe(
717
- rx.tap((err) => logger.error({ err }, 'monitor.stats')),
718
- rx.delay(10e3),
719
- ),
720
- ),
721
- rx.startWith({}),
722
- rx.publishReplay(1),
723
- rx.refCount(),
714
+ rxjs.withLatestFrom(stats$.pipe(rxjs.startWith({}))),
715
+ rxjs.map(([appStats, serviceStats]) => ({
716
+ ...appStats,
717
+ // TODO (fix): [serviceName] is not great and can collide.
718
+ [serviceName]: serviceStats,
719
+ })),
720
+ rxjs.retry({
721
+ delay(err, retryCount) {
722
+ logger.error({ err, retryCount }, 'monitor.stats$ failed')
723
+ return rxjs.timer(10e3)
724
+ },
725
+ }),
726
+ )
727
+ .subscribe(monitorProviders.stats$),
724
728
  )
725
729
 
726
730
  const statsBC = new BroadcastChannel('nxt:app:stats').unref()
731
+
727
732
  if (isMainThread) {
728
733
  statsMap = new Map()
729
734
  statsBC.onmessage = ({ data: { data, id } }) => {
730
- statsMap.set(id, data)
735
+ if (data != null) {
736
+ statsMap.set(id, data)
737
+ } else {
738
+ statsMap.delete(id)
739
+ }
731
740
  }
732
741
  }
733
742
 
734
- monitorProviders.stats$ = stats$
743
+ appDestroyers.unshift(
744
+ monitorProviders.stats$
745
+ .subscribe((stats) => {
746
+ statsBC.postMessage({ id: threadId, data: stats })
747
+ })
748
+ .add(() => {
749
+ statsBC.postMessage({ id: threadId, data: undefined })
750
+ }),
751
+ )
735
752
 
736
753
  if (process.env.NODE_ENV === 'production') {
737
754
  appDestroyers.unshift(
738
- stats$.pipe(rx.auditTime(10e3)).subscribe((stats) => {
739
- statsBC.postMessage({ id: threadId, data: stats })
755
+ monitorProviders.stats$.pipe(rxjs.auditTime(10e3)).subscribe((stats) => {
740
756
  logger.debug(stats, 'STATS')
741
757
  }),
742
758
  )
743
759
  }
744
760
  }
745
761
 
746
- let status$
747
762
  if (appConfig.status) {
763
+ let status$
748
764
  if (appConfig.status.subscribe) {
749
765
  status$ = appConfig.status
750
766
  } else if (typeof appConfig.status === 'function') {
@@ -754,294 +770,293 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
754
770
  return ret?.then || ret?.subscribe ? ret : rxjs.of(ret)
755
771
  })
756
772
  .pipe(
757
- rx.catchError((err) => rxjs.of({ warnings: [err.message] })),
758
- rx.repeatWhen(() => rxjs.timer(10e3)),
773
+ rxjs.catchError((err) => rxjs.of({ warnings: [err.message] })),
774
+ rxjs.repeatWhen(() => rxjs.timer(10e3)),
759
775
  )
760
776
  } else if (appConfig.status && typeof appConfig.status === 'object') {
761
- status$ = rxjs.timer(0, 10e3).pipe(rx.exhaustMap(() => appConfig.status))
777
+ status$ = rxjs.timer(0, 10e3).pipe(rxjs.exhaustMap(() => appConfig.status))
762
778
  } else {
763
779
  status$ = rxjs.of({})
764
780
  }
765
781
 
766
- status$ = rxjs
767
- .combineLatest(
768
- [
769
- status$.pipe(
770
- rx.filter(Boolean),
771
- rx.map((xs) => (Array.isArray(xs) ? { messages: xs } : xs)),
772
- rx.catchError((err) => {
773
- logger.error({ err }, 'monitor.status')
774
- return rxjs.of([
775
- {
776
- id: 'app:user_monitor_status',
777
- level: 50,
778
- code: err.code,
779
- msg: err.message,
780
- },
781
- ])
782
- }),
783
- rx.startWith([]),
784
- rx.distinctUntilChanged(fp.isEqual),
785
- rx.repeatWhen((complete$) => complete$.pipe(rx.delay(10e3))),
786
- ),
787
- stats$.pipe(
788
- rx.map(({ memory, heap, utilization, undici, http }) => {
789
- const messages = []
790
-
791
- if (memory?.containerLimit) {
792
- const usagePercent = (memory.containerUsage / memory.containerLimit) * 100
793
- messages.push({
794
- id: 'app:container_memory_usage',
795
- level: usagePercent > 90 ? 50 : usagePercent > 70 ? 40 : 30,
796
- msg: `Memory Usage: ${usagePercent.toFixed(2)}%`,
797
- })
798
- }
799
-
800
- if (heap) {
801
- const usagePercent = (heap.used_heap_size / heap.heap_size_limit) * 100
802
- messages.push({
803
- id: 'app:heap_memory_usage',
804
- level: usagePercent > 90 ? 50 : usagePercent > 70 ? 40 : 30,
805
- msg: `Heap Usage: ${usagePercent.toFixed(2)}%`,
806
- })
807
- }
808
-
809
- if (utilization) {
810
- const elp = utilization.utilization * 100
811
- messages.push({
812
- id: 'app:event_loop_utilization',
813
- level: elp > 95 ? 50 : elp > 80 ? 40 : 30,
814
- msg: `Event Loop Utilization: ${elp.toFixed(2)}%`,
815
- })
816
- }
817
-
818
- if (undici) {
819
- messages.push({
820
- id: 'app:undici_upstream_sockets',
821
- level: undici.totalSockets > 8192 ? 50 : undici.totalSockets > 4096 ? 40 : 30,
822
- msg: `Undici: ${undici.totalSockets} upstream connected`,
823
- })
824
- }
825
-
826
- if (http) {
827
- messages.push({
828
- id: 'app:http_pending_requests',
829
- level: http.totalPending > 8192 ? 50 : http.totalPending > 4096 ? 40 : 30,
830
- msg: `HTTP: ${http.totalPending} pending requests`,
831
- })
832
- }
833
-
834
- return messages
835
- }),
836
- ),
837
- toobusy?.appLag$.pipe(
838
- rx.map((lag) =>
839
- lag == null
840
- ? []
841
- : [
842
- {
843
- id: 'app:toobusy_lag',
844
- level: lag > 1e3 ? 50 : lag > toobusy.maxLag ? 40 : 30,
845
- code: 'NXT_LAG',
846
- msg: `Lag: ${lag.toFixed(2)} ms`,
847
- },
848
- ],
782
+ appDestroyers.unshift(
783
+ rxjs
784
+ .combineLatest(
785
+ [
786
+ status$.pipe(
787
+ rxjs.filter(Boolean),
788
+ rxjs.map((xs) => (Array.isArray(xs) ? { messages: xs } : xs)),
789
+ rxjs.catchError((err) => {
790
+ logger.error({ err }, 'monitor.status')
791
+ return rxjs.of([
792
+ {
793
+ id: 'app:user_monitor_status',
794
+ level: 50,
795
+ code: err.code,
796
+ msg: err.message,
797
+ },
798
+ ])
799
+ }),
800
+ rxjs.startWith([]),
801
+ rxjs.distinctUntilChanged(fp.isEqual),
802
+ rxjs.repeatWhen((complete$) => complete$.pipe(rxjs.delay(10e3))),
849
803
  ),
850
- ) ?? rxjs.of([]),
851
- underPressure?.pressure$?.pipe(
852
- rx.map((pressure) =>
853
- pressure == null
854
- ? []
855
- : [
856
- {
857
- id: 'app:under_pressure',
858
- level: 40,
859
- code: 'NXT_PRESSURE',
860
- msg: `Under Pressure`,
861
- },
862
- ],
804
+ monitorProviders.stats$?.pipe(
805
+ rxjs.map(({ memory, heap, utilization, undici, http }) => {
806
+ const messages = []
807
+
808
+ if (memory?.containerLimit) {
809
+ const usagePercent = (memory.containerUsage / memory.containerLimit) * 100
810
+ messages.push({
811
+ id: 'app:container_memory_usage',
812
+ level: usagePercent > 90 ? 50 : usagePercent > 70 ? 40 : 30,
813
+ msg: `Memory Usage: ${usagePercent.toFixed(2)}%`,
814
+ })
815
+ }
816
+
817
+ if (heap) {
818
+ const usagePercent = (heap.used_heap_size / heap.heap_size_limit) * 100
819
+ messages.push({
820
+ id: 'app:heap_memory_usage',
821
+ level: usagePercent > 90 ? 50 : usagePercent > 70 ? 40 : 30,
822
+ msg: `Heap Usage: ${usagePercent.toFixed(2)}%`,
823
+ })
824
+ }
825
+
826
+ if (utilization) {
827
+ const elp = utilization.utilization * 100
828
+ messages.push({
829
+ id: 'app:event_loop_utilization',
830
+ level: elp > 95 ? 50 : elp > 80 ? 40 : 30,
831
+ msg: `Event Loop Utilization: ${elp.toFixed(2)}%`,
832
+ })
833
+ }
834
+
835
+ if (undici) {
836
+ messages.push({
837
+ id: 'app:undici_upstream_sockets',
838
+ level: undici.totalSockets > 8192 ? 50 : undici.totalSockets > 4096 ? 40 : 30,
839
+ msg: `Undici: ${undici.totalSockets} upstream connected`,
840
+ })
841
+ }
842
+
843
+ if (http) {
844
+ messages.push({
845
+ id: 'app:http_pending_requests',
846
+ level: http.totalPending > 8192 ? 50 : http.totalPending > 4096 ? 40 : 30,
847
+ msg: `HTTP: ${http.totalPending} pending requests`,
848
+ })
849
+ }
850
+
851
+ return messages
852
+ }),
863
853
  ),
864
- ) ?? rxjs.of([]),
865
- couch
866
- ? rxjs.timer(0, 10e3).pipe(
867
- rx.exhaustMap(async () => {
868
- try {
869
- await couch.up()
870
- return [
854
+ toobusy?.appLag$.pipe(
855
+ rxjs.map((lag) =>
856
+ lag == null
857
+ ? []
858
+ : [
871
859
  {
872
- id: 'app:couch',
873
- level: 30,
874
- msg: 'Couch: connected',
860
+ id: 'app:toobusy_lag',
861
+ level: lag > 1e3 ? 50 : lag > toobusy.maxLag ? 40 : 30,
862
+ code: 'NXT_LAG',
863
+ msg: `Lag: ${lag.toFixed(2)} ms`,
875
864
  },
876
- ]
877
- } catch (err) {
878
- return [
865
+ ],
866
+ ),
867
+ ) ?? rxjs.of([]),
868
+ underPressure?.pressure$?.pipe(
869
+ rxjs.map((pressure) =>
870
+ pressure == null
871
+ ? []
872
+ : [
879
873
  {
880
- id: 'app:couch',
874
+ id: 'app:under_pressure',
881
875
  level: 40,
882
- code: err.code,
883
- msg: 'Couch: ' + err.message,
876
+ code: 'NXT_PRESSURE',
877
+ msg: `Under Pressure`,
884
878
  },
885
- ]
886
- }
887
- }),
888
- rx.startWith([]),
889
- rx.distinctUntilChanged(fp.isEqual),
890
- )
891
- : rxjs.of({}),
892
- ds
893
- ? rxjs.fromEvent(ds, 'connectionStateChanged').pipe(
894
- rxjs.map((connectionState) =>
895
- connectionState === 'OPEN'
896
- ? [
879
+ ],
880
+ ),
881
+ ) ?? rxjs.of([]),
882
+ couch
883
+ ? rxjs.timer(0, 10e3).pipe(
884
+ rxjs.exhaustMap(async () => {
885
+ try {
886
+ await couch.up()
887
+ return [
897
888
  {
898
- id: 'app:ds_connection_state',
889
+ id: 'app:couch',
899
890
  level: 30,
900
- msg: 'Deepstream: connected',
901
- data: { connectionState },
891
+ msg: 'Couch: connected',
902
892
  },
903
893
  ]
904
- : [
894
+ } catch (err) {
895
+ return [
905
896
  {
906
- id: 'app:ds_connection_state',
897
+ id: 'app:couch',
907
898
  level: 40,
908
- msg: 'Deepstream: connecting',
909
- data: { connectionState },
899
+ code: err.code,
900
+ msg: 'Couch: ' + err.message,
910
901
  },
911
- ],
912
- ),
902
+ ]
903
+ }
904
+ }),
905
+ rxjs.startWith([]),
906
+ rxjs.distinctUntilChanged(fp.isEqual),
907
+ )
908
+ : rxjs.of({}),
909
+ ds
910
+ ? rxjs.fromEvent(ds, 'connectionStateChanged').pipe(
911
+ rxjs.map((connectionState) =>
912
+ connectionState === 'OPEN'
913
+ ? [
914
+ {
915
+ id: 'app:ds_connection_state',
916
+ level: 30,
917
+ msg: 'Deepstream: connected',
918
+ data: { connectionState },
919
+ },
920
+ ]
921
+ : [
922
+ {
923
+ id: 'app:ds_connection_state',
924
+ level: 40,
925
+ msg: 'Deepstream: connecting',
926
+ data: { connectionState },
927
+ },
928
+ ],
929
+ ),
930
+ )
931
+ : rxjs.of([]),
932
+ ds
933
+ ? rxjs.timer(0, 10e3).pipe(
934
+ rxjs.exhaustMap(async () => {
935
+ const messages = []
936
+
937
+ if (ds.stats.record.records > 100e3) {
938
+ messages.push({
939
+ id: 'app:ds_record_records',
940
+ level: 40,
941
+ code: 'NXT_DEEPSTREAM_RECORDS_RECORDS',
942
+ msg: 'Deepstream: ' + ds.stats.record.records + ' records',
943
+ })
944
+ }
945
+
946
+ if (ds.stats.record.pruning > 100e3) {
947
+ messages.push({
948
+ id: 'app:ds_record_pruning',
949
+ level: 40,
950
+ code: 'NXT_DEEPSTREAM_RECORDS_PRUNING',
951
+ msg: 'Deepstream: ' + ds.stats.record.pruning + ' pruning',
952
+ })
953
+ }
954
+
955
+ if (ds.stats.record.pending > 10e3) {
956
+ messages.push({
957
+ id: 'app:ds_record_pending',
958
+ level: 40,
959
+ code: 'NXT_DEEPSTREAM_RECORDS_PENDING',
960
+ msg: 'Deepstream: ' + ds.stats.record.pending + ' pending',
961
+ })
962
+ }
963
+
964
+ if (ds.stats.record.updating > 10e3) {
965
+ messages.push({
966
+ id: 'app:ds_record_updating',
967
+ level: 40,
968
+ code: 'NXT_DEEPSTREAM_RECORDS_UPDATING',
969
+ msg: 'Deepstream: ' + ds.stats.record.updating + ' updating',
970
+ })
971
+ }
972
+
973
+ if (ds.stats.record.patching > 10e3) {
974
+ messages.push({
975
+ id: 'app:ds_record_patching',
976
+ level: 40,
977
+ code: 'NXT_DEEPSTREAM_RECORDS_PATCHING',
978
+ msg: 'Deepstream: ' + ds.stats.record.patching + ' patching',
979
+ })
980
+ }
981
+
982
+ return messages
983
+ }),
984
+ )
985
+ : rxjs.of([]),
986
+ rxjs.timer(0, 10e3),
987
+ ].filter(Boolean),
988
+ )
989
+ .pipe(
990
+ rxjs.auditTime(1e3),
991
+ rxjs.map(([status, lag, couch, ds]) => {
992
+ const messages = [
993
+ lag,
994
+ couch,
995
+ ds,
996
+ [
997
+ status?.messages,
998
+ fp.map((x) => (fp.isString(x) ? { msg: x, level: 40 } : x), status?.warnings),
999
+ status,
1000
+ ].find((x) => fp.isArray(x) && !fp.isEmpty(x)) ?? [],
1001
+ ]
1002
+ .flat()
1003
+ .filter((x) => fp.isPlainObject(x) && !fp.isEmpty(x))
1004
+ .map((message) =>
1005
+ message.msg || !message.message
1006
+ ? message
1007
+ : {
1008
+ ...message,
1009
+ message: undefined,
1010
+ msg: message.message,
1011
+ },
913
1012
  )
914
- : rxjs.of([]),
915
- ds
916
- ? rxjs.timer(0, 10e3).pipe(
917
- rx.exhaustMap(async () => {
918
- const messages = []
919
-
920
- if (ds.stats.record.records > 100e3) {
921
- messages.push({
922
- id: 'app:ds_record_records',
923
- level: 40,
924
- code: 'NXT_DEEPSTREAM_RECORDS_RECORDS',
925
- msg: 'Deepstream: ' + ds.stats.record.records + ' records',
926
- })
927
- }
928
-
929
- if (ds.stats.record.pruning > 100e3) {
930
- messages.push({
931
- id: 'app:ds_record_pruning',
932
- level: 40,
933
- code: 'NXT_DEEPSTREAM_RECORDS_PRUNING',
934
- msg: 'Deepstream: ' + ds.stats.record.pruning + ' pruning',
935
- })
936
- }
937
-
938
- if (ds.stats.record.pending > 10e3) {
939
- messages.push({
940
- id: 'app:ds_record_pending',
941
- level: 40,
942
- code: 'NXT_DEEPSTREAM_RECORDS_PENDING',
943
- msg: 'Deepstream: ' + ds.stats.record.pending + ' pending',
944
- })
945
- }
946
-
947
- if (ds.stats.record.updating > 10e3) {
948
- messages.push({
949
- id: 'app:ds_record_updating',
950
- level: 40,
951
- code: 'NXT_DEEPSTREAM_RECORDS_UPDATING',
952
- msg: 'Deepstream: ' + ds.stats.record.updating + ' updating',
953
- })
954
- }
955
-
956
- if (ds.stats.record.patching > 10e3) {
957
- messages.push({
958
- id: 'app:ds_record_patching',
959
- level: 40,
960
- code: 'NXT_DEEPSTREAM_RECORDS_PATCHING',
961
- msg: 'Deepstream: ' + ds.stats.record.patching + ' patching',
962
- })
963
- }
964
-
965
- return messages
966
- }),
1013
+ .map((message) =>
1014
+ message.id
1015
+ ? message
1016
+ : {
1017
+ ...message,
1018
+ id: hashString(
1019
+ [message.msg, message].find(fp.isString) ?? JSON.stringify(message),
1020
+ ),
1021
+ },
967
1022
  )
968
- : rxjs.of([]),
969
- rxjs.timer(0, 10e3),
970
- ].filter(Boolean),
971
- )
972
- .pipe(
973
- rx.auditTime(1e3),
974
- rx.map(([status, lag, couch, ds]) => {
975
- const messages = [
976
- lag,
977
- couch,
978
- ds,
979
- [
980
- status?.messages,
981
- fp.map((x) => (fp.isString(x) ? { msg: x, level: 40 } : x), status?.warnings),
982
- status,
983
- ].find((x) => fp.isArray(x) && !fp.isEmpty(x)) ?? [],
984
- ]
985
- .flat()
986
- .filter((x) => fp.isPlainObject(x) && !fp.isEmpty(x))
987
- .map((message) =>
988
- message.msg || !message.message
989
- ? message
990
- : {
991
- ...message,
992
- message: undefined,
993
- msg: message.message,
994
- },
995
- )
996
- .map((message) =>
997
- message.id
998
- ? message
999
- : {
1000
- ...message,
1001
- id: hashString(
1002
- [message.msg, message].find(fp.isString) ?? JSON.stringify(message),
1003
- ),
1004
- },
1005
- )
1006
1023
 
1007
- return { ...status, messages, timestamp: Date.now() }
1008
- }),
1009
- rx.catchError((err) => {
1010
- logger.error({ err }, 'monitor.status')
1011
- return rxjs.of({
1012
- messages: [{ id: 'app:monitor_status', level: 50, code: err.code, msg: err.message }],
1013
- })
1014
- }),
1015
- rx.repeatWhen((complete$) => complete$.pipe(rx.delay(10e3))),
1016
- rx.startWith({}),
1017
- rx.distinctUntilChanged(fp.isEqual),
1018
- rx.publishReplay(1),
1019
- rx.refCount(),
1020
- )
1024
+ return { ...status, messages, timestamp: Date.now() }
1025
+ }),
1026
+ rxjs.catchError((err) => {
1027
+ logger.error({ err }, 'monitor.status')
1028
+ return rxjs.of({
1029
+ messages: [{ id: 'app:monitor_status', level: 50, code: err.code, msg: err.message }],
1030
+ })
1031
+ }),
1032
+ rxjs.repeatWhen((complete$) => complete$.pipe(rxjs.delay(10e3))),
1033
+ rxjs.startWith({}),
1034
+ rxjs.distinctUntilChanged(fp.isEqual),
1035
+ )
1036
+ .subscribe(monitorProviders.status$),
1037
+ )
1021
1038
 
1022
- const loggerSubscription = status$
1023
- .pipe(rx.auditTime(1e3), rx.pluck('messages'), rx.startWith([]), rx.pairwise())
1024
- .subscribe(([prev, next]) => {
1025
- for (const { level, msg: status, ...message } of fp.differenceBy('id', next, prev)) {
1026
- if (level >= 50) {
1027
- logger.error({ ...message, status }, `status added`)
1028
- } else if (level >= 40) {
1029
- logger.warn({ ...message, status }, `status added`)
1030
- } else {
1031
- logger.info({ ...message, status }, `status added`)
1039
+ appDestroyers.unshift(
1040
+ monitorProviders.status$
1041
+ .pipe(rxjs.auditTime(1e3), rxjs.pluck('messages'), rxjs.startWith([]), rxjs.pairwise())
1042
+ .subscribe(([prev, next]) => {
1043
+ for (const { level, msg: status, ...message } of fp.differenceBy('id', next, prev)) {
1044
+ if (level >= 50) {
1045
+ logger.error({ ...message, status }, `status added`)
1046
+ } else if (level >= 40) {
1047
+ logger.warn({ ...message, status }, `status added`)
1048
+ } else {
1049
+ logger.info({ ...message, status }, `status added`)
1050
+ }
1032
1051
  }
1033
- }
1034
1052
 
1035
- for (const { level, msg: status, ...message } of fp.differenceBy('id', prev, next)) {
1036
- if (level >= 40) {
1037
- logger.info({ ...message, status }, `status removed`)
1053
+ for (const { level, msg: status, ...message } of fp.differenceBy('id', prev, next)) {
1054
+ if (level >= 40) {
1055
+ logger.info({ ...message, status }, `status removed`)
1056
+ }
1038
1057
  }
1039
- }
1040
- })
1041
-
1042
- monitorProviders.status$ = status$
1043
-
1044
- appDestroyers.unshift(loggerSubscription)
1058
+ }),
1059
+ )
1045
1060
  }
1046
1061
 
1047
1062
  if (ds && Object.keys(monitorProviders).length && appConfig.monitor !== false) {
@@ -1275,13 +1290,13 @@ export function makeApp(appConfig, onTerminateOrMeta, metaOrNull) {
1275
1290
  try {
1276
1291
  if (req.method === 'GET' && req.url === '/stats') {
1277
1292
  res.setHeader('content-type', 'application/json')
1278
- res.end(JSON.stringify(stats$.value))
1293
+ res.end(JSON.stringify(monitorProviders.stats$.value))
1279
1294
  return
1280
1295
  }
1281
1296
 
1282
1297
  if (req.method === 'GET' && req.url === '/status') {
1283
1298
  res.setHeader('content-type', 'application/json')
1284
- res.end(JSON.stringify(status$.value))
1299
+ res.end(JSON.stringify(monitorProviders.status$.value))
1285
1300
  return
1286
1301
  }
1287
1302
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/lib",
3
- "version": "28.0.11",
3
+ "version": "28.0.13",
4
4
  "license": "UNLICENSED",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "type": "module",
@@ -52,7 +52,7 @@
52
52
  "@elastic/transport": "^8.9.3",
53
53
  "@nxtedition/nxt-undici": "^7.1.9",
54
54
  "@nxtedition/sched": "^1.0.2",
55
- "@nxtedition/template": "^1.0.9",
55
+ "@nxtedition/template": "^1.0.10",
56
56
  "@nxtedition/weak-cache": "^1.0.2",
57
57
  "diff": "5.2.0",
58
58
  "fast-querystring": "^1.1.2",
@@ -92,5 +92,5 @@
92
92
  "pino": ">=7.0.0",
93
93
  "rxjs": "^7.0.0"
94
94
  },
95
- "gitHead": "0337fc7ffd76296e12c4ce91be5941c839e8c90b"
95
+ "gitHead": "ab3426c105b6b59a7a092a3a5ae1e563ea1253a4"
96
96
  }