blob: 985d090afb2a3e41a8f11f7a68ae56b779993320 [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 {uuidv4} from '../base/uuid';
import {NUM} from '../trace_processor/query_result';
import {VisualizedArgsTrack} from './visualized_args_track';
import {TrackNode} from '../public/workspace';
import {Trace} from '../public/trace';
import {SLICE_TRACK_KIND} from '../public/track_kinds';
const VISUALIZED_ARGS_SLICE_TRACK_URI_PREFIX = 'perfetto.VisualizedArgs';
export async function addVisualizedArgTracks(trace: Trace, argName: string) {
const escapedArgName = argName.replace(/[^a-zA-Z]/g, '_');
const tableName = `__arg_visualisation_helper_${escapedArgName}_slice`;
const result = await trace.engine.query(`
drop table if exists ${tableName};
create table ${tableName} as
with slice_with_arg as (
select
slice.id,
slice.track_id,
slice.ts,
slice.dur,
slice.thread_dur,
NULL as cat,
args.display_value as name
from slice
join args using (arg_set_id)
where args.key='${argName}'
)
select
*,
(select count()
from ancestor_slice(s1.id) s2
join slice_with_arg s3 on s2.id=s3.id
) as depth
from slice_with_arg s1
order by id;
select
track_id as trackId,
max(depth) as maxDepth
from ${tableName}
group by track_id;
`);
const addedTracks: TrackNode[] = [];
const it = result.iter({trackId: NUM, maxDepth: NUM});
for (; it.valid(); it.next()) {
const trackId = it.trackId;
const maxDepth = it.maxDepth;
const uri = `${VISUALIZED_ARGS_SLICE_TRACK_URI_PREFIX}#${uuidv4()}`;
trace.tracks.registerTrack({
uri,
title: argName,
chips: ['arg'],
track: new VisualizedArgsTrack({
trace,
uri,
trackId,
maxDepth,
argName,
onClose: () => {
// Remove all added for this argument
addedTracks.forEach((t) => t.parent?.removeChild(t));
},
}),
});
// Find the thread slice track that corresponds with this trackID and insert
// this track before it.
const threadSliceTrack = trace.workspace.flatTracks.find((trackNode) => {
if (!trackNode.uri) return false;
const trackDescriptor = trace.tracks.getTrack(trackNode.uri);
return (
trackDescriptor &&
trackDescriptor.tags?.kind === SLICE_TRACK_KIND &&
trackDescriptor.tags?.trackIds?.includes(trackId)
);
});
const parentGroup = threadSliceTrack?.parent;
if (parentGroup) {
const newTrack = new TrackNode({uri, title: argName});
parentGroup.addChildBefore(newTrack, threadSliceTrack);
addedTracks.push(newTrack);
}
}
}