• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 <limits>
18 
19 #include <stdint.h>
20 
21 #include "src/trace_processor/importers/common/flow_tracker.h"
22 #include "src/trace_processor/importers/common/slice_tracker.h"
23 #include "src/trace_processor/storage/trace_storage.h"
24 #include "src/trace_processor/types/trace_processor_context.h"
25 
26 namespace perfetto {
27 namespace trace_processor {
28 
FlowTracker(TraceProcessorContext * context)29 FlowTracker::FlowTracker(TraceProcessorContext* context) : context_(context) {
30   name_key_id_ = context_->storage->InternString("name");
31   cat_key_id_ = context_->storage->InternString("cat");
32 }
33 
34 FlowTracker::~FlowTracker() = default;
35 
36 /* TODO: if we report a flow event earlier that a corresponding slice then
37   flow event would not be added, and it will increase "flow_no_enclosing_slice"
38   In catapult, it was possible to report a flow after an enclosing slice if
39   timestamps were equal. But because of our seqential processing of a trace
40   it is a bit tricky to make it here.
41   We suspect that this case is too rare or impossible */
Begin(TrackId track_id,FlowId flow_id)42 void FlowTracker::Begin(TrackId track_id, FlowId flow_id) {
43   base::Optional<SliceId> open_slice_id =
44       context_->slice_tracker->GetTopmostSliceOnTrack(track_id);
45   if (!open_slice_id) {
46     context_->storage->IncrementStats(stats::flow_no_enclosing_slice);
47     return;
48   }
49   if (flow_to_slice_map_.count(flow_id) != 0) {
50     context_->storage->IncrementStats(stats::flow_duplicate_id);
51     return;
52   }
53   flow_to_slice_map_[flow_id] = open_slice_id.value();
54 }
55 
Step(TrackId track_id,FlowId flow_id)56 void FlowTracker::Step(TrackId track_id, FlowId flow_id) {
57   base::Optional<SliceId> open_slice_id =
58       context_->slice_tracker->GetTopmostSliceOnTrack(track_id);
59   if (!open_slice_id) {
60     context_->storage->IncrementStats(stats::flow_no_enclosing_slice);
61     return;
62   }
63   if (flow_to_slice_map_.count(flow_id) == 0) {
64     context_->storage->IncrementStats(stats::flow_step_without_start);
65     return;
66   }
67   SliceId slice_out_id = flow_to_slice_map_[flow_id];
68   InsertFlow(flow_id, slice_out_id, open_slice_id.value());
69   flow_to_slice_map_[flow_id] = open_slice_id.value();
70 }
71 
End(TrackId track_id,FlowId flow_id,bool bind_enclosing_slice,bool close_flow)72 void FlowTracker::End(TrackId track_id,
73                       FlowId flow_id,
74                       bool bind_enclosing_slice,
75                       bool close_flow) {
76   if (!bind_enclosing_slice) {
77     pending_flow_ids_map_[track_id].push_back(flow_id);
78     return;
79   }
80   base::Optional<SliceId> open_slice_id =
81       context_->slice_tracker->GetTopmostSliceOnTrack(track_id);
82   if (!open_slice_id) {
83     context_->storage->IncrementStats(stats::flow_no_enclosing_slice);
84     return;
85   }
86   if (flow_to_slice_map_.count(flow_id) == 0) {
87     context_->storage->IncrementStats(stats::flow_end_without_start);
88     return;
89   }
90   SliceId slice_out_id = flow_to_slice_map_[flow_id];
91   if (close_flow) {
92     flow_to_slice_map_.erase(flow_to_slice_map_.find(flow_id));
93   }
94   InsertFlow(flow_id, slice_out_id, open_slice_id.value());
95 }
96 
IsActive(FlowId flow_id) const97 bool FlowTracker::IsActive(FlowId flow_id) const {
98   return flow_to_slice_map_.find(flow_id) != flow_to_slice_map_.end();
99 }
100 
GetFlowIdForV1Event(uint64_t source_id,StringId cat,StringId name)101 FlowId FlowTracker::GetFlowIdForV1Event(uint64_t source_id,
102                                         StringId cat,
103                                         StringId name) {
104   V1FlowId v1_flow_id = {source_id, cat, name};
105   auto iter = v1_flow_id_to_flow_id_map_.find(v1_flow_id);
106   if (iter != v1_flow_id_to_flow_id_map_.end()) {
107     return iter->second;
108   }
109   FlowId new_id = v1_id_counter_++;
110   flow_id_to_v1_flow_id_map_[new_id] = v1_flow_id;
111   v1_flow_id_to_flow_id_map_[v1_flow_id] = new_id;
112   return new_id;
113 }
114 
ClosePendingEventsOnTrack(TrackId track_id,SliceId slice_id)115 void FlowTracker::ClosePendingEventsOnTrack(TrackId track_id,
116                                             SliceId slice_id) {
117   auto iter = pending_flow_ids_map_.find(track_id);
118   if (iter == pending_flow_ids_map_.end())
119     return;
120 
121   for (FlowId flow_id : iter->second) {
122     SliceId slice_out_id = flow_to_slice_map_[flow_id];
123     InsertFlow(flow_id, slice_out_id, slice_id);
124   }
125 
126   pending_flow_ids_map_.erase(iter);
127 }
128 
InsertFlow(FlowId flow_id,SliceId slice_out_id,SliceId slice_in_id)129 void FlowTracker::InsertFlow(FlowId flow_id,
130                              SliceId slice_out_id,
131                              SliceId slice_in_id) {
132   tables::FlowTable::Row row(slice_out_id, slice_in_id, kInvalidArgSetId);
133   auto id = context_->storage->mutable_flow_table()->Insert(row).id;
134 
135   auto it = flow_id_to_v1_flow_id_map_.find(flow_id);
136   if (it != flow_id_to_v1_flow_id_map_.end()) {
137     // TODO(b/168007725): Add any args from v1 flow events and also export them.
138     auto args_tracker = ArgsTracker(context_);
139     auto inserter = context_->args_tracker->AddArgsTo(id);
140     inserter.AddArg(name_key_id_, Variadic::String(it->second.name));
141     inserter.AddArg(cat_key_id_, Variadic::String(it->second.cat));
142     context_->args_tracker->Flush();
143   }
144 }
145 
InsertFlow(SliceId slice_out_id,SliceId slice_in_id)146 void FlowTracker::InsertFlow(SliceId slice_out_id, SliceId slice_in_id) {
147   tables::FlowTable::Row row(slice_out_id, slice_in_id, kInvalidArgSetId);
148   context_->storage->mutable_flow_table()->Insert(row);
149 }
150 
151 }  // namespace trace_processor
152 }  // namespace perfetto
153