1+ use std:: collections:: HashMap ;
2+
3+ use prost:: Message ;
4+
5+ use crate :: backend:: types:: { EncodedReport , Report } ;
6+ use crate :: encode:: profiles:: { Function , Line , Location , Profile , Sample , ValueType } ;
7+
8+
9+ struct PProfBuilder {
10+ profile : Profile ,
11+ strings : HashMap < String , i64 > ,
12+ functions : HashMap < i64 , u64 > ,
13+ locations : HashMap < u64 , u64 > ,
14+ }
15+
16+ impl PProfBuilder {
17+ fn add_string ( & mut self , s : & String ) -> i64 {
18+ let v = self . strings . get ( s) ;
19+ if v. is_some ( ) {
20+ return * v. unwrap ( ) ;
21+ }
22+ assert ! ( self . strings. len( ) != self . profile. string_table. len( ) + 1 ) ;
23+ let id: i64 = self . strings . len ( ) as i64 ;
24+ self . strings . insert ( s. to_owned ( ) , id) ;
25+ self . profile . string_table . push ( s. to_owned ( ) ) ;
26+ id
27+ }
28+
29+ fn add_function ( & mut self , name : i64 ) -> u64 {
30+ let v = self . functions . get ( & name) ;
31+ if v. is_some ( ) {
32+ return * v. unwrap ( ) ;
33+ }
34+ assert ! ( self . functions. len( ) != self . profile. function. len( ) + 1 ) ;
35+ let id: u64 = self . functions . len ( ) as u64 + 1 ;
36+ let f = Function {
37+ id : id,
38+ name : name,
39+ system_name : 0 ,
40+ filename : 0 ,
41+ start_line : 0 ,
42+ } ;
43+ self . functions . insert ( name, id) ;
44+ self . profile . function . push ( f) ;
45+ id
46+ }
47+
48+ fn add_location ( & mut self , function_id : u64 ) -> u64 {
49+ let v = self . locations . get ( & function_id) ;
50+ if v. is_some ( ) {
51+ return * v. unwrap ( ) ;
52+ }
53+ assert ! ( self . locations. len( ) != self . profile. location. len( ) + 1 ) ;
54+ let id: u64 = self . locations . len ( ) as u64 + 1 ;
55+ let l = Location {
56+ id,
57+ mapping_id : 0 ,
58+ address : 0 ,
59+ line : vec ! [ Line {
60+ function_id: function_id,
61+ line: 0 ,
62+ } ] ,
63+ is_folded : false ,
64+ } ;
65+ self . locations . insert ( function_id, id) ;
66+ self . profile . location . push ( l) ;
67+ id
68+ }
69+ }
70+
71+ pub fn encode ( reports : Vec < Report > ) -> Vec < EncodedReport > {
72+ let mut b = PProfBuilder {
73+ strings : HashMap :: new ( ) ,
74+ functions : HashMap :: new ( ) ,
75+ locations : HashMap :: new ( ) ,
76+ profile : Profile {
77+ sample_type : vec ! [ ] ,
78+ sample : vec ! [ ] ,
79+ mapping : vec ! [ ] ,
80+ location : vec ! [ ] ,
81+ function : vec ! [ ] ,
82+ string_table : vec ! [ ] ,
83+ drop_frames : 0 ,
84+ keep_frames : 0 ,
85+ time_nanos : 0 ,
86+ duration_nanos : 0 ,
87+ period_type : None ,
88+ period : 0 ,
89+ comment : vec ! [ ] ,
90+ default_sample_type : 0 ,
91+ } ,
92+ } ;
93+ {
94+ let cpu = b. add_string ( & "cpu" . to_string ( ) ) ;
95+ let samples = b. add_string ( & "samples" . to_string ( ) ) ;
96+ b. profile . sample_type . push ( ValueType {
97+ r#type : samples,
98+ unit : cpu,
99+ } ) ;
100+ }
101+ for report in & reports {
102+ for ( stacktrace, value) in & report. data {
103+ let mut sample = Sample {
104+ location_id : vec ! [ ] ,
105+ value : vec ! [ * value as i64 ] ,
106+ label : vec ! [ ] ,
107+ } ;
108+ for sf in & stacktrace. frames {
109+ let name = format ! ( "{}:{} - {}" ,
110+ sf. filename. as_ref( ) . unwrap_or( & "" . to_string( ) ) ,
111+ sf. line. unwrap_or( 0 ) ,
112+ sf. name. as_ref( ) . unwrap_or( & "" . to_string( ) ) ) ;
113+ let name = b. add_string ( & name) ;
114+ let function_id = b. add_function ( name) ;
115+ let location_id = b. add_location ( function_id) ;
116+ sample. location_id . push ( location_id as u64 ) ;
117+ }
118+ b. profile . sample . push ( sample) ;
119+ }
120+ }
121+
122+ vec ! [ EncodedReport {
123+ format: "pprof" . to_string( ) ,
124+ content_type: "binary/octet-stream" . to_string( ) ,
125+ content_encoding: "" . to_string( ) ,
126+ data: b. profile. encode_to_vec( ) ,
127+ metadata: Default :: default ( ) ,
128+ } ]
129+ }
0 commit comments