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. 14 15import m from 'mithril'; 16import {time} from '../../base/time'; 17import { 18 metricsFromTableOrSubquery, 19 QueryFlamegraph, 20} from '../../components/query_flamegraph'; 21import {Timestamp} from '../../components/widgets/timestamp'; 22import { 23 TrackEventDetailsPanel, 24 TrackEventDetailsPanelSerializeArgs, 25} from '../../public/details_panel'; 26import {DetailsShell} from '../../widgets/details_shell'; 27import {Trace} from '../../public/trace'; 28import { 29 Flamegraph, 30 FLAMEGRAPH_STATE_SCHEMA, 31 FlamegraphState, 32} from '../../widgets/flamegraph'; 33 34export class CpuProfileSampleFlamegraphDetailsPanel 35 implements TrackEventDetailsPanel 36{ 37 private readonly flamegraph: QueryFlamegraph; 38 readonly serialization: TrackEventDetailsPanelSerializeArgs<FlamegraphState>; 39 40 constructor( 41 trace: Trace, 42 private ts: time, 43 utid: number, 44 ) { 45 const metrics = metricsFromTableOrSubquery( 46 ` 47 ( 48 select 49 id, 50 parent_id as parentId, 51 name, 52 mapping_name, 53 source_file, 54 cast(line_number AS text) as line_number, 55 self_count 56 from _callstacks_for_callsites!(( 57 select p.callsite_id 58 from cpu_profile_stack_sample p 59 where p.ts = ${ts} and p.utid = ${utid} 60 )) 61 ) 62 `, 63 [ 64 { 65 name: 'CPU Profile Samples', 66 unit: '', 67 columnName: 'self_count', 68 }, 69 ], 70 'include perfetto module callstacks.stack_profile', 71 [{name: 'mapping_name', displayName: 'Mapping'}], 72 [ 73 { 74 name: 'source_file', 75 displayName: 'Source File', 76 mergeAggregation: 'ONE_OR_NULL', 77 }, 78 { 79 name: 'line_number', 80 displayName: 'Line Number', 81 mergeAggregation: 'ONE_OR_NULL', 82 }, 83 ], 84 ); 85 this.serialization = { 86 schema: FLAMEGRAPH_STATE_SCHEMA, 87 state: Flamegraph.createDefaultState(metrics), 88 }; 89 this.flamegraph = new QueryFlamegraph(trace, metrics, this.serialization); 90 } 91 92 render() { 93 return m( 94 '.flamegraph-profile', 95 m( 96 DetailsShell, 97 { 98 fillParent: true, 99 title: m('.title', 'CPU Profile Samples'), 100 description: [], 101 buttons: [m('div.time', `Timestamp: `, m(Timestamp, {ts: this.ts}))], 102 }, 103 this.flamegraph.render(), 104 ), 105 ); 106 } 107} 108