1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACKS_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACKS_H_
19
20 #include <array>
21 #include <cstddef>
22 #include <cstdint>
23 #include <string_view>
24 #include <tuple>
25
26 #include "perfetto/ext/base/hash.h"
27 #include "perfetto/ext/base/string_view.h"
28 #include "src/trace_processor/containers/string_pool.h"
29 #include "src/trace_processor/importers/common/tracks_internal.h"
30
31 namespace perfetto::trace_processor::tracks {
32
33 // This file contains the "public API" for creating track blueprints.
34 // See TrackTracker::InternTrack for usages of the functions in this file.
35
36 // Start of blueprint functions.
37
38 // Creates a blueprint for a slice track.
39 // See TrackTracker::InternTrack for usage of this function.
40 template <typename NB = NameBlueprintT::Auto, typename... D>
41 constexpr auto SliceBlueprint(const char classification[],
42 DimensionBlueprintsT<D...> dimensions = {},
43 NB name = NB{}) {
44 static_assert(sizeof...(D) < 8, "At most 8 dimensions are supported");
45 auto dims_array = std::apply(
46 [](auto&&... x) { return std::array<DimensionBlueprintBase, 8>{x...}; },
47 dimensions);
48 return BlueprintT<NB, UnitBlueprintT::Unknown, D...>{
49 {
50 "slice",
51 classification,
52 base::Hasher::CreatePartial(classification),
53 dims_array,
54 },
55 name,
56 UnitBlueprintT::Unknown{},
57 };
58 }
59
60 // Creates a blueprint for a counter track.
61 // See TrackTracker::InternTrack for usage on this function.
62 template <typename NB = NameBlueprintT::Auto,
63 typename UB = UnitBlueprintT::Unknown,
64 typename... D>
65 constexpr auto CounterBlueprint(const char classification[],
66 UB unit,
67 DimensionBlueprintsT<D...> dimensions = {},
68 NB name = NB{}) {
69 static_assert(sizeof...(D) < 8, "At most 8 dimensions are supported");
70 auto dims_array = std::apply(
71 [](auto&&... x) { return std::array<DimensionBlueprintBase, 8>{x...}; },
72 dimensions);
73 return BlueprintT<NB, UB, D...>{
74 {
75 "counter",
76 classification,
77 base::Hasher::CreatePartial(classification),
78 dims_array,
79 },
80 name,
81 unit,
82 };
83 }
84
85 // Wraps all the dimension blueprints before passing them to SliceBlueprint()
86 // or CounterBlueprint().
87 template <typename... DimensionBlueprint>
DimensionBlueprints(DimensionBlueprint...dimensions)88 constexpr auto DimensionBlueprints(DimensionBlueprint... dimensions) {
89 return DimensionBlueprintsT<DimensionBlueprint...>{dimensions...};
90 }
91
92 // Adds a unit32_t dimension with the given name.
UintDimensionBlueprint(const char name[])93 constexpr auto UintDimensionBlueprint(const char name[]) {
94 return DimensionBlueprintT<uint32_t>{{name, std::string_view(name) == "cpu"}};
95 }
96
97 // Adds a string dimension with the given name.
StringDimensionBlueprint(const char name[])98 constexpr auto StringDimensionBlueprint(const char name[]) {
99 return DimensionBlueprintT<base::StringView>{{name, false}};
100 }
101
102 // Adds a int64_t dimension with the given name.
LongDimensionBlueprint(const char name[])103 constexpr auto LongDimensionBlueprint(const char name[]) {
104 return DimensionBlueprintT<int64_t>{{name, false}};
105 }
106
107 // Indicates the name should be automatically determined by trace processor.
AutoNameBlueprint()108 constexpr auto AutoNameBlueprint() {
109 return NameBlueprintT::Auto{};
110 }
111
112 // Indicates the name of the track should be given by a static string. This
113 // should really only be used when the track has no dimensions as it's quite
114 // confusing in queries otherwise.
StaticNameBlueprint(const char name[])115 constexpr auto StaticNameBlueprint(const char name[]) {
116 return NameBlueprintT::Static{name};
117 }
118
119 // Indicates the name of the track is dynamic and will be provided at runtime to
120 // InternTrack.
DynamicNameBlueprint()121 constexpr auto DynamicNameBlueprint() {
122 return NameBlueprintT::Dynamic{};
123 }
124
125 // Indicates the name of the track is a function which accepts as input the
126 // dimensions of the track and returns a base::StackString containing the
127 // results of transforming the dimensions.
128 template <typename F>
FnNameBlueprint(F fn)129 constexpr auto FnNameBlueprint(F fn) {
130 return NameBlueprintT::Fn<F>{{}, fn};
131 }
132
133 // Indicates that the unit of this track is given by a static string.
StaticUnitBlueprint(const char unit[])134 constexpr auto StaticUnitBlueprint(const char unit[]) {
135 return UnitBlueprintT::Static{unit};
136 }
137
138 // Indicates the unit of this track is dynamic and will be provided at
139 // InternTrack time.
DynamicUnitBlueprint()140 constexpr auto DynamicUnitBlueprint() {
141 return UnitBlueprintT::Dynamic{};
142 }
143
144 // Indicates that the units of the counter are unknown. Should not be used, is
145 // only intended for counter tracks which predate the introduction of track
146 // blueprints.
UnknownUnitBlueprint()147 constexpr auto UnknownUnitBlueprint() {
148 return UnitBlueprintT::Unknown{};
149 }
150
151 // End of blueprint functions.
152
153 // Start of InternTrack helper functions.
154
155 // Wraps all the dimensions for a track before passing them to InternTrack.
156 template <typename... D>
Dimensions(D...dimensions)157 constexpr auto Dimensions(D... dimensions) {
158 return DimensionsT<D...>{dimensions...};
159 }
160
161 // Indicates that the name of the track was provided in the blueprint.
BlueprintName()162 constexpr nullptr_t BlueprintName() {
163 return nullptr;
164 }
165
166 // Indicates that the name of the track should be `id`. Only valid if
167 // `DynamicNameBlueprint()` was passed when creating the blueprint.
DynamicName(StringPool::Id id)168 constexpr StringPool::Id DynamicName(StringPool::Id id) {
169 return id;
170 }
171
172 // Indicates that the unit of the track was provided in the blueprint.
BlueprintUnit()173 constexpr nullptr_t BlueprintUnit() {
174 return nullptr;
175 }
176
177 // Indicates that the unit of the track should be `id`. Only valid if
178 // `DynamicUnitBlueprint()` was passed when creating the blueprint.
DynamicUnit(StringPool::Id id)179 constexpr StringPool::Id DynamicUnit(StringPool::Id id) {
180 return id;
181 }
182
183 // End of InternTrack helper functions.
184
185 } // namespace perfetto::trace_processor::tracks
186
187 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACKS_H_
188