@@ -30,19 +30,19 @@ const DEFAULT_PROFILER_SECONDS: u64 = 10;
30
30
// DEFAULT_PROFILER_FREQUENCY is the default frequency to start profiling.
31
31
const DEFAULT_PROFILER_FREQUENCY : i32 = 1000 ;
32
32
33
- // PProfQueryParams is the query params to start profiling.
33
+ // PProfProfileQueryParams is the query params to start profiling.
34
34
#[ derive( Deserialize , Serialize ) ]
35
35
#[ serde( default ) ]
36
- pub struct PProfQueryParams {
36
+ pub struct PProfProfileQueryParams {
37
37
// seconds is the seconds to start profiling.
38
38
pub seconds : u64 ,
39
39
40
40
// frequency is the frequency to start profiling.
41
41
pub frequency : i32 ,
42
42
}
43
43
44
- // PProfQueryParams implements the default.
45
- impl Default for PProfQueryParams {
44
+ // PProfProfileQueryParams implements the default.
45
+ impl Default for PProfProfileQueryParams {
46
46
fn default ( ) -> Self {
47
47
Self {
48
48
seconds : DEFAULT_PROFILER_SECONDS ,
@@ -84,16 +84,24 @@ impl Stats {
84
84
// Clone the shutdown channel.
85
85
let mut shutdown = self . shutdown . clone ( ) ;
86
86
87
- // Create the stats route.
88
- let stats_route = warp:: path!( "debug" / "pprof" / "profile" )
87
+ // Create the pprof profile route.
88
+ let pprof_profile_route = warp:: path!( "debug" / "pprof" / "profile" )
89
89
. and ( warp:: get ( ) )
90
- . and ( warp:: query :: < PProfQueryParams > ( ) )
91
- . and_then ( Self :: stats_handler) ;
90
+ . and ( warp:: query :: < PProfProfileQueryParams > ( ) )
91
+ . and_then ( Self :: pprof_profile_handler) ;
92
+
93
+ // Create the pprof heap route.
94
+ let pprof_heap_route = warp:: path!( "debug" / "pprof" / "heap" )
95
+ . and ( warp:: get ( ) )
96
+ . and_then ( Self :: pprof_heap_handler) ;
97
+
98
+ // Create the pprof routes.
99
+ let pprof_routes = pprof_profile_route. or ( pprof_heap_route) ;
92
100
93
101
// Start the stats server and wait for it to finish.
94
102
info ! ( "stats server listening on {}" , self . addr) ;
95
103
tokio:: select! {
96
- _ = warp:: serve( stats_route ) . run( self . addr) => {
104
+ _ = warp:: serve( pprof_routes ) . run( self . addr) => {
97
105
// Stats server ended.
98
106
info!( "stats server ended" ) ;
99
107
}
@@ -105,35 +113,29 @@ impl Stats {
105
113
}
106
114
107
115
// stats_handler handles the stats request.
108
- async fn stats_handler ( query_params : PProfQueryParams ) -> Result < impl Reply , Rejection > {
116
+ async fn pprof_profile_handler (
117
+ query_params : PProfProfileQueryParams ,
118
+ ) -> Result < impl Reply , Rejection > {
109
119
info ! (
110
120
"start profiling for {} seconds with {} frequency" ,
111
121
query_params. seconds, query_params. frequency
112
122
) ;
113
- let guard = match ProfilerGuard :: new ( query_params. frequency ) {
114
- Ok ( guard) => guard,
115
- Err ( err) => {
116
- error ! ( "failed to create profiler guard: {}" , err) ;
117
- return Err ( warp:: reject:: reject ( ) ) ;
118
- }
119
- } ;
123
+
124
+ let guard = ProfilerGuard :: new ( query_params. frequency ) . map_err ( |err| {
125
+ error ! ( "failed to create profiler guard: {}" , err) ;
126
+ warp:: reject:: reject ( )
127
+ } ) ?;
120
128
121
129
tokio:: time:: sleep ( Duration :: from_secs ( query_params. seconds ) ) . await ;
122
- let report = match guard. report ( ) . build ( ) {
123
- Ok ( report) => report,
124
- Err ( err) => {
125
- error ! ( "failed to build profiler report: {}" , err) ;
126
- return Err ( warp:: reject:: reject ( ) ) ;
127
- }
128
- } ;
130
+ let report = guard. report ( ) . build ( ) . map_err ( |err| {
131
+ error ! ( "failed to build profiler report: {}" , err) ;
132
+ warp:: reject:: reject ( )
133
+ } ) ?;
129
134
130
- let profile = match report. pprof ( ) {
131
- Ok ( profile) => profile,
132
- Err ( err) => {
133
- error ! ( "failed to get pprof profile: {}" , err) ;
134
- return Err ( warp:: reject:: reject ( ) ) ;
135
- }
136
- } ;
135
+ let profile = report. pprof ( ) . map_err ( |err| {
136
+ error ! ( "failed to get pprof profile: {}" , err) ;
137
+ warp:: reject:: reject ( )
138
+ } ) ?;
137
139
138
140
let mut body: Vec < u8 > = Vec :: new ( ) ;
139
141
profile. write_to_vec ( & mut body) . map_err ( |err| {
@@ -143,4 +145,26 @@ impl Stats {
143
145
144
146
Ok ( body)
145
147
}
148
+
149
+ // pprof_heap_handler handles the pprof heap request.
150
+ async fn pprof_heap_handler ( ) -> Result < impl Reply , Rejection > {
151
+ info ! ( "start heap profiling" ) ;
152
+ #[ cfg( target_os = "linux" ) ]
153
+ {
154
+ let mut prof_ctl = jemalloc_pprof:: PROF_CTL . as_ref ( ) . unwrap ( ) . lock ( ) . await ;
155
+ if !prof_ctl. activated ( ) {
156
+ return Err ( warp:: reject:: reject ( ) ) ;
157
+ }
158
+
159
+ let pprof = prof_ctl. dump_pprof ( ) . map_err ( |err| {
160
+ error ! ( "failed to dump pprof: {}" , err) ;
161
+ warp:: reject:: reject ( )
162
+ } ) ?;
163
+
164
+ Ok ( pprof)
165
+ }
166
+
167
+ #[ cfg( not( target_os = "linux" ) ) ]
168
+ Err :: < warp:: http:: Error , Rejection > ( warp:: reject:: reject ( ) )
169
+ }
146
170
}
0 commit comments