xref: /aosp_15_r20/external/cronet/base/trace_event/interned_args_helper.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_
6 #define BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_
7 
8 #include <optional>
9 #include <string>
10 
11 #include "base/base_export.h"
12 #include "base/containers/span.h"
13 #include "base/hash/hash.h"
14 #include "base/location.h"
15 #include "base/profiler/module_cache.h"
16 #include "base/trace_event/trace_event.h"
17 #include "build/build_config.h"
18 #include "third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h"
19 #include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h"
20 
21 namespace base {
22 namespace trace_event {
23 
24 // TrackEventInternedDataIndex expects the same data structure to be used for
25 // all interned fields with the same field number. We can't use base::Location
26 // for log event's location since base::Location uses program counter based
27 // location.
28 struct BASE_EXPORT TraceSourceLocation {
29   const char* function_name = nullptr;
30   const char* file_name = nullptr;
31   int line_number = 0;
32 
33   TraceSourceLocation() = default;
TraceSourceLocationTraceSourceLocation34   TraceSourceLocation(const char* function_name,
35                       const char* file_name,
36                       int line_number)
37       : function_name(function_name),
38         file_name(file_name),
39         line_number(line_number) {}
40   // Construct a new source location from an existing base::Location, the only
41   // attributes that are read are |function_name|, |file_name| and
42   // |line_number|.
TraceSourceLocationTraceSourceLocation43   explicit TraceSourceLocation(const base::Location& location)
44       : function_name(location.function_name()),
45         file_name(location.file_name()),
46         line_number(location.line_number()) {}
47 
48   bool operator==(const TraceSourceLocation& other) const {
49     return file_name == other.file_name &&
50            function_name == other.function_name &&
51            line_number == other.line_number;
52   }
53 };
54 
55 // Data structure for constructing an interned
56 // perfetto.protos.UnsymbolizedSourceLocation proto message.
57 struct BASE_EXPORT UnsymbolizedSourceLocation {
58   uint64_t mapping_id = 0;
59   uint64_t rel_pc = 0;
60 
61   UnsymbolizedSourceLocation() = default;
UnsymbolizedSourceLocationUnsymbolizedSourceLocation62   UnsymbolizedSourceLocation(uint64_t mapping_id, uint64_t rel_pc)
63       : mapping_id(mapping_id), rel_pc(rel_pc) {}
64 
65   bool operator==(const UnsymbolizedSourceLocation& other) const {
66     return mapping_id == other.mapping_id && rel_pc == other.rel_pc;
67   }
68 };
69 
70 }  // namespace trace_event
71 }  // namespace base
72 
73 namespace std {
74 
75 template <>
76 struct hash<base::trace_event::TraceSourceLocation> {
77   std::size_t operator()(
78       const base::trace_event::TraceSourceLocation& loc) const {
79     return base::HashInts(
80         base::HashInts(reinterpret_cast<uintptr_t>(loc.file_name),
81                        reinterpret_cast<uintptr_t>(loc.function_name)),
82         static_cast<size_t>(loc.line_number));
83   }
84 };
85 
86 template <>
87 struct hash<base::trace_event::UnsymbolizedSourceLocation> {
88   std::size_t operator()(
89       const base::trace_event::UnsymbolizedSourceLocation& module) const {
90     return base::HashInts(module.mapping_id, module.rel_pc);
91   }
92 };
93 
94 }  // namespace std
95 
96 namespace base {
97 namespace trace_event {
98 
99 struct BASE_EXPORT InternedSourceLocation
100     : public perfetto::TrackEventInternedDataIndex<
101           InternedSourceLocation,
102           perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
103           TraceSourceLocation> {
104   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
105                   size_t iid,
106                   const TraceSourceLocation& location);
107   using perfetto::TrackEventInternedDataIndex<
108       InternedSourceLocation,
109       perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
110       TraceSourceLocation>::Get;
111   static size_t Get(perfetto::EventContext* ctx, const Location& location) {
112     return perfetto::TrackEventInternedDataIndex<
113         InternedSourceLocation,
114         perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
115         TraceSourceLocation>::Get(ctx, TraceSourceLocation(location));
116   }
117 };
118 
119 struct BASE_EXPORT InternedLogMessage
120     : public perfetto::TrackEventInternedDataIndex<
121           InternedLogMessage,
122           perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
123           std::string> {
124   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
125                   size_t iid,
126                   const std::string& log_message);
127 };
128 
129 struct BASE_EXPORT InternedBuildId
130     : public perfetto::TrackEventInternedDataIndex<
131           InternedBuildId,
132           perfetto::protos::pbzero::InternedData::kBuildIdsFieldNumber,
133           std::string> {
134   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
135                   size_t iid,
136                   const std::string& build_id);
137 };
138 
139 struct BASE_EXPORT InternedMappingPath
140     : public perfetto::TrackEventInternedDataIndex<
141           InternedMappingPath,
142           perfetto::protos::pbzero::InternedData::kMappingPathsFieldNumber,
143           std::string> {
144   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
145                   size_t iid,
146                   const std::string& mapping_path);
147 };
148 
149 struct BASE_EXPORT InternedMapping
150     : public perfetto::TrackEventInternedDataIndex<
151           InternedMapping,
152           perfetto::protos::pbzero::InternedData::kMappingsFieldNumber,
153           const base::ModuleCache::Module*> {
154   // We need a custom implementation here to plumb EventContext to Add.
155   static size_t Get(perfetto::EventContext* ctx,
156                     const base::ModuleCache::Module* module);
157   static void Add(perfetto::EventContext* ctx,
158                   size_t iid,
159                   const base::ModuleCache::Module* module);
160 };
161 
162 // Interns an unsymbolized source code location + all it's "dependencies", i.e.
163 // module, strings used in the module definition, and so on.
164 struct BASE_EXPORT InternedUnsymbolizedSourceLocation
165     : public perfetto::TrackEventInternedDataIndex<
166           InternedUnsymbolizedSourceLocation,
167           perfetto::protos::pbzero::InternedData::
168               kUnsymbolizedSourceLocationsFieldNumber,
169           uintptr_t> {
170   // We need a custom Get implementation to use ModuleCache, and to return
171   // a nullopt if a module for the given address cannot be found.
172   static std::optional<size_t> Get(perfetto::EventContext* ctx,
173                                    uintptr_t address);
174   static void Add(perfetto::protos::pbzero::InternedData* interned_data,
175                   size_t iid,
176                   const UnsymbolizedSourceLocation& location);
177 
178 // We use thread local storage for the module cache if we are using the
179 // client library since it is more optimal. It was not worth it to write
180 // optimal caching for not client library users since everyone will convert.
181 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
182  private:
183   // This implies that a module cache lifetime = incremental state.
184   // We don't want unlimited lifetime because it keeps modules pinned in
185   // memory on some platforms (Windows).
186   // TODO(b/237055179): Consider tying module cache to DataSource instead so
187   // that the cache is not unnecessarily cleared on incremental state change.
188   base::ModuleCache module_cache_;
189 #endif
190 };
191 
192 }  // namespace trace_event
193 }  // namespace base
194 
195 #endif  // BASE_TRACE_EVENT_INTERNED_ARGS_HELPER_H_
196