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 #include <grpc/support/port_platform.h>
20
21 #include "src/core/ext/filters/client_channel/client_channel.h"
22 #include "src/core/ext/filters/client_channel/client_channel_channelz.h"
23 #include "src/core/lib/channel/channelz_registry.h"
24 #include "src/core/lib/gpr/useful.h"
25 #include "src/core/lib/surface/channel.h"
26 #include "src/core/lib/transport/connectivity_state.h"
27
28 #include <grpc/support/string_util.h>
29
30 namespace grpc_core {
31 namespace channelz {
32 namespace {
33
client_channel_channelz_copy(void * p)34 void* client_channel_channelz_copy(void* p) { return p; }
35
client_channel_channelz_destroy(void * p)36 void client_channel_channelz_destroy(void* p) {}
37
client_channel_channelz_cmp(void * a,void * b)38 int client_channel_channelz_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
39
40 } // namespace
41
42 static const grpc_arg_pointer_vtable client_channel_channelz_vtable = {
43 client_channel_channelz_copy, client_channel_channelz_destroy,
44 client_channel_channelz_cmp};
45
ClientChannelNode(grpc_channel * channel,size_t channel_tracer_max_nodes,bool is_top_level_channel)46 ClientChannelNode::ClientChannelNode(grpc_channel* channel,
47 size_t channel_tracer_max_nodes,
48 bool is_top_level_channel)
49 : ChannelNode(channel, channel_tracer_max_nodes, is_top_level_channel) {
50 client_channel_ =
51 grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
52 GPR_ASSERT(client_channel_->filter == &grpc_client_channel_filter);
53 }
54
PopulateConnectivityState(grpc_json * json)55 void ClientChannelNode::PopulateConnectivityState(grpc_json* json) {
56 grpc_connectivity_state state;
57 if (ChannelIsDestroyed()) {
58 state = GRPC_CHANNEL_SHUTDOWN;
59 } else {
60 state =
61 grpc_client_channel_check_connectivity_state(client_channel_, false);
62 }
63 json = grpc_json_create_child(nullptr, json, "state", nullptr,
64 GRPC_JSON_OBJECT, false);
65 grpc_json_create_child(nullptr, json, "state",
66 grpc_connectivity_state_name(state), GRPC_JSON_STRING,
67 false);
68 }
69
PopulateChildRefs(grpc_json * json)70 void ClientChannelNode::PopulateChildRefs(grpc_json* json) {
71 ChildRefsList child_subchannels;
72 ChildRefsList child_channels;
73 grpc_json* json_iterator = nullptr;
74 grpc_client_channel_populate_child_refs(client_channel_, &child_subchannels,
75 &child_channels);
76 if (!child_subchannels.empty()) {
77 grpc_json* array_parent = grpc_json_create_child(
78 nullptr, json, "subchannelRef", nullptr, GRPC_JSON_ARRAY, false);
79 for (size_t i = 0; i < child_subchannels.size(); ++i) {
80 json_iterator =
81 grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
82 GRPC_JSON_OBJECT, false);
83 grpc_json_add_number_string_child(json_iterator, nullptr, "subchannelId",
84 child_subchannels[i]);
85 }
86 }
87 if (!child_channels.empty()) {
88 grpc_json* array_parent = grpc_json_create_child(
89 nullptr, json, "channelRef", nullptr, GRPC_JSON_ARRAY, false);
90 json_iterator = nullptr;
91 for (size_t i = 0; i < child_channels.size(); ++i) {
92 json_iterator =
93 grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
94 GRPC_JSON_OBJECT, false);
95 grpc_json_add_number_string_child(json_iterator, nullptr, "channelId",
96 child_channels[i]);
97 }
98 }
99 }
100
CreateChannelArg()101 grpc_arg ClientChannelNode::CreateChannelArg() {
102 return grpc_channel_arg_pointer_create(
103 const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC),
104 reinterpret_cast<void*>(MakeClientChannelNode),
105 &client_channel_channelz_vtable);
106 }
107
MakeClientChannelNode(grpc_channel * channel,size_t channel_tracer_max_nodes,bool is_top_level_channel)108 RefCountedPtr<ChannelNode> ClientChannelNode::MakeClientChannelNode(
109 grpc_channel* channel, size_t channel_tracer_max_nodes,
110 bool is_top_level_channel) {
111 return MakeRefCounted<ClientChannelNode>(channel, channel_tracer_max_nodes,
112 is_top_level_channel);
113 }
114
SubchannelNode(grpc_subchannel * subchannel,size_t channel_tracer_max_nodes)115 SubchannelNode::SubchannelNode(grpc_subchannel* subchannel,
116 size_t channel_tracer_max_nodes)
117 : BaseNode(EntityType::kSubchannel),
118 subchannel_(subchannel),
119 target_(
120 UniquePtr<char>(gpr_strdup(grpc_subchannel_get_target(subchannel_)))),
121 trace_(channel_tracer_max_nodes) {}
122
~SubchannelNode()123 SubchannelNode::~SubchannelNode() {}
124
PopulateConnectivityState(grpc_json * json)125 void SubchannelNode::PopulateConnectivityState(grpc_json* json) {
126 grpc_connectivity_state state;
127 if (subchannel_ == nullptr) {
128 state = GRPC_CHANNEL_SHUTDOWN;
129 } else {
130 state = grpc_subchannel_check_connectivity(subchannel_, nullptr);
131 }
132 json = grpc_json_create_child(nullptr, json, "state", nullptr,
133 GRPC_JSON_OBJECT, false);
134 grpc_json_create_child(nullptr, json, "state",
135 grpc_connectivity_state_name(state), GRPC_JSON_STRING,
136 false);
137 }
138
RenderJson()139 grpc_json* SubchannelNode::RenderJson() {
140 grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
141 grpc_json* json = top_level_json;
142 grpc_json* json_iterator = nullptr;
143 json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr,
144 GRPC_JSON_OBJECT, false);
145 json = json_iterator;
146 json_iterator = nullptr;
147 json_iterator = grpc_json_add_number_string_child(json, json_iterator,
148 "subchannelId", uuid());
149 // reset json iterators to top level object
150 json = top_level_json;
151 json_iterator = nullptr;
152 // create and fill the data child.
153 grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr,
154 GRPC_JSON_OBJECT, false);
155 json = data;
156 json_iterator = nullptr;
157 PopulateConnectivityState(json);
158 GPR_ASSERT(target_.get() != nullptr);
159 grpc_json_create_child(nullptr, json, "target", target_.get(),
160 GRPC_JSON_STRING, false);
161 // fill in the channel trace if applicable
162 grpc_json* trace_json = trace_.RenderJson();
163 if (trace_json != nullptr) {
164 trace_json->key = "trace"; // this object is named trace in channelz.proto
165 grpc_json_link_child(json, trace_json, nullptr);
166 }
167 // ask CallCountingHelper to populate trace and call count data.
168 call_counter_.PopulateCallCounts(json);
169 return top_level_json;
170 }
171
172 } // namespace channelz
173 } // namespace grpc_core
174