| // Copyright (C) 2024 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| import m from 'mithril'; |
| import {Row} from '../../../trace_processor/query_result'; |
| import {Engine} from '../../../trace_processor/engine'; |
| import {Filter, TableColumn, TableColumnSet} from '../sql/table/column'; |
| import {Histogram} from './histogram/histogram'; |
| import {SqlTableState} from '../sql/table/state'; |
| import {columnTitle} from '../sql/table/table'; |
| |
| export interface VegaLiteChartSpec { |
| $schema: string; |
| width: string | number; |
| mark: |
| | 'area' |
| | 'bar' |
| | 'circle' |
| | 'line' |
| | 'point' |
| | 'rect' |
| | 'rule' |
| | 'square' |
| | 'text' |
| | 'tick' |
| | 'geoshape' |
| | 'boxplot' |
| | 'errorband' |
| | 'errorbar'; |
| data: {values?: string | Row[]}; |
| |
| encoding: { |
| x: {[key: string]: unknown}; |
| y: {[key: string]: unknown}; |
| }; |
| } |
| |
| // Holds the various chart types and human readable string |
| export enum ChartOption { |
| HISTOGRAM = 'histogram', |
| } |
| |
| export interface ChartConfig { |
| readonly engine: Engine; |
| readonly columnTitle: string; // Human readable column name (ex: Duration) |
| readonly sqlColumn: string[]; // SQL column name (ex: dur) |
| readonly filters?: Filter[]; // Filters applied to SQL table |
| readonly tableDisplay?: string; // Human readable table name (ex: slices) |
| readonly query: string; // SQL query for the underlying data |
| readonly aggregationType?: 'nominal' | 'quantitative'; // Aggregation type. |
| } |
| |
| export interface Chart { |
| readonly option: ChartOption; |
| readonly config: ChartConfig; |
| } |
| |
| export interface ChartData { |
| readonly rows: Row[]; |
| readonly error?: string; |
| } |
| |
| export interface ChartState { |
| readonly engine: Engine; |
| readonly query: string; |
| readonly columns: TableColumn[] | TableColumnSet[] | string[]; |
| data?: ChartData; |
| spec?: VegaLiteChartSpec; |
| loadData(): Promise<void>; |
| isLoading(): boolean; |
| } |
| |
| export function toTitleCase(s: string): string { |
| const words = s.split(/\s/); |
| |
| for (let i = 0; i < words.length; ++i) { |
| words[i] = words[i][0].toUpperCase() + words[i].substring(1); |
| } |
| |
| return words.join(' '); |
| } |
| |
| // renderChartComponent will take a chart option and config and map |
| // to the corresponding chart class component. |
| export function renderChartComponent(chart: Chart) { |
| switch (chart.option) { |
| case ChartOption.HISTOGRAM: |
| return m(Histogram, chart.config); |
| default: |
| return; |
| } |
| } |
| |
| export function createChartConfigFromSqlTableState( |
| column: TableColumn, |
| columnAlias: string, |
| sqlTableState: SqlTableState, |
| ) { |
| return { |
| engine: sqlTableState.trace.engine, |
| columnTitle: columnTitle(column), |
| sqlColumn: [columnAlias], |
| filters: sqlTableState?.getFilters(), |
| tableDisplay: sqlTableState.config.displayName ?? sqlTableState.config.name, |
| query: sqlTableState.getSqlQuery( |
| Object.fromEntries([[columnAlias, column.primaryColumn()]]), |
| ), |
| aggregationType: column.aggregation?.().dataType, |
| }; |
| } |