3 * Copyright 2018 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
20 #define GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
22 #include <grpc/impl/codegen/port_platform.h>
24 #include <grpc/grpc.h>
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"
37 // Channel arg key for channelz node.
38 #define GRPC_ARG_CHANNELZ_CHANNEL_NODE "grpc.channelz_channel_node"
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"
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
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
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);
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;
67 typedef InlinedVector<SocketNode*, 10> ChildSocketsList;
70 class CallCountingHelperPeer;
71 class ChannelNodePeer;
72 } // namespace testing
74 // base class for all channelz entities
75 class BaseNode : public RefCounted<BaseNode> {
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 {
88 explicit BaseNode(EntityType type);
91 // All children must implement this function.
92 virtual grpc_json* RenderJson() GRPC_ABSTRACT;
94 // Renders the json and returns allocated string that must be freed by the
96 char* RenderJsonString();
98 EntityType type() const { return type_; }
99 intptr_t uuid() const { return uuid_; }
102 // to allow the ChannelzRegistry to set uuid_ under its lock.
103 friend class ChannelzRegistry;
104 const EntityType type_;
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 {
116 CallCountingHelper();
117 ~CallCountingHelper();
119 void RecordCallStarted();
120 void RecordCallFailed();
121 void RecordCallSucceeded();
123 // Common rendering of the call count data and last_call_started_timestamp.
124 void PopulateCallCounts(grpc_json* json);
127 // testing peer friend.
128 friend class testing::CallCountingHelperPeer;
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;
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;
144 // collects the sharded data into one CounterData struct.
145 void CollectData(CounterData* out);
147 AtomicCounterData* per_cpu_counter_data_storage_ = nullptr;
148 size_t num_cores_ = 0;
151 // Handles channelz bookkeeping for channels
152 class ChannelNode : public BaseNode {
154 ChannelNode(UniquePtr<char> target, size_t channel_tracer_max_nodes,
155 intptr_t parent_uuid);
157 intptr_t parent_uuid() const { return parent_uuid_; }
159 grpc_json* RenderJson() override;
161 // proxy methods to composed classes.
162 void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
163 trace_.AddTraceEvent(severity, data);
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));
171 void RecordCallStarted() { call_counter_.RecordCallStarted(); }
172 void RecordCallFailed() { call_counter_.RecordCallFailed(); }
173 void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
175 void SetConnectivityState(grpc_connectivity_state state);
177 void AddChildChannel(intptr_t child_uuid);
178 void RemoveChildChannel(intptr_t child_uuid);
180 void AddChildSubchannel(intptr_t child_uuid);
181 void RemoveChildSubchannel(intptr_t child_uuid);
184 void PopulateChildRefs(grpc_json* json);
186 // to allow the channel trace test to access trace_.
187 friend class testing::ChannelNodePeer;
189 UniquePtr<char> target_;
190 CallCountingHelper call_counter_;
192 const intptr_t parent_uuid_;
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};
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_;
206 // Handles channelz bookkeeping for servers
207 class ServerNode : public BaseNode {
209 ServerNode(grpc_server* server, size_t channel_tracer_max_nodes);
210 ~ServerNode() override;
212 grpc_json* RenderJson() override;
214 char* RenderServerSockets(intptr_t start_socket_id,
215 intptr_t pagination_limit);
217 // proxy methods to composed classes.
218 void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
219 trace_.AddTraceEvent(severity, data);
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));
227 void RecordCallStarted() { call_counter_.RecordCallStarted(); }
228 void RecordCallFailed() { call_counter_.RecordCallFailed(); }
229 void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
232 grpc_server* server_;
233 CallCountingHelper call_counter_;
237 // Handles channelz bookkeeping for sockets
238 class SocketNode : public BaseNode {
240 SocketNode(UniquePtr<char> local, UniquePtr<char> remote);
241 ~SocketNode() override {}
243 grpc_json* RenderJson() override;
245 void RecordStreamStartedFromLocal();
246 void RecordStreamStartedFromRemote();
247 void RecordStreamSucceeded() {
248 gpr_atm_no_barrier_fetch_add(&streams_succeeded_, static_cast<gpr_atm>(1));
250 void RecordStreamFailed() {
251 gpr_atm_no_barrier_fetch_add(&streams_failed_, static_cast<gpr_atm>(1));
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));
259 const char* remote() { return remote_.get(); }
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_;
276 // Handles channelz bookkeeping for listen sockets
277 class ListenSocketNode : public BaseNode {
279 // ListenSocketNode takes ownership of host.
280 explicit ListenSocketNode(UniquePtr<char> local_addr);
281 ~ListenSocketNode() override {}
283 grpc_json* RenderJson() override;
286 UniquePtr<char> local_addr_;
289 } // namespace channelz
290 } // namespace grpc_core
292 #endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_H */