xref: /aosp_15_r20/external/perfetto/ui/src/components/widgets/charts/chart.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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