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