| // Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | library; | 
 |  | 
 | /// A collection of metrics that is normally associated with a task. | 
 | abstract class Metrics { | 
 |   /// The namespace prepended to all the metric names with a period (`.`). | 
 |   /// An empty string means no namespace. | 
 |   String get namespace; | 
 |  | 
 |   /// Returns all the primary metrics. Only a few metrics that give an overall | 
 |   /// picture of the compilation should be selected as primary metrics. | 
 |   Iterable<Metric> get primary; | 
 |  | 
 |   /// Returns all the secondary metrics. Typically these are displayed together | 
 |   /// with the primary metrics to give three levels of detail: no metrics, just | 
 |   /// the primary metrics, all metrics including primary and secondary metrics. | 
 |   Iterable<Metric> get secondary; | 
 |  | 
 |   factory Metrics.none() => _emptyMetrics; | 
 | } | 
 |  | 
 | final Metrics _emptyMetrics = MetricsBase(); | 
 |  | 
 | class MetricsBase implements Metrics { | 
 |   @override | 
 |   String get namespace => ''; | 
 |  | 
 |   // TODO(sra): Make these late final fields. | 
 |   final List<Metric> _primary = []; | 
 |   final List<Metric> _secondary = []; | 
 |  | 
 |   /// Setter method that is usually called in a subclass constructor to define | 
 |   /// the primary metrics. | 
 |   set primary(Iterable<Metric> metrics) { | 
 |     assert(_primary.isEmpty); | 
 |     _primary.addAll(metrics); | 
 |   } | 
 |  | 
 |   /// Setter method that is usually called in a subclass constructor to define | 
 |   /// the secondary metrics. | 
 |   set secondary(Iterable<Metric> metrics) { | 
 |     assert(_secondary.isEmpty); | 
 |     _secondary.addAll(metrics); | 
 |   } | 
 |  | 
 |   @override | 
 |   Iterable<Metric> get primary => _primary; | 
 |  | 
 |   @override | 
 |   Iterable<Metric> get secondary => _secondary; | 
 | } | 
 |  | 
 | abstract class Metric { | 
 |   String get name; | 
 |   String formatValue(); | 
 | } | 
 |  | 
 | class DurationMetric implements Metric { | 
 |   @override | 
 |   final String name; | 
 |   Duration _duration = Duration.zero; | 
 |  | 
 |   DurationMetric(this.name); | 
 |  | 
 |   void add(Duration value) { | 
 |     _duration += value; | 
 |   } | 
 |  | 
 |   T measure<T>(T Function() action) { | 
 |     final stopwatch = Stopwatch()..start(); | 
 |     T result = action(); | 
 |     add(stopwatch.elapsed); | 
 |     return result; | 
 |   } | 
 |  | 
 |   @override | 
 |   String formatValue() { | 
 |     return '${(_duration.inMilliseconds / 1000).toStringAsFixed(3)}s'; | 
 |   } | 
 |  | 
 |   @override | 
 |   String toString() => 'DurationMetric("$name", $_duration)'; | 
 | } | 
 |  | 
 | class CountMetric implements Metric { | 
 |   @override | 
 |   final String name; | 
 |   int _count = 0; | 
 |  | 
 |   CountMetric(this.name); | 
 |  | 
 |   void add([int count = 1]) { | 
 |     _count += count; | 
 |   } | 
 |  | 
 |   @override | 
 |   String formatValue() => '$_count'; | 
 |  | 
 |   @override | 
 |   String toString() => 'CountMetric("$name", $_count)'; | 
 | } |