ui: Stdlib support prototype
Plumbing of stdlib into the UI. Parses the stdlib json and deserialises it into typescript objects. This is a noop.
This is the first step into being able to open any stdlib table in the UI, viewing the list of packages/modules/tables and seeing the column description.
Change-Id: I52a8b3b4824ecf0b5392216aff8ef34d482ce209
diff --git a/ui/src/core/default_plugins.ts b/ui/src/core/default_plugins.ts
index 4791e8e..caba9f0 100644
--- a/ui/src/core/default_plugins.ts
+++ b/ui/src/core/default_plugins.ts
@@ -60,6 +60,7 @@
'dev.perfetto.RestorePinnedTrack',
'dev.perfetto.Sched',
'dev.perfetto.Screenshots',
+ 'dev.perfetto.SqlModules',
'dev.perfetto.Thread',
'dev.perfetto.ThreadState',
'dev.perfetto.TimelineSync',
diff --git a/ui/src/plugins/dev.perfetto.SqlModules/index.ts b/ui/src/plugins/dev.perfetto.SqlModules/index.ts
new file mode 100644
index 0000000..f2fde8d
--- /dev/null
+++ b/ui/src/plugins/dev.perfetto.SqlModules/index.ts
@@ -0,0 +1,35 @@
+// 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 {assetSrc} from '../../base/assets';
+import {assertExists} from '../../base/logging';
+import {PerfettoPlugin} from '../../public/plugin';
+import {SqlModules} from './sql_modules';
+import {SQL_MODULES_DOCS_SCHEMA, SqlModulesImpl} from './sql_modules_impl';
+
+export default class implements PerfettoPlugin {
+ static readonly id = 'dev.perfetto.SqlModules';
+ private sqlModules?: SqlModules;
+
+ async onTraceLoad() {
+ const resp = await fetch(assetSrc('stdlib_docs.json'));
+ const json = await resp.json();
+ const docs = SQL_MODULES_DOCS_SCHEMA.parse(json);
+ this.sqlModules = new SqlModulesImpl(docs);
+ }
+
+ getSqlModules() {
+ return assertExists(this.sqlModules);
+ }
+}
diff --git a/ui/src/plugins/dev.perfetto.SqlModules/sql_modules.ts b/ui/src/plugins/dev.perfetto.SqlModules/sql_modules.ts
new file mode 100644
index 0000000..9f0503a
--- /dev/null
+++ b/ui/src/plugins/dev.perfetto.SqlModules/sql_modules.ts
@@ -0,0 +1,90 @@
+// 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.
+
+// Handles the access to all of the Perfetto SQL modules accessible to Trace
+// Processor.
+export interface SqlModules {
+ // Returns names of all tables/views between all loaded Perfetto SQL modules.
+ listTables(): string[];
+
+ // Returns Perfetto SQL table/view if it was loaded in one of the Perfetto
+ // SQL module.
+ getTable(tableName: string): SqlTable | undefined;
+}
+
+// Handles the access to a specific Perfetto SQL Package. Package consists of
+// Perfetto SQL modules.
+export interface SqlPackage {
+ readonly name: string;
+ readonly modules: SqlModule[];
+ listTables(): string[];
+ getTable(tableName: string): SqlTable | undefined;
+}
+
+// Handles the access to a specific Perfetto SQL module.
+export interface SqlModule {
+ readonly includeKey: string;
+ readonly dataObjects: SqlTable[];
+ readonly functions: SqlFunction[];
+ readonly tableFunctions: SqlTableFunction[];
+ readonly macros: SqlMacro[];
+}
+
+// The definition of Perfetto SQL table/view.
+export interface SqlTable {
+ readonly name: string;
+ readonly description: string;
+ readonly type: string;
+ readonly columns: SqlColumn[];
+}
+
+// The definition of Perfetto SQL function.
+export interface SqlFunction {
+ readonly name: string;
+ readonly description: string;
+ readonly args: SqlArgument[];
+ readonly returnType: string;
+ readonly returnDesc: string;
+}
+
+// The definition of Perfetto SQL table function.
+export interface SqlTableFunction {
+ readonly name: string;
+ readonly description: string;
+ readonly args: SqlArgument[];
+ readonly returnCols: SqlColumn[];
+}
+
+// The definition of Perfetto SQL macro.
+export interface SqlMacro {
+ readonly name: string;
+ readonly description: string;
+ readonly args: SqlArgument[];
+ readonly returnType: string;
+}
+
+// The definition of Perfetto SQL column.
+export interface SqlColumn {
+ readonly name: string;
+ readonly description: string;
+ readonly type: string;
+}
+
+// The definition of Perfetto SQL argument. Can be used for functions, table
+// functions or macros.
+export interface SqlArgument {
+ readonly name: string;
+ readonly description: string;
+ readonly type: string;
+}
diff --git a/ui/src/plugins/dev.perfetto.SqlModules/sql_modules_impl.ts b/ui/src/plugins/dev.perfetto.SqlModules/sql_modules_impl.ts
new file mode 100644
index 0000000..ee6fe79
--- /dev/null
+++ b/ui/src/plugins/dev.perfetto.SqlModules/sql_modules_impl.ts
@@ -0,0 +1,254 @@
+// 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 {z} from 'zod';
+import {
+ SqlModules,
+ SqlColumn,
+ SqlFunction,
+ SqlArgument,
+ SqlMacro,
+ SqlModule,
+ SqlPackage,
+ SqlTable,
+ SqlTableFunction,
+} from './sql_modules';
+
+export class SqlModulesImpl implements SqlModules {
+ readonly packages: SqlPackage[];
+
+ constructor(docs: SqlModulesDocsSchema) {
+ this.packages = docs.map((json) => new StdlibPackageImpl(json));
+ }
+
+ listTables(): string[] {
+ const tables: string[] = [];
+ for (const stdlibPackage of this.packages) {
+ tables.concat(stdlibPackage.listTables());
+ }
+ return tables;
+ }
+
+ getTable(tableName: string): SqlTable | undefined {
+ for (const stdlibPackage of this.packages) {
+ const maybeTable = stdlibPackage.getTable(tableName);
+ if (maybeTable) {
+ return maybeTable;
+ }
+ }
+ return undefined;
+ }
+}
+
+export class StdlibPackageImpl implements SqlPackage {
+ readonly name: string;
+ readonly modules: SqlModule[];
+
+ constructor(docs: DocsPackageSchemaType) {
+ this.name = docs.name;
+ this.modules = [];
+ for (const moduleJson of docs.modules) {
+ this.modules.push(new StdlibModuleImpl(moduleJson));
+ }
+ }
+
+ getTable(tableName: string): SqlTable | undefined {
+ for (const module of this.modules) {
+ for (const dataObj of module.dataObjects) {
+ if (dataObj.name == tableName) {
+ return dataObj;
+ }
+ }
+ }
+ return undefined;
+ }
+
+ listTables(): string[] {
+ return this.modules.flatMap((module) =>
+ module.dataObjects.map((dataObj) => dataObj.name),
+ );
+ }
+}
+
+export class StdlibModuleImpl implements SqlModule {
+ readonly includeKey: string;
+ readonly dataObjects: SqlTable[];
+ readonly functions: SqlFunction[];
+ readonly tableFunctions: SqlTableFunction[];
+ readonly macros: SqlMacro[];
+
+ constructor(docs: DocsModuleSchemaType) {
+ this.includeKey = docs.module_name;
+ this.dataObjects = docs.data_objects.map(
+ (json) => new StdlibDataObjectImpl(json),
+ );
+ this.functions = docs.functions.map((json) => new StdlibFunctionImpl(json));
+ this.tableFunctions = docs.table_functions.map(
+ (json) => new StdlibTableFunctionImpl(json),
+ );
+ this.macros = docs.macros.map((json) => new StdlibMacroImpl(json));
+ }
+}
+
+class StdlibMacroImpl implements SqlMacro {
+ readonly name: string;
+ readonly summaryDesc: string;
+ readonly description: string;
+ readonly args: SqlArgument[];
+ readonly returnType: string;
+
+ constructor(docs: DocsMacroSchemaType) {
+ this.name = docs.name;
+ this.summaryDesc = docs.summary_desc;
+ this.description = docs.desc;
+ this.returnType = docs.return_type;
+ this.args = [];
+ this.args = docs.args.map((json) => new StdlibFunctionArgImpl(json));
+ }
+}
+
+class StdlibTableFunctionImpl implements SqlTableFunction {
+ readonly name: string;
+ readonly summaryDesc: string;
+ readonly description: string;
+ readonly args: SqlArgument[];
+ readonly returnCols: SqlColumn[];
+
+ constructor(docs: DocsTableFunctionSchemaType) {
+ this.name = docs.name;
+ this.summaryDesc = docs.summary_desc;
+ this.description = docs.desc;
+ this.args = docs.args.map((json) => new StdlibFunctionArgImpl(json));
+ this.returnCols = docs.cols.map((json) => new StdlibColumnImpl(json));
+ }
+}
+
+class StdlibFunctionImpl implements SqlFunction {
+ readonly name: string;
+ readonly summaryDesc: string;
+ readonly description: string;
+ readonly args: SqlArgument[];
+ readonly returnType: string;
+ readonly returnDesc: string;
+
+ constructor(docs: DocsFunctionSchemaType) {
+ this.name = docs.name;
+ this.summaryDesc = docs.summary_desc;
+ this.description = docs.desc;
+ this.returnType = docs.return_type;
+ this.returnDesc = docs.return_desc;
+ this.args = docs.args.map((json) => new StdlibFunctionArgImpl(json));
+ }
+}
+
+class StdlibDataObjectImpl implements SqlTable {
+ name: string;
+ description: string;
+ type: string;
+ columns: SqlColumn[];
+
+ constructor(docs: DocsDataObjectSchemaType) {
+ this.name = docs.name;
+ this.description = docs.desc;
+ this.type = docs.type;
+ this.columns = docs.cols.map((json) => new StdlibColumnImpl(json));
+ }
+}
+
+class StdlibColumnImpl implements SqlColumn {
+ name: string;
+ type: string;
+ description: string;
+
+ constructor(docs: DocsArgOrColSchemaType) {
+ this.type = docs.type;
+ this.description = docs.desc;
+ this.name = docs.name;
+ }
+}
+
+class StdlibFunctionArgImpl implements SqlArgument {
+ name: string;
+ description: string;
+ type: string;
+
+ constructor(docs: DocsArgOrColSchemaType) {
+ this.type = docs.type;
+ this.description = docs.desc;
+ this.name = docs.name;
+ }
+}
+
+const ARG_OR_COL_SCHEMA = z.object({
+ name: z.string(),
+ type: z.string(),
+ desc: z.string(),
+});
+type DocsArgOrColSchemaType = z.infer<typeof ARG_OR_COL_SCHEMA>;
+
+const DATA_OBJECT_SCHEMA = z.object({
+ name: z.string(),
+ desc: z.string(),
+ summary_desc: z.string(),
+ type: z.string(),
+ cols: z.array(ARG_OR_COL_SCHEMA),
+});
+type DocsDataObjectSchemaType = z.infer<typeof DATA_OBJECT_SCHEMA>;
+
+const FUNCTION_SCHEMA = z.object({
+ name: z.string(),
+ desc: z.string(),
+ summary_desc: z.string(),
+ args: z.array(ARG_OR_COL_SCHEMA),
+ return_type: z.string(),
+ return_desc: z.string(),
+});
+type DocsFunctionSchemaType = z.infer<typeof FUNCTION_SCHEMA>;
+
+const TABLE_FUNCTION_SCHEMA = z.object({
+ name: z.string(),
+ desc: z.string(),
+ summary_desc: z.string(),
+ args: z.array(ARG_OR_COL_SCHEMA),
+ cols: z.array(ARG_OR_COL_SCHEMA),
+});
+type DocsTableFunctionSchemaType = z.infer<typeof TABLE_FUNCTION_SCHEMA>;
+
+const MACRO_SCHEMA = z.object({
+ name: z.string(),
+ desc: z.string(),
+ summary_desc: z.string(),
+ return_desc: z.string(),
+ return_type: z.string(),
+ args: z.array(ARG_OR_COL_SCHEMA),
+});
+type DocsMacroSchemaType = z.infer<typeof MACRO_SCHEMA>;
+
+const MODULE_SCHEMA = z.object({
+ module_name: z.string(),
+ data_objects: z.array(DATA_OBJECT_SCHEMA),
+ functions: z.array(FUNCTION_SCHEMA),
+ table_functions: z.array(TABLE_FUNCTION_SCHEMA),
+ macros: z.array(MACRO_SCHEMA),
+});
+type DocsModuleSchemaType = z.infer<typeof MODULE_SCHEMA>;
+
+const PACKAGE_SCHEMA = z.object({
+ name: z.string(),
+ modules: z.array(MODULE_SCHEMA),
+});
+type DocsPackageSchemaType = z.infer<typeof PACKAGE_SCHEMA>;
+
+export const SQL_MODULES_DOCS_SCHEMA = z.array(PACKAGE_SCHEMA);
+export type SqlModulesDocsSchema = z.infer<typeof SQL_MODULES_DOCS_SCHEMA>;
diff --git a/ui/src/public/lib/stdlib_docs.ts b/ui/src/public/lib/stdlib_docs.ts
deleted file mode 100644
index fcdcf18..0000000
--- a/ui/src/public/lib/stdlib_docs.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 {assetSrc} from '../../base/assets';
-
-// Fetch the stdlib docs
-export async function getStdlibDocs(): Promise<string> {
- const resp = await fetch(assetSrc('stdlib_docs.json'));
- const json = await resp.json();
- return JSON.parse(json);
-}