Imported Upstream version 1.21.0
[platform/upstream/grpc.git] / src / core / ext / filters / client_channel / client_channel_channelz.cc
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
34 void* client_channel_channelz_copy(void* p) { return p; }
35
36 void client_channel_channelz_destroy(void* p) {}
37
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
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   grpc_client_channel_set_channelz_node(client_channel_, this);
54 }
55
56 void ClientChannelNode::PopulateConnectivityState(grpc_json* json) {
57   grpc_connectivity_state state;
58   if (ChannelIsDestroyed()) {
59     state = GRPC_CHANNEL_SHUTDOWN;
60   } else {
61     state =
62         grpc_client_channel_check_connectivity_state(client_channel_, false);
63   }
64   json = grpc_json_create_child(nullptr, json, "state", nullptr,
65                                 GRPC_JSON_OBJECT, false);
66   grpc_json_create_child(nullptr, json, "state",
67                          grpc_connectivity_state_name(state), GRPC_JSON_STRING,
68                          false);
69 }
70
71 void ClientChannelNode::PopulateChildRefs(grpc_json* json) {
72   ChildRefsList child_subchannels;
73   ChildRefsList child_channels;
74   grpc_json* json_iterator = nullptr;
75   grpc_client_channel_populate_child_refs(client_channel_, &child_subchannels,
76                                           &child_channels);
77   if (!child_subchannels.empty()) {
78     grpc_json* array_parent = grpc_json_create_child(
79         nullptr, json, "subchannelRef", nullptr, GRPC_JSON_ARRAY, false);
80     for (size_t i = 0; i < child_subchannels.size(); ++i) {
81       json_iterator =
82           grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
83                                  GRPC_JSON_OBJECT, false);
84       grpc_json_add_number_string_child(json_iterator, nullptr, "subchannelId",
85                                         child_subchannels[i]);
86     }
87   }
88   if (!child_channels.empty()) {
89     grpc_json* array_parent = grpc_json_create_child(
90         nullptr, json, "channelRef", nullptr, GRPC_JSON_ARRAY, false);
91     json_iterator = nullptr;
92     for (size_t i = 0; i < child_channels.size(); ++i) {
93       json_iterator =
94           grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
95                                  GRPC_JSON_OBJECT, false);
96       grpc_json_add_number_string_child(json_iterator, nullptr, "channelId",
97                                         child_channels[i]);
98     }
99   }
100 }
101
102 grpc_arg ClientChannelNode::CreateChannelArg() {
103   return grpc_channel_arg_pointer_create(
104       const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC),
105       reinterpret_cast<void*>(MakeClientChannelNode),
106       &client_channel_channelz_vtable);
107 }
108
109 RefCountedPtr<ChannelNode> ClientChannelNode::MakeClientChannelNode(
110     grpc_channel* channel, size_t channel_tracer_max_nodes,
111     bool is_top_level_channel) {
112   return MakeRefCounted<ClientChannelNode>(channel, channel_tracer_max_nodes,
113                                            is_top_level_channel);
114 }
115
116 SubchannelNode::SubchannelNode(Subchannel* subchannel,
117                                size_t channel_tracer_max_nodes)
118     : BaseNode(EntityType::kSubchannel),
119       subchannel_(subchannel),
120       target_(UniquePtr<char>(gpr_strdup(subchannel_->GetTargetAddress()))),
121       trace_(channel_tracer_max_nodes) {}
122
123 SubchannelNode::~SubchannelNode() {}
124
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 = subchannel_->CheckConnectivity(true /* inhibit_health_checking */);
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
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   json = top_level_json;
170   // populate the child socket.
171   intptr_t socket_uuid = subchannel_->GetChildSocketUuid();
172   if (socket_uuid != 0) {
173     grpc_json* array_parent = grpc_json_create_child(
174         nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false);
175     json_iterator = grpc_json_create_child(json_iterator, array_parent, nullptr,
176                                            nullptr, GRPC_JSON_OBJECT, false);
177     grpc_json_add_number_string_child(json_iterator, nullptr, "socketId",
178                                       socket_uuid);
179   }
180   return top_level_json;
181 }
182
183 }  // namespace channelz
184 }  // namespace grpc_core