blob: db6d67f39804567a06910830ae8e1cdfe3653ec9 [file] [log] [blame]
// 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 {stringifyJsonWithBigints} from '../../../../base/json_utils';
import {raf} from '../../../../core/raf_scheduler';
import {Engine} from '../../../../trace_processor/engine';
import {Row} from '../../../../trace_processor/query_result';
import {ChartData, ChartState, VegaLiteChartSpec} from '../chart';
export interface HistogramChartConfig extends VegaLiteChartSpec {
binAxisType: 'nominal' | 'quantitative';
binAxis: 'x' | 'y';
countAxis: 'x' | 'y';
sort: string;
isBinned: boolean;
labelLimit?: number;
}
export class HistogramState implements ChartState {
data?: ChartData;
spec?: VegaLiteChartSpec;
constructor(
readonly engine: Engine,
readonly query: string,
readonly columns: string[],
private aggregationType?: 'nominal' | 'quantitative',
) {
this.loadData();
}
createHistogramVegaSpec(): VegaLiteChartSpec {
const binAxisEncoding = {
bin: this.aggregationType !== 'nominal',
field: this.columns[0],
type: this.aggregationType,
title: this.columns[0],
sort: this.aggregationType === 'nominal' && {
op: 'count',
order: 'descending',
},
axis: {
labelLimit: 500,
},
};
const countAxisEncoding = {
aggregate: 'count',
title: 'Count',
};
const spec: VegaLiteChartSpec = {
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
width: 'container',
mark: 'bar',
data: {
values: this.data?.rows,
},
encoding: {
x:
this.aggregationType !== 'nominal'
? binAxisEncoding
: countAxisEncoding,
y:
this.aggregationType !== 'nominal'
? countAxisEncoding
: binAxisEncoding,
},
};
return spec;
}
async loadData() {
const res = await this.engine.query(`
SELECT ${this.columns[0]}
FROM (
${this.query}
)
`);
const rows: Row[] = [];
let hasQuantitativeData = false;
for (const it = res.iter({}); it.valid(); it.next()) {
const rowVal = it.get(this.columns[0]);
if (typeof rowVal === 'bigint') {
hasQuantitativeData = true;
}
rows.push({
[this.columns[0]]: rowVal,
});
}
if (this.aggregationType === undefined) {
this.aggregationType = hasQuantitativeData ? 'quantitative' : 'nominal';
}
this.data = {
rows,
};
this.spec = this.createHistogramVegaSpec();
raf.scheduleFullRedraw();
}
isLoading(): boolean {
return this.data === undefined;
}
}