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 INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
18 #define INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
19 
20 #include "perfetto/protozero/message_handle.h"
21 #include "perfetto/tracing/internal/track_event_internal.h"
22 #include "perfetto/tracing/traced_proto.h"
23 #include "protos/perfetto/trace/trace_packet.pbzero.h"
24 
25 namespace perfetto {
26 namespace internal {
27 class TrackEventInternal;
28 }
29 
30 // Allows adding custom arguments into track events. Example:
31 //
32 //   TRACE_EVENT_BEGIN("category", "Title",
33 //                     [](perfetto::EventContext ctx) {
34 //                       auto* dbg = ctx.event()->add_debug_annotations();
35 //                       dbg->set_name("name");
36 //                       dbg->set_int_value(1234);
37 //                     });
38 //
39 class PERFETTO_EXPORT EventContext {
40  public:
41   EventContext(EventContext&&) = default;
42 
43   // For Chromium during the transition phase to the client library.
44   // TODO(eseckler): Remove once Chromium has switched to client lib entirely.
45   explicit EventContext(
46       protos::pbzero::TrackEvent* event,
47       internal::TrackEventIncrementalState* incremental_state = nullptr)
event_(event)48       : event_(event), incremental_state_(incremental_state) {}
49 
50   ~EventContext();
51 
52   // Get a TrackEvent message to write typed arguments to.
53   //
54   // event() is a template method to allow callers to specify a subclass of
55   // TrackEvent instead. Those subclasses correspond to TrackEvent message with
56   // application-specific extensions. More information in
57   // design-docs/extensions.md.
58   template <typename EventType = protos::pbzero::TrackEvent>
event()59   EventType* event() const {
60     // As the method does downcasting, we check that a target subclass does
61     // not add new fields.
62     static_assert(
63         sizeof(EventType) == sizeof(protos::pbzero::TrackEvent),
64         "Event type must be binary-compatible with protos::pbzero::TrackEvent");
65     return static_cast<EventType*>(event_);
66   }
67 
68   // Convert a raw pointer to protozero message to TracedProto which captures
69   // the reference to this EventContext.
70   template <typename MessageType>
Wrap(MessageType * message)71   TracedProto<MessageType> Wrap(MessageType* message) {
72     static_assert(std::is_base_of<protozero::Message, MessageType>::value,
73                   "TracedProto can be used only with protozero messages");
74 
75     return TracedProto<MessageType>(message, *this);
76   }
77 
78  private:
79   template <typename, size_t, typename, typename>
80   friend class TrackEventInternedDataIndex;
81   friend class internal::TrackEventInternal;
82 
83   using TracePacketHandle =
84       ::protozero::MessageHandle<protos::pbzero::TracePacket>;
85 
86   EventContext(TracePacketHandle, internal::TrackEventIncrementalState*);
87   EventContext(const EventContext&) = delete;
88 
89   TracePacketHandle trace_packet_;
90   protos::pbzero::TrackEvent* event_;
91   internal::TrackEventIncrementalState* incremental_state_;
92 };
93 
94 }  // namespace perfetto
95 
96 #endif  // INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
97