@@ -140,8 +140,11 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
140140
141141 // Gather and report analytics.
142142 const analytics = await this . getAnalytics ( ) ;
143+ let stopPeriodicFlushes : ( ( ) => Promise < void > ) | undefined ;
144+
143145 if ( this . shouldReportAnalytics ) {
144146 await this . reportAnalytics ( camelCasedOptions ) ;
147+ stopPeriodicFlushes = this . periodicAnalyticsFlush ( analytics ) ;
145148 }
146149
147150 let exitCode : number | void | undefined ;
@@ -151,7 +154,6 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
151154 exitCode = await this . run ( camelCasedOptions as Options < T > & OtherOptions ) ;
152155 const endTime = Date . now ( ) ;
153156 analytics . timing ( this . commandName , 'duration' , endTime - startTime ) ;
154- await analytics . flush ( ) ;
155157 } catch ( e ) {
156158 if ( e instanceof schema . SchemaValidationException ) {
157159 this . context . logger . fatal ( `Error: ${ e . message } ` ) ;
@@ -160,6 +162,8 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
160162 throw e ;
161163 }
162164 } finally {
165+ await stopPeriodicFlushes ?.( ) ;
166+
163167 if ( typeof exitCode === 'number' && exitCode > 0 ) {
164168 process . exitCode = exitCode ;
165169 }
@@ -170,6 +174,7 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
170174 options : ( Options < T > & OtherOptions ) | OtherOptions ,
171175 paths : string [ ] = [ ] ,
172176 dimensions : ( boolean | number | string ) [ ] = [ ] ,
177+ title ?: string ,
173178 ) : Promise < void > {
174179 for ( const [ name , ua ] of this . optionsWithAnalytics ) {
175180 const value = options [ name ] ;
@@ -183,6 +188,7 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
183188 analytics . pageview ( '/command/' + [ this . commandName , ...paths ] . join ( '/' ) , {
184189 dimensions,
185190 metrics : [ ] ,
191+ title,
186192 } ) ;
187193 }
188194
@@ -275,6 +281,26 @@ export abstract class CommandModule<T extends {} = {}> implements CommandModuleI
275281
276282 return workspace ;
277283 }
284+
285+ /**
286+ * Flush on an interval (if the event loop is waiting).
287+ *
288+ * @returns a method that when called will terminate the periodic
289+ * flush and call flush one last time.
290+ */
291+ private periodicAnalyticsFlush ( analytics : analytics . Analytics ) : ( ) => Promise < void > {
292+ let analyticsFlushPromise = Promise . resolve ( ) ;
293+ const analyticsFlushInterval = setInterval ( ( ) => {
294+ analyticsFlushPromise = analyticsFlushPromise . then ( ( ) => analytics . flush ( ) ) ;
295+ } , 2000 ) ;
296+
297+ return ( ) => {
298+ clearInterval ( analyticsFlushInterval ) ;
299+
300+ // Flush one last time.
301+ return analyticsFlushPromise . then ( ( ) => analytics . flush ( ) ) ;
302+ } ;
303+ }
278304}
279305
280306/**
0 commit comments