Imported Upstream version 1.22.0
[platform/upstream/grpc.git] / src / core / lib / channel / channelz.h
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
22 #include <grpc/impl/codegen/port_platform.h>
23
24 #include <grpc/grpc.h>
25
26 #include "src/core/lib/channel/channel_trace.h"
27 #include "src/core/lib/gprpp/inlined_vector.h"
28 #include "src/core/lib/gprpp/manual_constructor.h"
29 #include "src/core/lib/gprpp/map.h"
30 #include "src/core/lib/gprpp/ref_counted.h"
31 #include "src/core/lib/gprpp/ref_counted_ptr.h"
32 #include "src/core/lib/gprpp/sync.h"
33 #include "src/core/lib/iomgr/error.h"
34 #include "src/core/lib/iomgr/exec_ctx.h"
35 #include "src/core/lib/json/json.h"
36
37 // Channel arg key for channelz node.
38 #define GRPC_ARG_CHANNELZ_CHANNEL_NODE "grpc.channelz_channel_node"
39
40 // Channel arg key to encode the channelz uuid of the channel's parent.
41 #define GRPC_ARG_CHANNELZ_PARENT_UUID "grpc.channelz_parent_uuid"
42
43 /** This is the default value for whether or not to enable channelz. If
44  * GRPC_ARG_ENABLE_CHANNELZ is set, it will override this default value. */
45 #define GRPC_ENABLE_CHANNELZ_DEFAULT true
46
47 /** This is the default value for the maximum amount of memory used by trace
48  * events per channel trace node. If
49  * GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE is set, it will override
50  * this default value. */
51 #define GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT 1024 * 4
52
53 namespace grpc_core {
54
55 namespace channelz {
56
57 // Helpers for getting and setting GRPC_ARG_CHANNELZ_PARENT_UUID.
58 grpc_arg MakeParentUuidArg(intptr_t parent_uuid);
59 intptr_t GetParentUuidFromArgs(const grpc_channel_args& args);
60
61 // TODO(ncteisen), this only contains the uuids of the children for now,
62 // since that is all that is strictly needed. In a future enhancement we will
63 // add human readable names as in the channelz.proto
64 typedef InlinedVector<intptr_t, 10> ChildRefsList;
65
66 class SocketNode;
67 typedef InlinedVector<SocketNode*, 10> ChildSocketsList;
68
69 namespace testing {
70 class CallCountingHelperPeer;
71 class ChannelNodePeer;
72 }  // namespace testing
73
74 // base class for all channelz entities
75 class BaseNode : public RefCounted<BaseNode> {
76  public:
77   // There are only four high level channelz entities. However, to support
78   // GetTopChannelsRequest, we split the Channel entity into two different
79   // types. All children of BaseNode must be one of these types.
80   enum class EntityType {
81     kTopLevelChannel,
82     kInternalChannel,
83     kSubchannel,
84     kServer,
85     kSocket,
86   };
87
88   explicit BaseNode(EntityType type);
89   virtual ~BaseNode();
90
91   // All children must implement this function.
92   virtual grpc_json* RenderJson() GRPC_ABSTRACT;
93
94   // Renders the json and returns allocated string that must be freed by the
95   // caller.
96   char* RenderJsonString();
97
98   EntityType type() const { return type_; }
99   intptr_t uuid() const { return uuid_; }
100
101  private:
102   // to allow the ChannelzRegistry to set uuid_ under its lock.
103   friend class ChannelzRegistry;
104   const EntityType type_;
105   intptr_t uuid_;
106 };
107
108 // This class is a helper class for channelz entities that deal with Channels,
109 // Subchannels, and Servers, since those have similar proto definitions.
110 // This class has the ability to:
111 //   - track calls_{started,succeeded,failed}
112 //   - track last_call_started_timestamp
113 //   - perform rendering of the above items
114 class CallCountingHelper {
115  public:
116   CallCountingHelper();
117   ~CallCountingHelper();
118
119   void RecordCallStarted();
120   void RecordCallFailed();
121   void RecordCallSucceeded();
122
123   // Common rendering of the call count data and last_call_started_timestamp.
124   void PopulateCallCounts(grpc_json* json);
125
126  private:
127   // testing peer friend.
128   friend class testing::CallCountingHelperPeer;
129
130   struct AtomicCounterData {
131     gpr_atm calls_started = 0;
132     gpr_atm calls_succeeded = 0;
133     gpr_atm calls_failed = 0;
134     gpr_atm last_call_started_millis = 0;
135   };
136
137   struct CounterData {
138     intptr_t calls_started = 0;
139     intptr_t calls_succeeded = 0;
140     intptr_t calls_failed = 0;
141     intptr_t last_call_started_millis = 0;
142   };
143
144   // collects the sharded data into one CounterData struct.
145   void CollectData(CounterData* out);
146
147   AtomicCounterData* per_cpu_counter_data_storage_ = nullptr;
148   size_t num_cores_ = 0;
149 };
150
151 // Handles channelz bookkeeping for channels
152 class ChannelNode : public BaseNode {
153  public:
154   ChannelNode(UniquePtr<char> target, size_t channel_tracer_max_nodes,
155               intptr_t parent_uuid);
156
157   intptr_t parent_uuid() const { return parent_uuid_; }
158
159   grpc_json* RenderJson() override;
160
161   // proxy methods to composed classes.
162   void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
163     trace_.AddTraceEvent(severity, data);
164   }
165   void AddTraceEventWithReference(ChannelTrace::Severity severity,
166                                   const grpc_slice& data,
167                                   RefCountedPtr<BaseNode> referenced_channel) {
168     trace_.AddTraceEventWithReference(severity, data,
169                                       std::move(referenced_channel));
170   }
171   void RecordCallStarted() { call_counter_.RecordCallStarted(); }
172   void RecordCallFailed() { call_counter_.RecordCallFailed(); }
173   void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
174
175   void SetConnectivityState(grpc_connectivity_state state);
176
177   void AddChildChannel(intptr_t child_uuid);
178   void RemoveChildChannel(intptr_t child_uuid);
179
180   void AddChildSubchannel(intptr_t child_uuid);
181   void RemoveChildSubchannel(intptr_t child_uuid);
182
183  private:
184   void PopulateChildRefs(grpc_json* json);
185
186   // to allow the channel trace test to access trace_.
187   friend class testing::ChannelNodePeer;
188
189   UniquePtr<char> target_;
190   CallCountingHelper call_counter_;
191   ChannelTrace trace_;
192   const intptr_t parent_uuid_;
193
194   // Least significant bit indicates whether the value is set.  Remaining
195   // bits are a grpc_connectivity_state value.
196   Atomic<int> connectivity_state_{0};
197
198   Mutex child_mu_;  // Guards child maps below.
199   // TODO(roth): We don't actually use the values here, only the keys, so
200   // these should be sets instead of maps, but we don't currently have a set
201   // implementation.  Change this if/when we have one.
202   Map<intptr_t, bool> child_channels_;
203   Map<intptr_t, bool> child_subchannels_;
204 };
205
206 // Handles channelz bookkeeping for servers
207 class ServerNode : public BaseNode {
208  public:
209   ServerNode(grpc_server* server, size_t channel_tracer_max_nodes);
210   ~ServerNode() override;
211
212   grpc_json* RenderJson() override;
213
214   char* RenderServerSockets(intptr_t start_socket_id,
215                             intptr_t pagination_limit);
216
217   // proxy methods to composed classes.
218   void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
219     trace_.AddTraceEvent(severity, data);
220   }
221   void AddTraceEventWithReference(ChannelTrace::Severity severity,
222                                   const grpc_slice& data,
223                                   RefCountedPtr<BaseNode> referenced_channel) {
224     trace_.AddTraceEventWithReference(severity, data,
225                                       std::move(referenced_channel));
226   }
227   void RecordCallStarted() { call_counter_.RecordCallStarted(); }
228   void RecordCallFailed() { call_counter_.RecordCallFailed(); }
229   void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
230
231  private:
232   grpc_server* server_;
233   CallCountingHelper call_counter_;
234   ChannelTrace trace_;
235 };
236
237 // Handles channelz bookkeeping for sockets
238 class SocketNode : public BaseNode {
239  public:
240   SocketNode(UniquePtr<char> local, UniquePtr<char> remote);
241   ~SocketNode() override {}
242
243   grpc_json* RenderJson() override;
244
245   void RecordStreamStartedFromLocal();
246   void RecordStreamStartedFromRemote();
247   void RecordStreamSucceeded() {
248     gpr_atm_no_barrier_fetch_add(&streams_succeeded_, static_cast<gpr_atm>(1));
249   }
250   void RecordStreamFailed() {
251     gpr_atm_no_barrier_fetch_add(&streams_failed_, static_cast<gpr_atm>(1));
252   }
253   void RecordMessagesSent(uint32_t num_sent);
254   void RecordMessageReceived();
255   void RecordKeepaliveSent() {
256     gpr_atm_no_barrier_fetch_add(&keepalives_sent_, static_cast<gpr_atm>(1));
257   }
258
259   const char* remote() { return remote_.get(); }
260
261  private:
262   gpr_atm streams_started_ = 0;
263   gpr_atm streams_succeeded_ = 0;
264   gpr_atm streams_failed_ = 0;
265   gpr_atm messages_sent_ = 0;
266   gpr_atm messages_received_ = 0;
267   gpr_atm keepalives_sent_ = 0;
268   gpr_atm last_local_stream_created_millis_ = 0;
269   gpr_atm last_remote_stream_created_millis_ = 0;
270   gpr_atm last_message_sent_millis_ = 0;
271   gpr_atm last_message_received_millis_ = 0;
272   UniquePtr<char> local_;
273   UniquePtr<char> remote_;
274 };
275
276 // Handles channelz bookkeeping for listen sockets
277 class ListenSocketNode : public BaseNode {
278  public:
279   // ListenSocketNode takes ownership of host.
280   explicit ListenSocketNode(UniquePtr<char> local_addr);
281   ~ListenSocketNode() override {}
282
283   grpc_json* RenderJson() override;
284
285  private:
286   UniquePtr<char> local_addr_;
287 };
288
289 }  // namespace channelz
290 }  // namespace grpc_core
291
292 #endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_H */