| Index: tracing/tracing/metrics/metric_map_function.html
 | 
| diff --git a/tracing/tracing/metrics/metric_map_function.html b/tracing/tracing/metrics/metric_map_function.html
 | 
| index a4f10972021338995dade1d19d7067bd850cbee3..1624436520901a545356c333e2e537bb5fbe5b27 100644
 | 
| --- a/tracing/tracing/metrics/metric_map_function.html
 | 
| +++ b/tracing/tracing/metrics/metric_map_function.html
 | 
| @@ -21,27 +21,70 @@ tr.exportTo('tr.metrics', function() {
 | 
|     * @return {!tr.v.HistogramSet}
 | 
|     */
 | 
|    function runMetrics(model, options) {
 | 
| -    if (options === undefined)
 | 
| +    if (options === undefined) {
 | 
|        throw new Error('Options are required.');
 | 
| +    }
 | 
|  
 | 
|      var metricNames = options.metrics;
 | 
| -    if (!metricNames)
 | 
| +    if (!metricNames) {
 | 
|        throw new Error('Metric names should be specified.');
 | 
| +    }
 | 
|  
 | 
|      var histograms = new tr.v.HistogramSet();
 | 
|  
 | 
| +    var metrics = [];
 | 
|      for (var metricName of metricNames) {
 | 
|        var metric = tr.metrics.MetricRegistry.findTypeInfoWithName(metricName);
 | 
| -      if (metric === undefined)
 | 
| +      if (metric === undefined) {
 | 
|          throw new Error('"' + metricName + '" is not a registered metric.');
 | 
| -      metric.constructor(histograms, model, options);
 | 
| +      }
 | 
| +      metrics.push(metric);
 | 
| +      try {
 | 
| +        metric.constructor(histograms, model, options);
 | 
| +      } catch (e) {
 | 
| +        synthesizeFailureHistograms(histograms, metric, e);
 | 
| +      }
 | 
|      }
 | 
|  
 | 
| +    validateHistogramNames(histograms, metrics);
 | 
| +
 | 
|      return histograms;
 | 
|    }
 | 
|  
 | 
|    /**
 | 
|     * @param {!tr.v.HistogramSet} histograms
 | 
| +   * @param {!Array.<!tr.b.RegisteredTypeInfo>} metrics
 | 
| +   */
 | 
| +  function validateHistogramNames(histograms, metrics) {
 | 
| +    var registeredHistogramNames = new Set();
 | 
| +    for (var metric of metrics) {
 | 
| +      for (var name of metric.metadata.histogramNames) {
 | 
| +        registeredHistogramNames.add(name);
 | 
| +      }
 | 
| +    }
 | 
| +    for (var hist of histograms) {
 | 
| +      if (!registeredHistogramNames.has(hist.name)) {
 | 
| +        throw new Error('"' + hist.name +
 | 
| +                        '" is not a registered histogram name.');
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  /**
 | 
| +   * @param {!tr.v.HistogramSet} histograms
 | 
| +   * @param {!tr.b.RegisteredTypeInfo} metric
 | 
| +   * @param {!Error} error
 | 
| +   */
 | 
| +  function synthesizeFailureHistograms(histograms, metric, error) {
 | 
| +    for (var name of metric.metadata.histogramNames) {
 | 
| +      var hist = new tr.v.Histogram(name, tr.b.Unit.byName.unitlessNumber);
 | 
| +      // TODO(benjhayden): add a FailureInfo containing |error|.
 | 
| +      histograms.addHistogram(hist);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  /**
 | 
| +   * @param {!tr.v.HistogramSet} histograms
 | 
|     * @param {!tr.model.Model} model
 | 
|     */
 | 
|    function addTelemetryInfo(histograms, model) {
 | 
| 
 |