1
+ /**
2
+ * @typedef {import('stream').Writable } Writable
3
+ */
1
4
var common = require ( '../../../api/utils/common.js' ) ;
2
5
const inspector = require ( 'inspector' ) ;
3
- const countlyFs = require ( '../../../api/utils/countlyFs.js' ) ;
4
6
var exec = require ( 'child_process' ) . exec ;
5
7
const tar = require ( "tar-stream" ) ;
6
8
const session = new inspector . Session ( ) ;
9
+ const path = require ( "path" ) ;
10
+ const fs = require ( "fs/promises" ) ;
7
11
8
- const PROFILER_DIR = " nodeprofile";
12
+ const PROFILER_DIR = path . join ( __dirname , "../../../log/ nodeprofile") ;
9
13
10
14
var _id = null ;
11
15
@@ -424,23 +428,19 @@ function sessionPost(cmd) {
424
428
}
425
429
426
430
/**
427
- * Saves the result to gridfs
428
- * @param {string } filename file name with extension
429
- * @param {object } result result object returned by the profiler
430
- * @returns {Promise<string> } filename
431
+ * Takes a snapshot and writes its content to the passed stream.
432
+ * IMPORTANT: it will call the "end" for the passed stream object when it's done
433
+ * @param {Writable } stream Writable stream to write snapshot content to
431
434
*/
432
- function saveProfilerResult ( filename , result ) {
433
- return new Promise ( ( res , rej ) => {
434
- countlyFs . gridfs . saveData (
435
- PROFILER_DIR , filename , JSON . stringify ( result ) ,
436
- { writeMode : "overwrite" } ,
437
- function ( err ) {
438
- if ( err ) {
439
- return rej ( err ) ;
440
- }
441
- res ( filename ) ;
442
- }
443
- ) ;
435
+ function takeHeapSnapshot ( stream ) {
436
+ session . connect ( ) ;
437
+ session . on ( "HeapProfiler.addHeapSnapshotChunk" , m => stream . write ( m . params . chunk ) ) ;
438
+ session . post ( "HeapProfiler.takeHeapSnapshot" , null , ( err ) => {
439
+ session . disconnect ( ) ;
440
+ stream . end ( ) ;
441
+ if ( err ) {
442
+ console . error ( err ) ;
443
+ }
444
444
} ) ;
445
445
}
446
446
@@ -470,30 +470,22 @@ async function startProfiler() {
470
470
async function stopProfiler ( processName ) {
471
471
const errors = [ ] ;
472
472
473
- // clear old files
474
473
try {
475
- await new Promise (
476
- ( res , rej ) => countlyFs . gridfs . deleteAll (
477
- PROFILER_DIR ,
478
- null ,
479
- err => err ? rej ( err ) : res ( )
480
- )
481
- ) ;
474
+ await fs . rm ( PROFILER_DIR , { force : true , recursive : true } ) ; // clear old files
475
+ await fs . mkdir ( PROFILER_DIR , { recursive : true } ) ;
482
476
}
483
477
catch ( err ) {
484
- if ( err . code === 26 ) { // NamespaceNotFound: thrown when there's no collection initially
485
- // do nothing...
486
- }
487
- else {
488
- throw err ;
489
- }
478
+ errors . push ( err ) ;
490
479
}
491
480
492
481
// coverage
493
482
try {
494
483
const coverage = await sessionPost ( "Profiler.takePreciseCoverage" ) ;
495
- await saveProfilerResult ( processName + ".coverage" , coverage ?. result ) ;
496
484
await sessionPost ( "Profiler.stopPreciseCoverage" ) ;
485
+ await fs . writeFile (
486
+ path . join ( PROFILER_DIR , processName + ".coverage" ) ,
487
+ JSON . stringify ( coverage ?. result )
488
+ ) ;
497
489
}
498
490
catch ( err ) {
499
491
errors . push ( err ) ;
@@ -502,8 +494,11 @@ async function stopProfiler(processName) {
502
494
// cpu profiler
503
495
try {
504
496
const cpuProfile = await sessionPost ( "Profiler.stop" ) ;
505
- await saveProfilerResult ( processName + ".cpuprofile" , cpuProfile ?. profile ) ;
506
497
await sessionPost ( "Profiler.disable" ) ;
498
+ await fs . writeFile (
499
+ path . join ( PROFILER_DIR , processName + ".cpuprofile" ) ,
500
+ JSON . stringify ( cpuProfile ?. profile )
501
+ ) ;
507
502
}
508
503
catch ( err ) {
509
504
errors . push ( err ) ;
@@ -512,8 +507,11 @@ async function stopProfiler(processName) {
512
507
// heap profiler
513
508
try {
514
509
const heapProfile = await sessionPost ( "HeapProfiler.stopSampling" ) ;
515
- await saveProfilerResult ( processName + ".heapprofile" , heapProfile ?. profile ) ;
516
510
await sessionPost ( "HeapProfiler.disable" ) ;
511
+ await fs . writeFile (
512
+ path . join ( PROFILER_DIR , processName + ".heapprofile" ) ,
513
+ JSON . stringify ( heapProfile ?. profile )
514
+ ) ;
517
515
}
518
516
catch ( err ) {
519
517
errors . push ( err ) ;
@@ -526,39 +524,24 @@ async function stopProfiler(processName) {
526
524
}
527
525
}
528
526
529
- /**
530
- * Returns the data of a file in PROFILER_DIR collection
531
- * @param {string } filename file name with extension
532
- * @returns {Promise<{data:string, filename:string}> } file object with name and content
533
- */
534
- function downloadProfilerFile ( filename ) {
535
- return new Promise ( ( resolve , reject ) => {
536
- countlyFs . gridfs . getData ( PROFILER_DIR , filename , { } , ( err , data ) => {
537
- if ( err ) {
538
- return reject ( "File not found" ) ;
539
- }
540
- resolve ( { data, filename } ) ;
541
- } ) ;
542
- } ) ;
543
- }
544
527
/**
545
528
* Returns the names, creation dates and size of all files in the PROFILER_DIR collection
546
- * @returns {Promise<Array<{createdOn: Date, filename: string, size: number }>> } file info
529
+ * @returns {Promise<Array<{createdOn: Date, filename: string, size: number, path: string }>> } file info
547
530
*/
548
- function listProfilerFiles ( ) {
549
- return new Promise ( ( resolve , reject ) => {
550
- countlyFs . gridfs . listFiles ( PROFILER_DIR , ( err , files ) => {
551
- if ( err ) {
552
- return reject ( err ) ;
553
- }
554
- resolve ( files ) ;
555
- } ) ;
556
- } ) ;
531
+ async function listProfilerFiles ( ) {
532
+ const files = await fs . readdir ( PROFILER_DIR ) ;
533
+ return Promise . all (
534
+ files . map ( async ( filename ) => {
535
+ const fullPath = path . join ( PROFILER_DIR , filename ) ;
536
+ const { birthtime , size } = await fs . stat ( fullPath ) ;
537
+ return { createdOn : birthtime , size , filename , path : fullPath } ;
538
+ } )
539
+ ) ;
557
540
}
558
541
559
542
/**
560
543
* Returns the tarball read stream for all profiler files
561
- * @returns {tar.Pack } tar stream
544
+ * @returns {Promise< tar.Pack> } tar stream
562
545
*/
563
546
async function profilerFilesTarStream ( ) {
564
547
const files = await listProfilerFiles ( ) ;
@@ -569,14 +552,8 @@ async function profilerFilesTarStream() {
569
552
const pack = tar . pack ( ) ;
570
553
for ( let i = 0 ; i < files . length ; i ++ ) {
571
554
const entry = pack . entry ( { name : files [ i ] . filename , size : files [ i ] . size } ) ;
572
- const stream = await new Promise ( ( res , rej ) => {
573
- countlyFs . gridfs . getStream (
574
- PROFILER_DIR ,
575
- files [ i ] . filename ,
576
- { } ,
577
- ( err , fileStream ) => err ? rej ( err ) : res ( fileStream )
578
- ) ;
579
- } ) ;
555
+ const handle = await fs . open ( files [ i ] . path ) ;
556
+ const stream = handle . createReadStream ( ) ;
580
557
stream . pipe ( entry ) ;
581
558
stream . on ( "end" , ( ) => {
582
559
entry . end ( ) ;
@@ -622,9 +599,9 @@ function stopInspector() {
622
599
} ) ;
623
600
}
624
601
602
+ exports . takeHeapSnapshot = takeHeapSnapshot ;
625
603
exports . startProfiler = startProfiler ;
626
604
exports . stopProfiler = stopProfiler ;
627
- exports . downloadProfilerFile = downloadProfilerFile ;
628
605
exports . listProfilerFiles = listProfilerFiles ;
629
606
exports . startInspector = startInspector ;
630
607
exports . stopInspector = stopInspector ;
0 commit comments