• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2020 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 {Duration} from '../../base/time';
16import {ColumnDef} from '../../common/aggregation_data';
17import {Area, Sorting} from '../../common/state';
18import {globals} from '../../frontend/globals';
19import {Engine} from '../../trace_processor/engine';
20import {COUNTER_TRACK_KIND} from '../../core_plugins/counter';
21
22import {AggregationController} from './aggregation_controller';
23
24export class CounterAggregationController extends AggregationController {
25  async createAggregateView(engine: Engine, area: Area) {
26    await engine.query(`drop view if exists ${this.kind};`);
27
28    const trackIds: (string | number)[] = [];
29    for (const trackKey of area.tracks) {
30      const track = globals.state.tracks[trackKey];
31      if (track?.uri) {
32        const trackInfo = globals.trackManager.resolveTrackInfo(track.uri);
33        if (trackInfo?.kind === COUNTER_TRACK_KIND) {
34          trackInfo.trackIds && trackIds.push(...trackInfo.trackIds);
35        }
36      }
37    }
38    if (trackIds.length === 0) return false;
39    const duration = area.end - area.start;
40    const durationSec = Duration.toSeconds(duration);
41
42    // TODO(lalitm): Rewrite this query in a way that is both simpler and faster
43    let query;
44    if (trackIds.length === 1) {
45      // Optimized query for the special case where there is only 1 track id.
46      query = `CREATE VIEW ${this.kind} AS
47      WITH aggregated AS (
48        SELECT
49          COUNT(1) AS count,
50          ROUND(SUM(
51            (MIN(ts + dur, ${area.end}) - MAX(ts,${area.start}))*value)/${duration},
52            2
53          ) AS avg_value,
54          (SELECT value FROM experimental_counter_dur WHERE track_id = ${trackIds[0]}
55            AND ts + dur >= ${area.start}
56            AND ts <= ${area.end} ORDER BY ts DESC LIMIT 1)
57            AS last_value,
58          (SELECT value FROM experimental_counter_dur WHERE track_id = ${trackIds[0]}
59            AND ts + dur >= ${area.start}
60            AND ts <= ${area.end} ORDER BY ts ASC LIMIT 1)
61            AS first_value,
62          MIN(value) AS min_value,
63          MAX(value) AS max_value
64        FROM experimental_counter_dur
65          WHERE track_id = ${trackIds[0]}
66          AND ts + dur >= ${area.start}
67          AND ts <= ${area.end})
68      SELECT
69        (SELECT name FROM counter_track WHERE id = ${trackIds[0]}) AS name,
70        *,
71        MAX(last_value) - MIN(first_value) AS delta_value,
72        ROUND((MAX(last_value) - MIN(first_value))/${durationSec}, 2) AS rate
73      FROM aggregated`;
74    } else {
75      // Slower, but general purspose query that can aggregate multiple tracks
76      query = `CREATE VIEW ${this.kind} AS
77      WITH aggregated AS (
78        SELECT track_id,
79          COUNT(1) AS count,
80          ROUND(SUM(
81            (MIN(ts + dur, ${area.end}) - MAX(ts,${area.start}))*value)/${duration},
82            2
83          ) AS avg_value,
84          value_at_max_ts(-ts, value) AS first,
85          value_at_max_ts(ts, value) AS last,
86          MIN(value) AS min_value,
87          MAX(value) AS max_value
88        FROM experimental_counter_dur
89          WHERE track_id IN (${trackIds})
90          AND ts + dur >= ${area.start} AND
91          ts <= ${area.end}
92        GROUP BY track_id
93      )
94      SELECT
95        name,
96        count,
97        avg_value,
98        last AS last_value,
99        first AS first_value,
100        last - first AS delta_value,
101        ROUND((last - first)/${durationSec}, 2) AS rate,
102        min_value,
103        max_value
104      FROM aggregated JOIN counter_track ON
105        track_id = counter_track.id
106      GROUP BY track_id`;
107    }
108    await engine.query(query);
109    return true;
110  }
111
112  getColumnDefinitions(): ColumnDef[] {
113    return [
114      {
115        title: 'Name',
116        kind: 'STRING',
117        columnConstructor: Uint16Array,
118        columnId: 'name',
119      },
120      {
121        title: 'Delta value',
122        kind: 'NUMBER',
123        columnConstructor: Float64Array,
124        columnId: 'delta_value',
125      },
126      {
127        title: 'Rate /s',
128        kind: 'Number',
129        columnConstructor: Float64Array,
130        columnId: 'rate',
131      },
132      {
133        title: 'Weighted avg value',
134        kind: 'Number',
135        columnConstructor: Float64Array,
136        columnId: 'avg_value',
137      },
138      {
139        title: 'Count',
140        kind: 'Number',
141        columnConstructor: Float64Array,
142        columnId: 'count',
143        sum: true,
144      },
145      {
146        title: 'First value',
147        kind: 'NUMBER',
148        columnConstructor: Float64Array,
149        columnId: 'first_value',
150      },
151      {
152        title: 'Last value',
153        kind: 'NUMBER',
154        columnConstructor: Float64Array,
155        columnId: 'last_value',
156      },
157      {
158        title: 'Min value',
159        kind: 'NUMBER',
160        columnConstructor: Float64Array,
161        columnId: 'min_value',
162      },
163      {
164        title: 'Max value',
165        kind: 'NUMBER',
166        columnConstructor: Float64Array,
167        columnId: 'max_value',
168      },
169    ];
170  }
171
172  async getExtra() {}
173
174  getTabName() {
175    return 'Counters';
176  }
177
178  getDefaultSorting(): Sorting {
179    return {column: 'name', direction: 'DESC'};
180  }
181}
182