aboutsummaryrefslogtreecommitdiff
path: root/src/trace_processor/importers/proto/proto_importer_module.h
blob: cc2c3a2b3cfe1e2be066276da597765461c3c48b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_

#include <optional>

#include "perfetto/base/status.h"
#include "src/trace_processor/importers/common/trace_parser.h"

namespace perfetto {

namespace protos {
namespace pbzero {
class TraceConfig_Decoder;
class TracePacket_Decoder;
}  // namespace pbzero
}  // namespace protos

namespace trace_processor {

class PacketSequenceState;
class TraceBlobView;
class TraceProcessorContext;

// This file contains a base class for ProtoTraceReader/Parser modules.
// A module implements support for a subset of features of the TracePacket
// proto format.
// To add and integrate a new module:
// (1) Add MyModule as a subclass of ProtoImporterModule,
//     overriding the TokenizePacket(), ParsePacket() and/or ParseTraceConfig()
//     methods.
// (2) In the constructor call the RegisterForField method for every field
//     that the module knows how to handle.
// (3) Create a module instance and add it to TraceProcessorContext's |modules|
//     vector in either default_modules.cc or additional_modules.cc.
// See GraphicsEventModule for an example.

class ModuleResult {
 public:
  // Allow auto conversion from util::Status to Handled / Error result.
  ModuleResult(base::Status status)
      : ignored_(false),
        error_(status.ok() ? std::nullopt
                           : std::make_optional(status.message())) {}

  // Constructs a result that indicates the module ignored the packet and is
  // deferring the handling of the packet to other modules.
  static ModuleResult Ignored() { return ModuleResult(true); }

  // Constructs a result that indicates the module handled the packet. Other
  // modules will not be notified about the packet.
  static ModuleResult Handled() { return ModuleResult(false); }

  // Constructs a result that indicates an error condition while handling the
  // packet. Other modules will not be notified about the packet.
  static ModuleResult Error(const std::string& message) {
    return ModuleResult(message);
  }

  bool ignored() const { return ignored_; }
  bool ok() const { return !error_.has_value(); }
  const std::string& message() const { return *error_; }

  base::Status ToStatus() const {
    PERFETTO_DCHECK(!ignored_);
    if (error_)
      return base::Status(*error_);
    return base::OkStatus();
  }

 private:
  explicit ModuleResult(bool ignored) : ignored_(ignored) {}
  explicit ModuleResult(const std::string& error)
      : ignored_(false), error_(error) {}

  bool ignored_;
  std::optional<std::string> error_;
};

// Base class for modules.
class ProtoImporterModule {
 public:
  ProtoImporterModule();

  virtual ~ProtoImporterModule();

  // Called by ProtoTraceReader during the tokenization stage, i.e. before
  // sorting. It's called for each TracePacket that contains fields for which
  // the module was registered. If this returns a result other than
  // ModuleResult::Ignored(), tokenization of the packet will be aborted after
  // the module.
  virtual ModuleResult TokenizePacket(
      const protos::pbzero::TracePacket_Decoder&,
      TraceBlobView* packet,
      int64_t packet_timestamp,
      PacketSequenceState*,
      uint32_t field_id);

  // Called by ProtoTraceReader during the tokenization stage i.e. before
  // sorting. Indicates that sequence with id |packet_sequence_id| has cleared
  // its incremental state. This should be used to clear any cached state the
  // tokenizer has built up while reading packets until this point for this
  // packet sequence.
  virtual void OnIncrementalStateCleared(uint32_t /* packet_sequence_id */) {}

  // Called by ProtoTraceReader during the tokenization stage i.e. before
  // sorting. Indicates that sequence with id |packet_sequence_id| has a packet
  // with first_packet_on_sequence = true. This implies that there was no data
  // loss, including ring buffer overwrittes, on this sequence.
  virtual void OnFirstPacketOnSequence(uint32_t /* packet_sequence_id */) {}

  // ParsePacket functions are called by ProtoTraceParser after the sorting
  // stage for each non-ftrace TracePacket that contains fields for which the
  // module was registered.
  virtual void ParseTracePacketData(const protos::pbzero::TracePacket_Decoder&,
                                    int64_t ts,
                                    const TracePacketData&,
                                    uint32_t /*field_id*/);

  // Called by ProtoTraceParser for trace config packets after the sorting
  // stage, on all existing modules.
  virtual void ParseTraceConfig(const protos::pbzero::TraceConfig_Decoder&);

  virtual void NotifyEndOfFile() {}

 protected:
  void RegisterForField(uint32_t field_id, TraceProcessorContext*);
  // Primarily intended for special modules that need to get all TracePacket's,
  // for example for trace proto content analysis. Most modules need to register
  // for specific fields using the method above.
  void RegisterForAllFields(TraceProcessorContext*);
};

}  // namespace trace_processor
}  // namespace perfetto

#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_