@nxtedition/lib 13.0.8 → 13.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.
- package/app.js +203 -153
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -331,6 +331,74 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
331
331
|
|
|
332
332
|
const monitorProviders = {}
|
|
333
333
|
|
|
334
|
+
let stats$
|
|
335
|
+
if (appConfig.stats) {
|
|
336
|
+
const v8 = require('v8')
|
|
337
|
+
const rxjs = require('rxjs')
|
|
338
|
+
const rx = require('rxjs/operators')
|
|
339
|
+
const { eventLoopUtilization } = require('perf_hooks').performance
|
|
340
|
+
|
|
341
|
+
if (typeof appConfig.stats.subscribe === 'function') {
|
|
342
|
+
stats$ = appConfig.stats
|
|
343
|
+
} else if (typeof appConfig.stats === 'function') {
|
|
344
|
+
stats$ = rxjs.timer(0, 10e3).pipe(
|
|
345
|
+
rx.exhaustMap(() => {
|
|
346
|
+
const ret = appConfig.stats({ ds, couch, logger })
|
|
347
|
+
return ret?.then || ret?.subscribe ? ret : rxjs.of(ret)
|
|
348
|
+
})
|
|
349
|
+
)
|
|
350
|
+
} else if (typeof appConfig.stats === 'object') {
|
|
351
|
+
stats$ = rxjs.timer(0, 10e3).pipe(rx.map(() => appConfig.stats))
|
|
352
|
+
} else {
|
|
353
|
+
stats$ = rxjs.timer(0, 10e3).pipe(rx.map(() => ({})))
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
stats$ = stats$.pipe(
|
|
357
|
+
rx.map((x) => ({
|
|
358
|
+
...x,
|
|
359
|
+
timestamp: Date.now(),
|
|
360
|
+
})),
|
|
361
|
+
rx.auditTime(1e3),
|
|
362
|
+
rx.filter(Boolean),
|
|
363
|
+
rx.retryWhen((err$) =>
|
|
364
|
+
err$.pipe(
|
|
365
|
+
rx.tap((err) => logger.error({ err }, 'monitor.stats')),
|
|
366
|
+
rx.delay(10e3)
|
|
367
|
+
)
|
|
368
|
+
),
|
|
369
|
+
rx.startWith({}),
|
|
370
|
+
rx.publishReplay(1),
|
|
371
|
+
rx.refCount()
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
monitorProviders.stats$ = stats$
|
|
375
|
+
|
|
376
|
+
let elu1 = eventLoopUtilization?.()
|
|
377
|
+
const subscription = stats$.pipe(rx.auditTime(10e3)).subscribe((stats) => {
|
|
378
|
+
if (process.env.NODE_ENV === 'production') {
|
|
379
|
+
const elu2 = eventLoopUtilization?.()
|
|
380
|
+
logger.debug(
|
|
381
|
+
{
|
|
382
|
+
ds: ds?.stats,
|
|
383
|
+
couch: couch?.stats,
|
|
384
|
+
lag: toobusy?.lag(),
|
|
385
|
+
memory: process.memoryUsage(),
|
|
386
|
+
utilization: eventLoopUtilization?.(elu2, elu1),
|
|
387
|
+
heap: v8.getHeapStatistics(),
|
|
388
|
+
...stats,
|
|
389
|
+
},
|
|
390
|
+
'STATS'
|
|
391
|
+
)
|
|
392
|
+
elu1 = elu2
|
|
393
|
+
}
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
destroyers.push(() => {
|
|
397
|
+
subscription.unsubscribe()
|
|
398
|
+
})
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
let status$
|
|
334
402
|
if (appConfig.status) {
|
|
335
403
|
const rxjs = require('rxjs')
|
|
336
404
|
const rx = require('rxjs/operators')
|
|
@@ -338,7 +406,6 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
338
406
|
const fp = require('lodash/fp')
|
|
339
407
|
const hashString = require('./hash')
|
|
340
408
|
|
|
341
|
-
let status$
|
|
342
409
|
if (appConfig.status.subscribe) {
|
|
343
410
|
status$ = appConfig.status
|
|
344
411
|
} else if (typeof appConfig.status === 'function') {
|
|
@@ -358,103 +425,108 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
358
425
|
}
|
|
359
426
|
|
|
360
427
|
status$ = rxjs
|
|
361
|
-
.combineLatest(
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
428
|
+
.combineLatest(
|
|
429
|
+
[
|
|
430
|
+
status$.pipe(
|
|
431
|
+
rx.filter(Boolean),
|
|
432
|
+
rx.catchError((err) => {
|
|
433
|
+
logger.error({ err }, 'monitor.status')
|
|
434
|
+
return rxjs.of([
|
|
435
|
+
{
|
|
436
|
+
id: 'app:user_monitor_status',
|
|
437
|
+
level: 50,
|
|
438
|
+
code: err.code,
|
|
439
|
+
msg: err.message,
|
|
440
|
+
},
|
|
441
|
+
])
|
|
442
|
+
}),
|
|
443
|
+
rx.startWith([]),
|
|
444
|
+
rx.distinctUntilChanged(fp.isEqual),
|
|
445
|
+
rx.repeatWhen((complete$) => complete$.pipe(rx.delay(10e3)))
|
|
446
|
+
),
|
|
447
|
+
toobusy
|
|
448
|
+
? rxjs.timer(0, 1e3).pipe(
|
|
449
|
+
rx.map(() =>
|
|
450
|
+
toobusy.lag() > 1e3
|
|
451
|
+
? [
|
|
452
|
+
{
|
|
453
|
+
id: 'app:toobusy_lag',
|
|
454
|
+
level: 40,
|
|
455
|
+
code: 'NXT_LAG',
|
|
456
|
+
msg: `lag: ${toobusy.lag()}`,
|
|
457
|
+
},
|
|
458
|
+
]
|
|
459
|
+
: []
|
|
460
|
+
),
|
|
461
|
+
rx.startWith([]),
|
|
462
|
+
rx.distinctUntilChanged(fp.isEqual)
|
|
463
|
+
)
|
|
464
|
+
: rxjs.of({}),
|
|
465
|
+
couch
|
|
466
|
+
? rxjs.timer(0, 10e3).pipe(
|
|
467
|
+
rx.exhaustMap(async () => {
|
|
468
|
+
try {
|
|
469
|
+
await couch.info()
|
|
470
|
+
} catch (err) {
|
|
471
|
+
return [
|
|
384
472
|
{
|
|
385
|
-
id: 'app:
|
|
473
|
+
id: 'app:couch',
|
|
386
474
|
level: 40,
|
|
387
|
-
code:
|
|
388
|
-
msg:
|
|
475
|
+
code: err.code,
|
|
476
|
+
msg: 'couch: ' + err.message,
|
|
389
477
|
},
|
|
390
478
|
]
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
code: err.code,
|
|
408
|
-
msg: 'couch: ' + err.message,
|
|
409
|
-
},
|
|
410
|
-
]
|
|
411
|
-
}
|
|
412
|
-
}),
|
|
413
|
-
rx.startWith([]),
|
|
414
|
-
rx.distinctUntilChanged(fp.isEqual)
|
|
415
|
-
)
|
|
416
|
-
: rxjs.of({}),
|
|
417
|
-
ds
|
|
418
|
-
? new rxjs.Observable((o) => {
|
|
419
|
-
const client = new undici.Client(`http://${new URL(ds._url || ds.url).host}`, {
|
|
420
|
-
keepAliveTimeout: 30e3,
|
|
421
|
-
})
|
|
422
|
-
|
|
423
|
-
const subscription = rxjs
|
|
424
|
-
.timer(0, 10e3)
|
|
425
|
-
.pipe(
|
|
426
|
-
rx.exhaustMap(async () => {
|
|
427
|
-
try {
|
|
428
|
-
const { body } = await client.request({ method: 'GET', path: '/healthcheck' })
|
|
429
|
-
await body.dump()
|
|
430
|
-
} catch {
|
|
479
|
+
}
|
|
480
|
+
}),
|
|
481
|
+
rx.startWith([]),
|
|
482
|
+
rx.distinctUntilChanged(fp.isEqual)
|
|
483
|
+
)
|
|
484
|
+
: rxjs.of({}),
|
|
485
|
+
ds
|
|
486
|
+
? new rxjs.Observable((o) => {
|
|
487
|
+
const client = new undici.Client(`http://${new URL(ds._url || ds.url).host}`, {
|
|
488
|
+
keepAliveTimeout: 30e3,
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
const subscription = rxjs
|
|
492
|
+
.timer(0, 10e3)
|
|
493
|
+
.pipe(
|
|
494
|
+
rx.exhaustMap(async () => {
|
|
431
495
|
try {
|
|
432
496
|
const { body } = await client.request({
|
|
433
497
|
method: 'GET',
|
|
434
498
|
path: '/healthcheck',
|
|
435
499
|
})
|
|
436
500
|
await body.dump()
|
|
437
|
-
} catch
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
501
|
+
} catch {
|
|
502
|
+
try {
|
|
503
|
+
const { body } = await client.request({
|
|
504
|
+
method: 'GET',
|
|
505
|
+
path: '/healthcheck',
|
|
506
|
+
})
|
|
507
|
+
await body.dump()
|
|
508
|
+
} catch (err) {
|
|
509
|
+
return {
|
|
510
|
+
id: 'app:ds_http_connection',
|
|
511
|
+
level: 40,
|
|
512
|
+
code: err.code,
|
|
513
|
+
msg: 'ds: ' + err.message,
|
|
514
|
+
}
|
|
443
515
|
}
|
|
444
516
|
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
517
|
+
})
|
|
518
|
+
)
|
|
519
|
+
.subscribe(o)
|
|
520
|
+
|
|
521
|
+
return () => {
|
|
522
|
+
client.destroy()
|
|
523
|
+
subscription.unsubscribe()
|
|
524
|
+
}
|
|
525
|
+
}).pipe(rx.startWith([]), rx.distinctUntilChanged(fp.isEqual))
|
|
526
|
+
: rxjs.of({}),
|
|
527
|
+
rxjs.timer(0, 10e3),
|
|
528
|
+
].filter(Boolean)
|
|
529
|
+
)
|
|
458
530
|
.pipe(
|
|
459
531
|
rx.auditTime(1e3),
|
|
460
532
|
rx.map(([status, lag, couch, ds]) => {
|
|
@@ -490,6 +562,51 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
490
562
|
}
|
|
491
563
|
)
|
|
492
564
|
|
|
565
|
+
if (ds && ds.stats.record.records > 100e3) {
|
|
566
|
+
messages.push({
|
|
567
|
+
id: 'app:ds',
|
|
568
|
+
level: 40,
|
|
569
|
+
code: 'NXT_DS_RECORDS',
|
|
570
|
+
msg: 'ds: ' + ds.stats.record.records + ' records',
|
|
571
|
+
})
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (ds && ds.stats.record.pruning > 100e3) {
|
|
575
|
+
messages.push({
|
|
576
|
+
id: 'app:ds',
|
|
577
|
+
level: 40,
|
|
578
|
+
code: 'NXT_DS_PRUNING',
|
|
579
|
+
msg: 'ds: ' + ds.stats.record.pruning + ' pruning',
|
|
580
|
+
})
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (ds && ds.stats.record.pending > 10e3) {
|
|
584
|
+
messages.push({
|
|
585
|
+
id: 'app:ds',
|
|
586
|
+
level: 40,
|
|
587
|
+
code: 'NXT_DS_PENDING',
|
|
588
|
+
msg: 'ds: ' + ds.stats.record.pending + ' pending',
|
|
589
|
+
})
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (ds && ds.stats.record.updating > 10e3) {
|
|
593
|
+
messages.push({
|
|
594
|
+
id: 'app:ds',
|
|
595
|
+
level: 40,
|
|
596
|
+
code: 'NXT_DS_UPDATING',
|
|
597
|
+
msg: 'ds: ' + ds.stats.record.updating + ' updating',
|
|
598
|
+
})
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (ds && ds.stats.record.patching > 10e3) {
|
|
602
|
+
messages.push({
|
|
603
|
+
id: 'app:ds',
|
|
604
|
+
level: 40,
|
|
605
|
+
code: 'NXT_DS_PATCHING',
|
|
606
|
+
msg: 'ds: ' + ds.stats.record.patching + ' patching',
|
|
607
|
+
})
|
|
608
|
+
}
|
|
609
|
+
|
|
493
610
|
return { ...status, messages, timestamp: Date.now() }
|
|
494
611
|
}),
|
|
495
612
|
rx.catchError((err) => {
|
|
@@ -527,73 +644,6 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
527
644
|
})
|
|
528
645
|
}
|
|
529
646
|
|
|
530
|
-
if (appConfig.stats) {
|
|
531
|
-
const v8 = require('v8')
|
|
532
|
-
const rxjs = require('rxjs')
|
|
533
|
-
const rx = require('rxjs/operators')
|
|
534
|
-
const { eventLoopUtilization } = require('perf_hooks').performance
|
|
535
|
-
|
|
536
|
-
let stats$
|
|
537
|
-
if (typeof appConfig.stats.subscribe === 'function') {
|
|
538
|
-
stats$ = appConfig.stats
|
|
539
|
-
} else if (typeof appConfig.stats === 'function') {
|
|
540
|
-
stats$ = rxjs.timer(0, 10e3).pipe(
|
|
541
|
-
rx.exhaustMap(() => {
|
|
542
|
-
const ret = appConfig.stats({ ds, couch, logger })
|
|
543
|
-
return ret?.then || ret?.subscribe ? ret : rxjs.of(ret)
|
|
544
|
-
})
|
|
545
|
-
)
|
|
546
|
-
} else if (typeof appConfig.stats === 'object') {
|
|
547
|
-
stats$ = rxjs.timer(0, 10e3).pipe(rx.map(() => appConfig.stats))
|
|
548
|
-
} else {
|
|
549
|
-
stats$ = rxjs.timer(0, 10e3).pipe(rx.map(() => ({})))
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
stats$ = stats$.pipe(
|
|
553
|
-
rx.auditTime(1e3),
|
|
554
|
-
rx.filter(Boolean),
|
|
555
|
-
rx.map((x) => ({
|
|
556
|
-
...x,
|
|
557
|
-
ds: ds?.stats,
|
|
558
|
-
couch: couch?.stats,
|
|
559
|
-
lag: toobusy?.lag(),
|
|
560
|
-
timestamp: Date.now(),
|
|
561
|
-
})),
|
|
562
|
-
rx.retryWhen((err$) =>
|
|
563
|
-
err$.pipe(
|
|
564
|
-
rx.tap((err) => logger.error({ err }, 'monitor.stats')),
|
|
565
|
-
rx.delay(10e3)
|
|
566
|
-
)
|
|
567
|
-
),
|
|
568
|
-
rx.startWith({}),
|
|
569
|
-
rx.publishReplay(1),
|
|
570
|
-
rx.refCount()
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
monitorProviders.stats$ = stats$
|
|
574
|
-
|
|
575
|
-
let elu1 = eventLoopUtilization?.()
|
|
576
|
-
const subscription = stats$.pipe(rx.auditTime(10e3)).subscribe((stats) => {
|
|
577
|
-
if (process.env.NODE_ENV === 'production') {
|
|
578
|
-
const elu2 = eventLoopUtilization?.()
|
|
579
|
-
logger.debug(
|
|
580
|
-
{
|
|
581
|
-
memory: process.memoryUsage(),
|
|
582
|
-
utilization: eventLoopUtilization?.(elu2, elu1),
|
|
583
|
-
heap: v8.getHeapStatistics(),
|
|
584
|
-
...stats,
|
|
585
|
-
},
|
|
586
|
-
'STATS'
|
|
587
|
-
)
|
|
588
|
-
elu1 = elu2
|
|
589
|
-
}
|
|
590
|
-
})
|
|
591
|
-
|
|
592
|
-
destroyers.push(() => {
|
|
593
|
-
subscription.unsubscribe()
|
|
594
|
-
})
|
|
595
|
-
}
|
|
596
|
-
|
|
597
647
|
if (ds && Object.keys(monitorProviders).length && appConfig.monitor !== false) {
|
|
598
648
|
const { isMainThread } = require('node:worker_threads')
|
|
599
649
|
|