blob: 2c55adb1a41a6b89ab300f13800c6b56db102105 [file]
// Copyright (C) 2026 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 type {Filter} from '../../components/widgets/datagrid/model';
import {
SingleFieldStorage,
parseNullableStringArray,
} from './single_field_storage';
import {linkNameFirst} from './column_order';
// Persisted trace-selection state: the trace filter, processing order, the
// trace-grid shown columns, and the metadata columns attached to results.
// Subset of a /trace_metadata_schema column the resolvers below need.
interface SchemaColumn {
readonly name: string;
readonly defaultVisible: boolean;
}
// Filter chips for the trace-selection grid: the active filter IS the trace set
// a query runs over. Shipped as `trace_filters` on /execute_*. get() returns []
// for nothing/malformed/cleared.
export const traceFilterState = new SingleFieldStorage<readonly Filter[]>(
'bigtraceTraceFilters',
'filters',
(raw) => (Array.isArray(raw) ? (raw as Filter[]) : []),
[],
);
// AIP-132 ordering string, shipped as `trace_order_by` on /execute_*. Matters
// under a trace cap (picks which first-N survive). get() returns '' (default
// ordering) for nothing/non-string.
export const traceOrderByState = new SingleFieldStorage<string>(
'bigtraceTraceOrderBy',
'orderBy',
(raw) => (typeof raw === 'string' ? raw : ''),
'',
);
// Columns shown in the trace-selection grid; backs the DataGrid's controlled
// `columns`. An explicit array, else null = "use the schema's defaultVisible".
class TraceColumnsState extends SingleFieldStorage<readonly string[] | null> {
constructor() {
super('bigtraceTraceColumns', 'chosen', parseNullableStringArray, null);
}
// null → defaultVisible columns; else the selection ∩ schema (dropping removed
// columns). `link` hoisted first.
effective(schema: ReadonlyArray<SchemaColumn>): string[] {
const chosen = this.get();
if (chosen === null) {
return linkNameFirst(
schema.filter((c) => c.defaultVisible).map((c) => c.name),
);
}
const known = new Set(schema.map((c) => c.name));
return linkNameFirst(chosen.filter((c) => known.has(c)));
}
}
export const traceColumnsState = new TraceColumnsState();
// Resolver for traceQueryColumnsState against the live schema (link first):
// null → defaultVisible (so an untouched picker shows defaults); [...] → these ∩
// schema; [] → nothing.
export function effectiveQueryColumns(
chosen: readonly string[] | null,
schema: ReadonlyArray<SchemaColumn>,
): string[] {
if (chosen === null) {
return linkNameFirst(
schema.filter((c) => c.defaultVisible).map((c) => c.name),
);
}
const known = new Set(schema.map((c) => c.name));
return linkNameFirst(chosen.filter((c) => known.has(c)));
}
// Metadata columns attached to result rows (`trace_metadata_columns` on
// /execute_*) — distinct from traceColumnsState (the trace-list grid's shown
// columns). null = defaultVisible; [] = nothing; [...] = these. [] must NOT
// collapse to null, else "nothing" is unexpressible.
export const traceQueryColumnsState = new SingleFieldStorage<
readonly string[] | null
>(
'bigtraceTraceQueryColumns',
'chosen',
(raw) =>
Array.isArray(raw)
? raw.filter((v): v is string => typeof v === 'string')
: null,
null,
);