• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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