@@ -3,16 +3,15 @@ use std::io::Write as _;
3
3
use std:: str:: FromStr ;
4
4
use std:: time:: Duration ;
5
5
6
- use :: pprof:: ProfilerGuardBuilder ;
7
- use :: pprof:: protos:: Message as _;
8
6
use anyhow:: { Context , anyhow} ;
9
7
use bytes:: { Bytes , BytesMut } ;
10
8
use hyper:: header:: { AUTHORIZATION , CONTENT_DISPOSITION , CONTENT_TYPE , HeaderName } ;
11
9
use hyper:: http:: HeaderValue ;
12
10
use hyper:: { Body , Method , Request , Response } ;
13
11
use metrics:: { Encoder , IntCounter , TextEncoder , register_int_counter} ;
14
12
use once_cell:: sync:: Lazy ;
15
- use regex:: Regex ;
13
+ use pprof:: ProfilerGuardBuilder ;
14
+ use pprof:: protos:: Message as _;
16
15
use routerify:: ext:: RequestExt ;
17
16
use routerify:: { Middleware , RequestInfo , Router , RouterBuilder } ;
18
17
use tokio:: sync:: { Mutex , Notify , mpsc} ;
@@ -22,7 +21,6 @@ use tracing::{Instrument, debug, info, info_span, warn};
22
21
use utils:: auth:: { AuthError , Claims , SwappableJwtAuth } ;
23
22
24
23
use crate :: error:: { ApiError , api_error_handler, route_error_handler} ;
25
- use crate :: pprof;
26
24
use crate :: request:: { get_query_param, parse_query_param} ;
27
25
28
26
static SERVE_METRICS_COUNT : Lazy < IntCounter > = Lazy :: new ( || {
@@ -449,20 +447,6 @@ pub async fn profile_heap_handler(req: Request<Body>) -> Result<Response<Body>,
449
447
Some ( format) => return Err ( ApiError :: BadRequest ( anyhow ! ( "invalid format {format}" ) ) ) ,
450
448
} ;
451
449
452
- // Functions and mappings to strip when symbolizing pprof profiles. If true,
453
- // also remove child frames.
454
- static STRIP_FUNCTIONS : Lazy < Vec < ( Regex , bool ) > > = Lazy :: new ( || {
455
- vec ! [
456
- ( Regex :: new( "^__rust" ) . unwrap( ) , false ) ,
457
- ( Regex :: new( "^_start$" ) . unwrap( ) , false ) ,
458
- ( Regex :: new( "^irallocx_prof" ) . unwrap( ) , true ) ,
459
- ( Regex :: new( "^prof_alloc_prep" ) . unwrap( ) , true ) ,
460
- ( Regex :: new( "^std::rt::lang_start" ) . unwrap( ) , false ) ,
461
- ( Regex :: new( "^std::sys::backtrace::__rust" ) . unwrap( ) , false ) ,
462
- ]
463
- } ) ;
464
- const STRIP_MAPPINGS : & [ & str ] = & [ "libc" , "libgcc" , "pthread" , "vdso" ] ;
465
-
466
450
// Obtain profiler handle.
467
451
let mut prof_ctl = jemalloc_pprof:: PROF_CTL
468
452
. as_ref ( )
@@ -495,45 +479,27 @@ pub async fn profile_heap_handler(req: Request<Body>) -> Result<Response<Body>,
495
479
}
496
480
497
481
Format :: Pprof => {
498
- let data = tokio:: task:: spawn_blocking ( move || {
499
- let bytes = prof_ctl. dump_pprof ( ) ?;
500
- // Symbolize the profile.
501
- // TODO: consider moving this upstream to jemalloc_pprof and avoiding the
502
- // serialization roundtrip.
503
- let profile = pprof:: decode ( & bytes) ?;
504
- let profile = pprof:: symbolize ( profile) ?;
505
- let profile = pprof:: strip_locations ( profile, STRIP_MAPPINGS , & STRIP_FUNCTIONS ) ;
506
- pprof:: encode ( & profile)
507
- } )
508
- . await
509
- . map_err ( |join_err| ApiError :: InternalServerError ( join_err. into ( ) ) ) ?
510
- . map_err ( ApiError :: InternalServerError ) ?;
482
+ let data = tokio:: task:: spawn_blocking ( move || prof_ctl. dump_pprof ( ) )
483
+ . await
484
+ . map_err ( |join_err| ApiError :: InternalServerError ( join_err. into ( ) ) ) ?
485
+ . map_err ( ApiError :: InternalServerError ) ?;
511
486
Response :: builder ( )
512
487
. status ( 200 )
513
488
. header ( CONTENT_TYPE , "application/octet-stream" )
514
- . header ( CONTENT_DISPOSITION , "attachment; filename=\" heap.pb\" " )
489
+ . header ( CONTENT_DISPOSITION , "attachment; filename=\" heap.pb.gz \" " )
515
490
. body ( Body :: from ( data) )
516
491
. map_err ( |err| ApiError :: InternalServerError ( err. into ( ) ) )
517
492
}
518
493
519
494
Format :: Svg => {
520
- let body = tokio:: task:: spawn_blocking ( move || {
521
- let bytes = prof_ctl. dump_pprof ( ) ?;
522
- let profile = pprof:: decode ( & bytes) ?;
523
- let profile = pprof:: symbolize ( profile) ?;
524
- let profile = pprof:: strip_locations ( profile, STRIP_MAPPINGS , & STRIP_FUNCTIONS ) ;
525
- let mut opts = inferno:: flamegraph:: Options :: default ( ) ;
526
- opts. title = "Heap inuse" . to_string ( ) ;
527
- opts. count_name = "bytes" . to_string ( ) ;
528
- pprof:: flamegraph ( profile, & mut opts)
529
- } )
530
- . await
531
- . map_err ( |join_err| ApiError :: InternalServerError ( join_err. into ( ) ) ) ?
532
- . map_err ( ApiError :: InternalServerError ) ?;
495
+ let svg = tokio:: task:: spawn_blocking ( move || prof_ctl. dump_flamegraph ( ) )
496
+ . await
497
+ . map_err ( |join_err| ApiError :: InternalServerError ( join_err. into ( ) ) ) ?
498
+ . map_err ( ApiError :: InternalServerError ) ?;
533
499
Response :: builder ( )
534
500
. status ( 200 )
535
501
. header ( CONTENT_TYPE , "image/svg+xml" )
536
- . body ( Body :: from ( body ) )
502
+ . body ( Body :: from ( svg ) )
537
503
. map_err ( |err| ApiError :: InternalServerError ( err. into ( ) ) )
538
504
}
539
505
}
0 commit comments