1// Copyright (C) 2020 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {Actions} from '../common/actions'; 16import {Engine, QueryError} from '../common/engine'; 17import {iter, STR} from '../common/query_iterator'; 18 19import {Controller} from './controller'; 20import {globals} from './globals'; 21 22export class MetricsController extends Controller<'main'> { 23 private engine: Engine; 24 private currentlyRunningMetric?: string; 25 26 constructor(args: {engine: Engine}) { 27 super('main'); 28 this.engine = args.engine; 29 this.setup().finally(() => { 30 this.run(); 31 }); 32 } 33 34 private async getMetricNames() { 35 const metrics = []; 36 const it = iter( 37 { 38 name: STR, 39 }, 40 await this.engine.query('select name from trace_metrics')); 41 for (; it.valid(); it.next()) { 42 metrics.push(it.row.name); 43 } 44 return metrics; 45 } 46 47 private async setup() { 48 const metrics = await this.getMetricNames(); 49 globals.dispatch(Actions.setAvailableMetrics({metrics})); 50 } 51 52 private async computeMetric(name: string) { 53 if (name === this.currentlyRunningMetric) return; 54 this.currentlyRunningMetric = name; 55 try { 56 const metricResult = await this.engine.computeMetric([name]); 57 globals.publish( 58 'MetricResult', 59 {name, resultString: metricResult.metricsAsPrototext}); 60 } catch (e) { 61 if (e instanceof QueryError) { 62 // Reroute error to be displated differently when metric is run through 63 // metric page. 64 globals.publish('MetricResult', {name, error: e.message}); 65 } else { 66 throw e; 67 } 68 } 69 globals.dispatch(Actions.resetMetricRequest({name})); 70 this.currentlyRunningMetric = undefined; 71 } 72 73 run() { 74 const {requestedMetric} = globals.state.metrics; 75 if (!requestedMetric) return; 76 this.computeMetric(requestedMetric); 77 } 78} 79