xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/common/event_tracker.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2018 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 #include "src/trace_processor/importers/common/event_tracker.h"
18 
19 #include <cinttypes>
20 #include <cstdint>
21 #include <optional>
22 
23 #include "perfetto/base/compiler.h"
24 #include "perfetto/base/logging.h"
25 #include "src/trace_processor/importers/common/args_tracker.h"
26 #include "src/trace_processor/importers/common/track_tracker.h"
27 #include "src/trace_processor/importers/common/tracks.h"
28 #include "src/trace_processor/importers/common/tracks_common.h"
29 #include "src/trace_processor/storage/stats.h"
30 #include "src/trace_processor/storage/trace_storage.h"
31 #include "src/trace_processor/types/trace_processor_context.h"
32 
33 namespace perfetto::trace_processor {
34 
EventTracker(TraceProcessorContext * context)35 EventTracker::EventTracker(TraceProcessorContext* context)
36     : context_(context) {}
37 
38 EventTracker::~EventTracker() = default;
39 
PushProcessCounterForThread(ProcessCounterForThread pcounter,int64_t timestamp,double value,UniqueTid utid)40 void EventTracker::PushProcessCounterForThread(ProcessCounterForThread pcounter,
41                                                int64_t timestamp,
42                                                double value,
43                                                UniqueTid utid) {
44   const auto& counter = context_->storage->counter_table();
45   auto opt_id = PushCounter(timestamp, value, kInvalidTrackId);
46   if (opt_id) {
47     PendingUpidResolutionCounter pending;
48     pending.row = counter.FindById(*opt_id)->ToRowNumber().row_number();
49     pending.utid = utid;
50     pending.counter = pcounter;
51     pending_upid_resolution_counter_.emplace_back(pending);
52   }
53 }
54 
PushCounter(int64_t timestamp,double value,TrackId track_id)55 std::optional<CounterId> EventTracker::PushCounter(int64_t timestamp,
56                                                    double value,
57                                                    TrackId track_id) {
58   if (timestamp < max_timestamp_) {
59     PERFETTO_DLOG(
60         "counter event (ts: %" PRId64 ") out of order by %.4f ms, skipping",
61         timestamp, static_cast<double>(max_timestamp_ - timestamp) / 1e6);
62     context_->storage->IncrementStats(stats::counter_events_out_of_order);
63     return std::nullopt;
64   }
65   max_timestamp_ = timestamp;
66 
67   auto* counter_values = context_->storage->mutable_counter_table();
68   return counter_values->Insert({timestamp, track_id, value, {}}).id;
69 }
70 
PushCounter(int64_t timestamp,double value,TrackId track_id,const SetArgsCallback & args_callback)71 std::optional<CounterId> EventTracker::PushCounter(
72     int64_t timestamp,
73     double value,
74     TrackId track_id,
75     const SetArgsCallback& args_callback) {
76   auto maybe_counter_id = PushCounter(timestamp, value, track_id);
77   if (maybe_counter_id) {
78     auto inserter = context_->args_tracker->AddArgsTo(*maybe_counter_id);
79     args_callback(&inserter);
80   }
81   return maybe_counter_id;
82 }
83 
FlushPendingEvents()84 void EventTracker::FlushPendingEvents() {
85   const auto& thread_table = context_->storage->thread_table();
86   for (const auto& pending_counter : pending_upid_resolution_counter_) {
87     UniqueTid utid = pending_counter.utid;
88     std::optional<UniquePid> upid = thread_table[utid].upid();
89 
90     // If we still don't know which process this thread belongs to, fall back
91     // onto creating a thread counter track. It's too late to drop data
92     // because the counter values have already been inserted.
93     TrackId track_id;
94     switch (pending_counter.counter.index()) {
95       case base::variant_index<ProcessCounterForThread, OomScoreAdj>():
96         if (upid.has_value()) {
97           track_id = context_->track_tracker->InternTrack(
98               tracks::kOomScoreAdjBlueprint, tracks::Dimensions(*upid));
99         } else {
100           track_id = context_->track_tracker->InternTrack(
101               tracks::kOomScoreAdjThreadFallbackBlueprint,
102               tracks::Dimensions(utid));
103         }
104         break;
105       case base::variant_index<ProcessCounterForThread, MmEvent>(): {
106         const auto& mm_event = std::get<MmEvent>(pending_counter.counter);
107         if (upid.has_value()) {
108           track_id = context_->track_tracker->InternTrack(
109               tracks::kMmEventBlueprint,
110               tracks::Dimensions(*upid, mm_event.type, mm_event.metric));
111         } else {
112           track_id = context_->track_tracker->InternTrack(
113               tracks::kMmEventThreadFallbackBlueprint,
114               tracks::Dimensions(utid, mm_event.type, mm_event.metric));
115         }
116         break;
117       }
118       case base::variant_index<ProcessCounterForThread, RssStat>(): {
119         const auto& rss_stat = std::get<RssStat>(pending_counter.counter);
120         if (upid.has_value()) {
121           track_id = context_->track_tracker->InternTrack(
122               tracks::kProcessMemoryBlueprint,
123               tracks::Dimensions(*upid, rss_stat.process_memory_key));
124         } else {
125           track_id = context_->track_tracker->InternTrack(
126               tracks::kProcessMemoryThreadFallbackBlueprint,
127               tracks::Dimensions(utid, rss_stat.process_memory_key));
128         }
129         break;
130       }
131       case base::variant_index<ProcessCounterForThread, JsonCounter>(): {
132         const auto& json = std::get<JsonCounter>(pending_counter.counter);
133         if (upid.has_value()) {
134           track_id = context_->track_tracker->InternTrack(
135               tracks::kJsonCounterBlueprint,
136               tracks::Dimensions(
137                   *upid, context_->storage->GetString(json.counter_name_id)),
138               tracks::DynamicName(json.counter_name_id));
139         } else {
140           track_id = context_->track_tracker->InternTrack(
141               tracks::kJsonCounterThreadFallbackBlueprint,
142               tracks::Dimensions(
143                   utid, context_->storage->GetString(json.counter_name_id)),
144               tracks::DynamicName(json.counter_name_id));
145         }
146         break;
147       }
148     }
149     auto& counter = *context_->storage->mutable_counter_table();
150     counter[pending_counter.row].set_track_id(track_id);
151   }
152   pending_upid_resolution_counter_.clear();
153 }
154 
155 }  // namespace perfetto::trace_processor
156