GRPC C++  1.26.0
channelz.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2018 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
20 #define GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
21 
23 
24 #include <grpc/grpc.h>
25 
26 #include <string>
27 
33 #include "src/core/lib/gprpp/map.h"
39 #include "src/core/lib/json/json.h"
40 
41 // Channel arg key for channelz node.
42 #define GRPC_ARG_CHANNELZ_CHANNEL_NODE "grpc.channelz_channel_node"
43 
44 // Channel arg key to encode the channelz uuid of the channel's parent.
45 #define GRPC_ARG_CHANNELZ_PARENT_UUID "grpc.channelz_parent_uuid"
46 
49 #define GRPC_ENABLE_CHANNELZ_DEFAULT true
50 
55 #define GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT 1024 * 4
56 
57 namespace grpc_core {
58 
59 namespace channelz {
60 
61 // Helpers for getting and setting GRPC_ARG_CHANNELZ_PARENT_UUID.
62 grpc_arg MakeParentUuidArg(intptr_t parent_uuid);
63 intptr_t GetParentUuidFromArgs(const grpc_channel_args& args);
64 
65 class SocketNode;
66 class ListenSocketNode;
67 
68 namespace testing {
69 class CallCountingHelperPeer;
70 class ChannelNodePeer;
71 } // namespace testing
72 
73 // base class for all channelz entities
74 class BaseNode : public RefCounted<BaseNode> {
75  public:
76  // There are only four high level channelz entities. However, to support
77  // GetTopChannelsRequest, we split the Channel entity into two different
78  // types. All children of BaseNode must be one of these types.
79  enum class EntityType {
83  kServer,
84  kSocket,
85  };
86 
87  protected:
89 
90  public:
91  virtual ~BaseNode();
92 
93  // All children must implement this function.
94  virtual grpc_json* RenderJson() = 0;
95 
96  // Renders the json and returns allocated string that must be freed by the
97  // caller.
98  char* RenderJsonString();
99 
100  EntityType type() const { return type_; }
101  intptr_t uuid() const { return uuid_; }
102  const std::string& name() const { return name_; }
103 
104  private:
105  // to allow the ChannelzRegistry to set uuid_ under its lock.
106  friend class ChannelzRegistry;
107  const EntityType type_;
108  intptr_t uuid_;
109  std::string name_;
110 };
111 
112 // This class is a helper class for channelz entities that deal with Channels,
113 // Subchannels, and Servers, since those have similar proto definitions.
114 // This class has the ability to:
115 // - track calls_{started,succeeded,failed}
116 // - track last_call_started_timestamp
117 // - perform rendering of the above items
119  public:
121 
122  void RecordCallStarted();
123  void RecordCallFailed();
124  void RecordCallSucceeded();
125 
126  // Common rendering of the call count data and last_call_started_timestamp.
127  void PopulateCallCounts(grpc_json* json);
128 
129  private:
130  // testing peer friend.
132 
133  // TODO(soheil): add a proper PerCPU helper and use it here.
135  // Define the ctors so that we can use this structure in InlinedVector.
136  AtomicCounterData() = default;
138  : calls_started(that.calls_started.Load(MemoryOrder::RELAXED)),
139  calls_succeeded(that.calls_succeeded.Load(MemoryOrder::RELAXED)),
140  calls_failed(that.calls_failed.Load(MemoryOrder::RELAXED)),
142  that.last_call_started_cycle.Load(MemoryOrder::RELAXED)) {}
144  Atomic<int64_t> calls_started{0};
145  Atomic<int64_t> calls_succeeded{0};
146  Atomic<int64_t> calls_failed{0};
147  Atomic<gpr_cycle_counter> last_call_started_cycle{0};
148  // Make sure the size is exactly one cache line.
149  uint8_t padding[GPR_CACHELINE_SIZE - 3 * sizeof(Atomic<intptr_t>) -
150  sizeof(Atomic<gpr_cycle_counter>)];
151  } GPR_ALIGN_STRUCT(GPR_CACHELINE_SIZE);
152 
153  struct CounterData {
154  int64_t calls_started = 0;
155  int64_t calls_succeeded = 0;
156  int64_t calls_failed = 0;
157  gpr_cycle_counter last_call_started_cycle = 0;
158  };
159 
160  // collects the sharded data into one CounterData struct.
161  void CollectData(CounterData* out);
162 
163  // Really zero-sized, but 0-sized arrays are illegal on MSVC.
164  InlinedVector<AtomicCounterData, 1> per_cpu_counter_data_storage_;
165  size_t num_cores_ = 0;
166 };
167 
168 // Handles channelz bookkeeping for channels
169 class ChannelNode : public BaseNode {
170  public:
171  ChannelNode(std::string target, size_t channel_tracer_max_nodes,
172  intptr_t parent_uuid);
173 
174  // Returns the string description of the given connectivity state.
175  static const char* GetChannelConnectivityStateChangeString(
177 
178  intptr_t parent_uuid() const { return parent_uuid_; }
179 
180  grpc_json* RenderJson() override;
181 
182  // proxy methods to composed classes.
183  void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
184  trace_.AddTraceEvent(severity, data);
185  }
187  const grpc_slice& data,
188  RefCountedPtr<BaseNode> referenced_channel) {
189  trace_.AddTraceEventWithReference(severity, data,
190  std::move(referenced_channel));
191  }
192  void RecordCallStarted() { call_counter_.RecordCallStarted(); }
193  void RecordCallFailed() { call_counter_.RecordCallFailed(); }
194  void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
195 
197 
198  // TODO(roth): take in a RefCountedPtr to the child channel so we can retrieve
199  // the human-readable name.
200  void AddChildChannel(intptr_t child_uuid);
201  void RemoveChildChannel(intptr_t child_uuid);
202 
203  // TODO(roth): take in a RefCountedPtr to the child subchannel so we can
204  // retrieve the human-readable name.
205  void AddChildSubchannel(intptr_t child_uuid);
206  void RemoveChildSubchannel(intptr_t child_uuid);
207 
208  private:
209  void PopulateChildRefs(grpc_json* json);
210 
211  // to allow the channel trace test to access trace_.
213 
214  std::string target_;
215  CallCountingHelper call_counter_;
216  ChannelTrace trace_;
217  const intptr_t parent_uuid_;
218 
219  // Least significant bit indicates whether the value is set. Remaining
220  // bits are a grpc_connectivity_state value.
221  Atomic<int> connectivity_state_{0};
222 
223  Mutex child_mu_; // Guards child maps below.
224  // TODO(roth): We don't actually use the values here, only the keys, so
225  // these should be sets instead of maps, but we don't currently have a set
226  // implementation. Change this if/when we have one.
227  std::map<intptr_t, bool> child_channels_;
228  std::map<intptr_t, bool> child_subchannels_;
229 };
230 
231 // Handles channelz bookkeeping for servers
232 class ServerNode : public BaseNode {
233  public:
234  ServerNode(grpc_server* server, size_t channel_tracer_max_nodes);
235 
236  ~ServerNode() override;
237 
238  grpc_json* RenderJson() override;
239 
240  char* RenderServerSockets(intptr_t start_socket_id, intptr_t max_results);
241 
243 
244  void RemoveChildSocket(intptr_t child_uuid);
245 
247 
248  void RemoveChildListenSocket(intptr_t child_uuid);
249 
250  // proxy methods to composed classes.
251  void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
252  trace_.AddTraceEvent(severity, data);
253  }
255  const grpc_slice& data,
256  RefCountedPtr<BaseNode> referenced_channel) {
257  trace_.AddTraceEventWithReference(severity, data,
258  std::move(referenced_channel));
259  }
260  void RecordCallStarted() { call_counter_.RecordCallStarted(); }
261  void RecordCallFailed() { call_counter_.RecordCallFailed(); }
262  void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
263 
264  private:
265  CallCountingHelper call_counter_;
266  ChannelTrace trace_;
267  Mutex child_mu_; // Guards child maps below.
268  std::map<intptr_t, RefCountedPtr<SocketNode>> child_sockets_;
269  std::map<intptr_t, RefCountedPtr<ListenSocketNode>> child_listen_sockets_;
270 };
271 
272 // Handles channelz bookkeeping for sockets
273 class SocketNode : public BaseNode {
274  public:
276  ~SocketNode() override {}
277 
278  grpc_json* RenderJson() override;
279 
283  streams_succeeded_.FetchAdd(1, MemoryOrder::RELAXED);
284  }
286  streams_failed_.FetchAdd(1, MemoryOrder::RELAXED);
287  }
288  void RecordMessagesSent(uint32_t num_sent);
289  void RecordMessageReceived();
291  keepalives_sent_.FetchAdd(1, MemoryOrder::RELAXED);
292  }
293 
294  const std::string& remote() { return remote_; }
295 
296  private:
297  Atomic<int64_t> streams_started_{0};
298  Atomic<int64_t> streams_succeeded_{0};
299  Atomic<int64_t> streams_failed_{0};
300  Atomic<int64_t> messages_sent_{0};
301  Atomic<int64_t> messages_received_{0};
302  Atomic<int64_t> keepalives_sent_{0};
303  Atomic<gpr_cycle_counter> last_local_stream_created_cycle_{0};
304  Atomic<gpr_cycle_counter> last_remote_stream_created_cycle_{0};
305  Atomic<gpr_cycle_counter> last_message_sent_cycle_{0};
306  Atomic<gpr_cycle_counter> last_message_received_cycle_{0};
307  std::string local_;
308  std::string remote_;
309 };
310 
311 // Handles channelz bookkeeping for listen sockets
312 class ListenSocketNode : public BaseNode {
313  public:
315  ~ListenSocketNode() override {}
316 
317  grpc_json* RenderJson() override;
318 
319  private:
320  std::string local_addr_;
321 };
322 
323 } // namespace channelz
324 } // namespace grpc_core
325 
326 #endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_H */
void RemoveChildListenSocket(intptr_t child_uuid)
SocketNode(std::string local, std::string remote, std::string name)
Definition: channelz.h:273
std::string string
Definition: config.h:35
grpc_json * RenderJson() override
An array of arguments that can be passed around.
Definition: grpc_types.h:132
Severity
Definition: channel_trace.h:47
BaseNode(EntityType type, std::string name)
char * RenderServerSockets(intptr_t start_socket_id, intptr_t max_results)
grpc_json * RenderJson() override
void RecordCallFailed()
Definition: channelz.h:193
Atomic< int64_t > calls_succeeded
Definition: channelz.h:142
const std::string & name() const
Definition: channelz.h:102
A grpc_slice s, if initialized, represents the byte range s.bytes[0..s.length-1]. ...
Definition: slice.h:60
grpc_connectivity_state
Connectivity state of a channel.
Definition: connectivity_state.h:27
intptr_t uuid() const
Definition: channelz.h:101
Definition: channelz.h:312
struct grpc_server grpc_server
A server listens to some port and responds to request calls.
Definition: grpc_types.h:65
T FetchAdd(Arg arg, MemoryOrder order=MemoryOrder::SEQ_CST)
Definition: atomic.h:71
A single argument...
Definition: grpc_types.h:103
void RecordCallStarted()
Definition: channelz.h:260
void AddChildSocket(RefCountedPtr< SocketNode > node)
void AddTraceEventWithReference(Severity severity, const grpc_slice &data, RefCountedPtr< BaseNode > referenced_entity)
ChannelNode(std::string target, size_t channel_tracer_max_nodes, intptr_t parent_uuid)
grpc_json * RenderJson() override
~ListenSocketNode() override
Definition: channelz.h:315
intptr_t parent_uuid() const
Definition: channelz.h:178
Internal thread interface.
Definition: backoff.h:26
Atomic< gpr_cycle_counter > last_call_started_cycle
Definition: channelz.h:144
void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice &data)
Definition: channelz.h:251
virtual grpc_json * RenderJson()=0
Definition: channelz.h:118
AtomicCounterData()=default
EntityType
Definition: channelz.h:79
void RecordStreamSucceeded()
Definition: channelz.h:282
Definition: channelz.h:74
Definition: channelz_registry.h:36
void RecordKeepaliveSent()
Definition: channelz.h:290
#define GPR_CACHELINE_SIZE
Definition: port_platform.h:522
void RecordMessagesSent(uint32_t num_sent)
void RemoveChildSocket(intptr_t child_uuid)
intptr_t GetParentUuidFromArgs(const grpc_channel_args &args)
Definition: ref_counted_ptr.h:35
void RecordCallSucceeded()
Definition: channelz.h:194
void RecordCallFailed()
Definition: channelz.h:261
void AddTraceEventWithReference(ChannelTrace::Severity severity, const grpc_slice &data, RefCountedPtr< BaseNode > referenced_channel)
Definition: channelz.h:254
const std::string & remote()
Definition: channelz.h:294
void AddChildChannel(intptr_t child_uuid)
void PopulateCallCounts(grpc_json *json)
void SetConnectivityState(grpc_connectivity_state state)
Definition: json.h:32
void RecordCallStarted()
Definition: channelz.h:192
ServerNode(grpc_server *server, size_t channel_tracer_max_nodes)
Definition: channel_trace.h:42
Definition: ref_counted.h:248
static const char * GetChannelConnectivityStateChangeString(grpc_connectivity_state state)
void RemoveChildSubchannel(intptr_t child_uuid)
void RecordCallSucceeded()
Definition: channelz.h:262
void AddChildListenSocket(RefCountedPtr< ListenSocketNode > node)
Definition: sync.h:40
Definition: channelz.h:232
Atomic< int64_t > calls_failed
Definition: channelz.h:143
Atomic< int64_t > calls_started
Definition: channelz.h:141
grpc_json * RenderJson() override
void AddChildSubchannel(intptr_t child_uuid)
friend class testing::CallCountingHelperPeer
Definition: channelz.h:131
Definition: channelz.h:169
ListenSocketNode(std::string local_addr, std::string name)
void AddTraceEvent(Severity severity, const grpc_slice &data)
EntityType type() const
Definition: channelz.h:100
~SocketNode() override
Definition: channelz.h:276
void AddTraceEventWithReference(ChannelTrace::Severity severity, const grpc_slice &data, RefCountedPtr< BaseNode > referenced_channel)
Definition: channelz.h:186
grpc_arg MakeParentUuidArg(intptr_t parent_uuid)
uint8_t padding[GPR_CACHELINE_SIZE - 3 *sizeof(Atomic< intptr_t >) - sizeof(Atomic< gpr_cycle_counter >)]
Definition: channelz.h:147
friend class testing::ChannelNodePeer
Definition: channelz.h:212
void RecordStreamFailed()
Definition: channelz.h:285
void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice &data)
Definition: channelz.h:183
void RemoveChildChannel(intptr_t child_uuid)