1// Copyright (C) 2024 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. 14import m from 'mithril'; 15import {Row} from '../../../trace_processor/query_result'; 16import {Engine} from '../../../trace_processor/engine'; 17import {Filter, TableColumn, TableColumnSet} from '../sql/table/column'; 18import {Histogram} from './histogram/histogram'; 19import {SqlTableState} from '../sql/table/state'; 20import {columnTitle} from '../sql/table/table'; 21 22export interface VegaLiteChartSpec { 23 $schema: string; 24 width: string | number; 25 mark: 26 | 'area' 27 | 'bar' 28 | 'circle' 29 | 'line' 30 | 'point' 31 | 'rect' 32 | 'rule' 33 | 'square' 34 | 'text' 35 | 'tick' 36 | 'geoshape' 37 | 'boxplot' 38 | 'errorband' 39 | 'errorbar'; 40 data: {values?: string | Row[]}; 41 42 encoding: { 43 x: {[key: string]: unknown}; 44 y: {[key: string]: unknown}; 45 }; 46} 47 48// Holds the various chart types and human readable string 49export enum ChartOption { 50 HISTOGRAM = 'histogram', 51} 52 53export interface ChartConfig { 54 readonly engine: Engine; 55 readonly columnTitle: string; // Human readable column name (ex: Duration) 56 readonly sqlColumn: string[]; // SQL column name (ex: dur) 57 readonly filters?: Filter[]; // Filters applied to SQL table 58 readonly tableDisplay?: string; // Human readable table name (ex: slices) 59 readonly query: string; // SQL query for the underlying data 60 readonly aggregationType?: 'nominal' | 'quantitative'; // Aggregation type. 61} 62 63export interface Chart { 64 readonly option: ChartOption; 65 readonly config: ChartConfig; 66} 67 68export interface ChartData { 69 readonly rows: Row[]; 70 readonly error?: string; 71} 72 73export interface ChartState { 74 readonly engine: Engine; 75 readonly query: string; 76 readonly columns: TableColumn[] | TableColumnSet[] | string[]; 77 data?: ChartData; 78 spec?: VegaLiteChartSpec; 79 loadData(): Promise<void>; 80 isLoading(): boolean; 81} 82 83export function toTitleCase(s: string): string { 84 const words = s.split(/\s/); 85 86 for (let i = 0; i < words.length; ++i) { 87 words[i] = words[i][0].toUpperCase() + words[i].substring(1); 88 } 89 90 return words.join(' '); 91} 92 93// renderChartComponent will take a chart option and config and map 94// to the corresponding chart class component. 95export function renderChartComponent(chart: Chart) { 96 switch (chart.option) { 97 case ChartOption.HISTOGRAM: 98 return m(Histogram, chart.config); 99 default: 100 return; 101 } 102} 103 104export function createChartConfigFromSqlTableState( 105 column: TableColumn, 106 columnAlias: string, 107 sqlTableState: SqlTableState, 108) { 109 return { 110 engine: sqlTableState.trace.engine, 111 columnTitle: columnTitle(column), 112 sqlColumn: [columnAlias], 113 filters: sqlTableState?.getFilters(), 114 tableDisplay: sqlTableState.config.displayName ?? sqlTableState.config.name, 115 query: sqlTableState.getSqlQuery( 116 Object.fromEntries([[columnAlias, column.primaryColumn()]]), 117 ), 118 aggregationType: column.aggregation?.().dataType, 119 }; 120} 121