@@ -10,6 +10,7 @@ import 'package:analysis_server/protocol/protocol_constants.dart';
1010import 'package:analysis_server/src/analytics/active_request_data.dart' ;
1111import 'package:analysis_server/src/analytics/context_structure.dart' ;
1212import 'package:analysis_server/src/analytics/notification_data.dart' ;
13+ import 'package:analysis_server/src/analytics/percentile_calculator.dart' ;
1314import 'package:analysis_server/src/analytics/plugin_data.dart' ;
1415import 'package:analysis_server/src/analytics/request_data.dart' ;
1516import 'package:analysis_server/src/analytics/session_data.dart' ;
@@ -83,6 +84,13 @@ class AnalyticsManager {
8384 /// represented by the key.
8485 final Map <String , Map <String , int >> _severityAdjustments = {};
8586
87+ /// The start time of the current window during which analysis was working,
88+ /// or `null` if analysis is currently idle.
89+ DateTime ? _analysisWorkingStart;
90+
91+ /// Accumulates durations (in ms) of periods where analysis was working.
92+ final PercentileCalculator _analysisWorkingDurations = PercentileCalculator ();
93+
8694 /// A periodic timer used to send analytics data. This timer should be
8795 /// cancelled at shutdown.
8896 Timer ? periodicTimer;
@@ -128,6 +136,15 @@ class AnalyticsManager {
128136 );
129137 }
130138
139+ /// Called when analysis status changes to record period durations.
140+ void analysisStatusChanged (bool isWorking) {
141+ if (isWorking) {
142+ _analysisWorkingStart ?? = DateTime .now ();
143+ } else {
144+ _finalizeOpenWorkingPeriod ();
145+ }
146+ }
147+
131148 /// Record that the set of plugins known to the [pluginManager] has changed.
132149 void changedPlugins (PluginManager pluginManager) {
133150 _pluginData.recordPlugins (pluginManager);
@@ -431,6 +448,13 @@ class AnalyticsManager {
431448 buffer.writeln ('</ul>' );
432449 }
433450
451+ if (_analysisWorkingDurations.valueCount > 0 ) {
452+ h3 ('Analysis status periods' );
453+ buffer.writeln ('<ul>' );
454+ li ('workingDurations: ${_analysisWorkingDurations .toAnalyticsString ()}' );
455+ buffer.writeln ('</ul>' );
456+ }
457+
434458 if (_lintUsageCounts.isNotEmpty) {
435459 h3 ('Lint usage counts' );
436460 buffer.writeln ('<ul>' );
@@ -478,6 +502,16 @@ class AnalyticsManager {
478502 return buffer.toString ();
479503 }
480504
505+ void _finalizeOpenWorkingPeriod () {
506+ if (_analysisWorkingStart case var workingStart? ) {
507+ var durationMilliseconds =
508+ DateTime .now ().millisecondsSinceEpoch -
509+ workingStart.millisecondsSinceEpoch;
510+ _analysisWorkingDurations.addValue (durationMilliseconds);
511+ _analysisWorkingStart = null ;
512+ }
513+ }
514+
481515 /// Record that the request with the given [id] was responded to at the given
482516 /// [sendTime] .
483517 void _recordResponseData (String id, DateTime sendTime) {
@@ -525,6 +559,19 @@ class AnalyticsManager {
525559 }
526560 }
527561
562+ /// Send information about analysis statistics.
563+ Future <void > _sendAnalysisStatistics () async {
564+ if (_analysisWorkingDurations.valueCount == 0 ) {
565+ return ;
566+ }
567+ analytics.send (
568+ Event .analysisStatistics (
569+ workingDuration: _analysisWorkingDurations.toAnalyticsString (),
570+ ),
571+ );
572+ _analysisWorkingDurations.clear ();
573+ }
574+
528575 /// Send information about the number of times each lint is enabled in an
529576 /// analysis options file.
530577 Future <void > _sendLintUsageCounts () async {
@@ -564,6 +611,7 @@ class AnalyticsManager {
564611 await _sendNotificationHandlingTimes ();
565612 await _sendLintUsageCounts ();
566613 await _sendSeverityAdjustments ();
614+ await _sendAnalysisStatistics ();
567615 }
568616
569617 /// Send information about the response times of plugins.
0 commit comments