@@ -3,7 +3,9 @@ use anyhow::Context;
33use chrono:: { DateTime , Utc } ;
44use log:: { debug, info} ;
55use ra_ap_project_model:: ProjectManifest ;
6+ use serde:: ser:: SerializeMap ;
67use serde:: Serialize ;
8+ use std:: collections:: HashMap ;
79use std:: fmt:: Display ;
810use std:: fs:: File ;
911use std:: path:: { Path , PathBuf } ;
@@ -72,27 +74,29 @@ pub struct Diagnostics<T> {
7274 attributes : T ,
7375}
7476
75- #[ derive( Debug , Clone , Serialize ) ]
77+ #[ derive( Default , Debug , Clone , Copy , Serialize , PartialEq , Eq , Hash ) ]
7678#[ serde( rename_all = "camelCase" ) ]
77- enum ExtractionStepTarget {
78- LoadManifest ( PathBuf ) ,
79- FetchFile ( PathBuf ) ,
80- Parse ( PathBuf ) ,
81- Extract ( PathBuf ) ,
79+ enum ExtractionStepKind {
80+ #[ default]
81+ LoadManifest ,
82+ LoadSource ,
83+ Parse ,
84+ Extract ,
8285}
8386
8487#[ derive( Debug , Clone , Serialize ) ]
8588#[ serde( rename_all = "camelCase" ) ]
8689pub struct ExtractionStep {
87- # [ serde ( flatten ) ]
88- target : ExtractionStepTarget ,
90+ action : ExtractionStepKind ,
91+ file : PathBuf ,
8992 ms : u128 ,
9093}
9194
9295impl ExtractionStep {
93- fn new ( start : Instant , target : ExtractionStepTarget ) -> Self {
96+ fn new ( start : Instant , action : ExtractionStepKind , file : PathBuf ) -> Self {
9497 let ret = ExtractionStep {
95- target,
98+ action,
99+ file,
96100 ms : start. elapsed ( ) . as_millis ( ) ,
97101 } ;
98102 debug ! ( "{ret:?}" ) ;
@@ -102,70 +106,84 @@ impl ExtractionStep {
102106 pub fn load_manifest ( start : Instant , target : & ProjectManifest ) -> Self {
103107 Self :: new (
104108 start,
105- ExtractionStepTarget :: LoadManifest ( PathBuf :: from ( target. manifest_path ( ) ) ) ,
109+ ExtractionStepKind :: LoadManifest ,
110+ PathBuf :: from ( target. manifest_path ( ) ) ,
106111 )
107112 }
108113
109114 pub fn parse ( start : Instant , target : & Path ) -> Self {
110- Self :: new ( start, ExtractionStepTarget :: Parse ( PathBuf :: from ( target) ) )
115+ Self :: new ( start, ExtractionStepKind :: Parse , PathBuf :: from ( target) )
111116 }
112117
113118 pub fn extract ( start : Instant , target : & Path ) -> Self {
114- Self :: new ( start, ExtractionStepTarget :: Extract ( PathBuf :: from ( target) ) )
119+ Self :: new ( start, ExtractionStepKind :: Extract , PathBuf :: from ( target) )
115120 }
116121
117- pub fn fetch_file ( start : Instant , target : & Path ) -> Self {
118- Self :: new (
119- start,
120- ExtractionStepTarget :: FetchFile ( PathBuf :: from ( target) ) ,
121- )
122+ pub fn load_source ( start : Instant , target : & Path ) -> Self {
123+ Self :: new ( start, ExtractionStepKind :: LoadSource , PathBuf :: from ( target) )
122124 }
123125}
124126
125- #[ derive( Debug , Default , Clone , Serialize ) ]
126- #[ serde( rename_all = "camelCase" ) ]
127- struct HumanReadableDuration {
128- ms : u128 ,
129- pretty : String ,
127+ #[ derive( Debug , Default , Clone ) ]
128+ struct HumanReadableDuration ( u128 ) ;
129+
130+ impl Serialize for HumanReadableDuration {
131+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
132+ let mut map = serializer. serialize_map ( Some ( 2 ) ) ?;
133+ map. serialize_entry ( "ms" , & self . 0 ) ?;
134+ map. serialize_entry ( "pretty" , & self . pretty ( ) ) ?;
135+ map. end ( )
136+ }
130137}
131138
132139impl HumanReadableDuration {
133- pub fn new ( ms : u128 ) -> Self {
134- let seconds = ms / 1000 ;
135- let minutes = seconds / 60 ;
140+ pub fn add ( & mut self , other : u128 ) {
141+ self . 0 += other;
142+ }
143+
144+ pub fn pretty ( & self ) -> String {
145+ let milliseconds = self . 0 % 1000 ;
146+ let mut seconds = self . 0 / 1000 ;
147+ if seconds < 60 {
148+ return format ! ( "{seconds}.{milliseconds:03}s" ) ;
149+ }
150+ let mut minutes = seconds / 60 ;
151+ seconds %= 60 ;
152+ if minutes < 60 {
153+ return format ! ( "{minutes}min{seconds:02}.{milliseconds:03}s" ) ;
154+ }
136155 let hours = minutes / 60 ;
137- let pretty = format ! (
138- "{hours}:{minutes:02}:{seconds:02}.{milliseconds:03}" ,
139- minutes = minutes % 60 ,
140- seconds = seconds % 60 ,
141- milliseconds = ms % 1000 ,
142- ) ;
143- Self { ms, pretty }
156+ minutes %= 60 ;
157+ format ! ( "{hours}h{minutes:02}min{seconds:02}.{milliseconds:03}s" )
144158 }
145159}
146160
147161impl From < u128 > for HumanReadableDuration {
148162 fn from ( val : u128 ) -> Self {
149- HumanReadableDuration :: new ( val)
163+ HumanReadableDuration ( val)
150164 }
151165}
152166
153167impl Display for HumanReadableDuration {
154168 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
155- write ! ( f , "{}ms ({})" , self . ms , self . pretty)
169+ f . write_str ( & self . pretty ( ) )
156170 }
157171}
158172
173+ #[ derive( Debug , Default , Clone , Serialize ) ]
174+ #[ serde( rename_all = "camelCase" ) ]
175+ struct DurationsSummary {
176+ #[ serde( flatten) ]
177+ durations : HashMap < ExtractionStepKind , HumanReadableDuration > ,
178+ total : HumanReadableDuration ,
179+ }
180+
159181#[ derive( Debug , Default , Clone , Serialize ) ]
160182#[ serde( rename_all = "camelCase" ) ]
161183struct ExtractionSummary {
162184 number_of_manifests : usize ,
163185 number_of_files : usize ,
164- total_load_duration : HumanReadableDuration ,
165- total_fetch_file_duration : HumanReadableDuration ,
166- total_parse_duration : HumanReadableDuration ,
167- total_extract_duration : HumanReadableDuration ,
168- total_duration : HumanReadableDuration ,
186+ durations : DurationsSummary ,
169187}
170188
171189#[ derive( Debug , Default , Clone , Serialize ) ]
@@ -180,46 +198,32 @@ type ExtractionDiagnostics = Diagnostics<ExtractionAttributes>;
180198fn summary ( start : Instant , steps : & [ ExtractionStep ] ) -> ExtractionSummary {
181199 let mut number_of_manifests = 0 ;
182200 let mut number_of_files = 0 ;
183- let mut total_load_duration = 0 ;
184- let mut total_parse_duration = 0 ;
185- let mut total_extract_duration = 0 ;
186- let mut total_fetch_file_duration: u128 = 0 ;
201+ let mut durations = HashMap :: new ( ) ;
187202 for step in steps {
188- match & step. target {
189- ExtractionStepTarget :: LoadManifest ( _ ) => {
203+ match & step. action {
204+ ExtractionStepKind :: LoadManifest => {
190205 number_of_manifests += 1 ;
191- total_load_duration += step. ms ;
192206 }
193- ExtractionStepTarget :: FetchFile ( _ ) => {
207+ ExtractionStepKind :: Parse => {
194208 number_of_files += 1 ;
195- total_fetch_file_duration += step. ms ;
196- }
197- ExtractionStepTarget :: Parse ( _) => {
198- total_parse_duration += step. ms ;
199- }
200- ExtractionStepTarget :: Extract ( _) => {
201- total_extract_duration += step. ms ;
202209 }
210+ _ => { }
203211 }
212+ durations
213+ . entry ( step. action )
214+ . or_insert ( HumanReadableDuration ( 0 ) )
215+ . add ( step. ms ) ;
204216 }
205- let ret = ExtractionSummary {
217+ let total = start. elapsed ( ) . as_millis ( ) . into ( ) ;
218+ for ( key, value) in & durations {
219+ info ! ( "total duration ({key:?}): {value}" ) ;
220+ }
221+ info ! ( "total duration: {total}" ) ;
222+ ExtractionSummary {
206223 number_of_manifests,
207224 number_of_files,
208- total_load_duration : total_load_duration. into ( ) ,
209- total_fetch_file_duration : total_fetch_file_duration. into ( ) ,
210- total_parse_duration : total_parse_duration. into ( ) ,
211- total_extract_duration : total_extract_duration. into ( ) ,
212- total_duration : start. elapsed ( ) . as_millis ( ) . into ( ) ,
213- } ;
214- info ! ( "total loadimg duration: {}" , ret. total_load_duration) ;
215- info ! (
216- "total file fetching duration: {}" ,
217- ret. total_fetch_file_duration
218- ) ;
219- info ! ( "total parsing duration: {}" , ret. total_parse_duration) ;
220- info ! ( "total extracting duration: {}" , ret. total_extract_duration) ;
221- info ! ( "total duration: {}" , ret. total_duration) ;
222- ret
225+ durations : DurationsSummary { durations, total } ,
226+ }
223227}
224228
225229pub fn emit_extraction_diagnostics (
0 commit comments