• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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_PROTO_PROTO_IMPORTER_MODULE_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_
19 
20 #include <optional>
21 
22 #include "perfetto/base/status.h"
23 #include "src/trace_processor/importers/common/trace_parser.h"
24 
25 namespace perfetto {
26 
27 namespace protos {
28 namespace pbzero {
29 class TraceConfig_Decoder;
30 class TracePacket_Decoder;
31 }  // namespace pbzero
32 }  // namespace protos
33 
34 namespace trace_processor {
35 
36 class PacketSequenceState;
37 class TraceBlobView;
38 class TraceProcessorContext;
39 
40 // This file contains a base class for ProtoTraceReader/Parser modules.
41 // A module implements support for a subset of features of the TracePacket
42 // proto format.
43 // To add and integrate a new module:
44 // (1) Add MyModule as a subclass of ProtoImporterModule,
45 //     overriding the TokenizePacket(), ParsePacket() and/or ParseTraceConfig()
46 //     methods.
47 // (2) In the constructor call the RegisterForField method for every field
48 //     that the module knows how to handle.
49 // (3) Create a module instance and add it to TraceProcessorContext's |modules|
50 //     vector in either default_modules.cc or additional_modules.cc.
51 // See GraphicsEventModule for an example.
52 
53 class ModuleResult {
54  public:
55   // Allow auto conversion from util::Status to Handled / Error result.
ModuleResult(base::Status status)56   ModuleResult(base::Status status)
57       : ignored_(false),
58         error_(status.ok() ? std::nullopt
59                            : std::make_optional(status.message())) {}
60 
61   // Constructs a result that indicates the module ignored the packet and is
62   // deferring the handling of the packet to other modules.
Ignored()63   static ModuleResult Ignored() { return ModuleResult(true); }
64 
65   // Constructs a result that indicates the module handled the packet. Other
66   // modules will not be notified about the packet.
Handled()67   static ModuleResult Handled() { return ModuleResult(false); }
68 
69   // Constructs a result that indicates an error condition while handling the
70   // packet. Other modules will not be notified about the packet.
Error(const std::string & message)71   static ModuleResult Error(const std::string& message) {
72     return ModuleResult(message);
73   }
74 
ignored()75   bool ignored() const { return ignored_; }
ok()76   bool ok() const { return !error_.has_value(); }
message()77   const std::string& message() const { return *error_; }
78 
ToStatus()79   base::Status ToStatus() const {
80     PERFETTO_DCHECK(!ignored_);
81     if (error_)
82       return base::Status(*error_);
83     return base::OkStatus();
84   }
85 
86  private:
ModuleResult(bool ignored)87   explicit ModuleResult(bool ignored) : ignored_(ignored) {}
ModuleResult(const std::string & error)88   explicit ModuleResult(const std::string& error)
89       : ignored_(false), error_(error) {}
90 
91   bool ignored_;
92   std::optional<std::string> error_;
93 };
94 
95 // Base class for modules.
96 class ProtoImporterModule {
97  public:
98   ProtoImporterModule();
99 
100   virtual ~ProtoImporterModule();
101 
102   // Called by ProtoTraceReader during the tokenization stage, i.e. before
103   // sorting. It's called for each TracePacket that contains fields for which
104   // the module was registered. If this returns a result other than
105   // ModuleResult::Ignored(), tokenization of the packet will be aborted after
106   // the module.
107   virtual ModuleResult TokenizePacket(
108       const protos::pbzero::TracePacket_Decoder&,
109       TraceBlobView* packet,
110       int64_t packet_timestamp,
111       PacketSequenceState*,
112       uint32_t field_id);
113 
114   // Called by ProtoTraceReader during the tokenization stage i.e. before
115   // sorting. Indicates that sequence with id |packet_sequence_id| has cleared
116   // its incremental state. This should be used to clear any cached state the
117   // tokenizer has built up while reading packets until this point for this
118   // packet sequence.
OnIncrementalStateCleared(uint32_t)119   virtual void OnIncrementalStateCleared(uint32_t /* packet_sequence_id */) {}
120 
121   // Called by ProtoTraceReader during the tokenization stage i.e. before
122   // sorting. Indicates that sequence with id |packet_sequence_id| has a packet
123   // with first_packet_on_sequence = true. This implies that there was no data
124   // loss, including ring buffer overwrittes, on this sequence.
OnFirstPacketOnSequence(uint32_t)125   virtual void OnFirstPacketOnSequence(uint32_t /* packet_sequence_id */) {}
126 
127   // ParsePacket functions are called by ProtoTraceParser after the sorting
128   // stage for each non-ftrace TracePacket that contains fields for which the
129   // module was registered.
130   virtual void ParseTracePacketData(const protos::pbzero::TracePacket_Decoder&,
131                                     int64_t ts,
132                                     const TracePacketData&,
133                                     uint32_t /*field_id*/);
134 
135   // Called by ProtoTraceParser for trace config packets after the sorting
136   // stage, on all existing modules.
137   virtual void ParseTraceConfig(const protos::pbzero::TraceConfig_Decoder&);
138 
NotifyEndOfFile()139   virtual void NotifyEndOfFile() {}
140 
141  protected:
142   void RegisterForField(uint32_t field_id, TraceProcessorContext*);
143   // Primarily intended for special modules that need to get all TracePacket's,
144   // for example for trace proto content analysis. Most modules need to register
145   // for specific fields using the method above.
146   void RegisterForAllFields(TraceProcessorContext*);
147 };
148 
149 }  // namespace trace_processor
150 }  // namespace perfetto
151 
152 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_
153