• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2017 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/impl/codegen/port_platform.h>
20 
21 #include "src/core/lib/channel/channelz.h"
22 
23 #include <grpc/grpc.h>
24 #include <grpc/support/alloc.h>
25 #include <grpc/support/log.h>
26 #include <grpc/support/string_util.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "src/core/lib/channel/channelz_registry.h"
32 #include "src/core/lib/channel/status_util.h"
33 #include "src/core/lib/gpr/string.h"
34 #include "src/core/lib/gpr/useful.h"
35 #include "src/core/lib/gprpp/memory.h"
36 #include "src/core/lib/iomgr/error.h"
37 #include "src/core/lib/slice/slice_internal.h"
38 #include "src/core/lib/surface/channel.h"
39 #include "src/core/lib/transport/error_utils.h"
40 
41 namespace grpc_core {
42 namespace channelz {
43 
BaseNode(EntityType type)44 BaseNode::BaseNode(EntityType type)
45     : type_(type), uuid_(ChannelzRegistry::Register(this)) {}
46 
~BaseNode()47 BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); }
48 
RenderJsonString()49 char* BaseNode::RenderJsonString() {
50   grpc_json* json = RenderJson();
51   GPR_ASSERT(json != nullptr);
52   char* json_str = grpc_json_dump_to_string(json, 0);
53   grpc_json_destroy(json);
54   return json_str;
55 }
56 
CallCountingHelper()57 CallCountingHelper::CallCountingHelper() {
58   gpr_atm_no_barrier_store(&last_call_started_millis_,
59                            (gpr_atm)ExecCtx::Get()->Now());
60 }
61 
~CallCountingHelper()62 CallCountingHelper::~CallCountingHelper() {}
63 
RecordCallStarted()64 void CallCountingHelper::RecordCallStarted() {
65   gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1);
66   gpr_atm_no_barrier_store(&last_call_started_millis_,
67                            (gpr_atm)ExecCtx::Get()->Now());
68 }
69 
PopulateCallCounts(grpc_json * json)70 void CallCountingHelper::PopulateCallCounts(grpc_json* json) {
71   grpc_json* json_iterator = nullptr;
72   if (calls_started_ != 0) {
73     json_iterator = grpc_json_add_number_string_child(
74         json, json_iterator, "callsStarted", calls_started_);
75   }
76   if (calls_succeeded_ != 0) {
77     json_iterator = grpc_json_add_number_string_child(
78         json, json_iterator, "callsSucceeded", calls_succeeded_);
79   }
80   if (calls_failed_) {
81     json_iterator = grpc_json_add_number_string_child(
82         json, json_iterator, "callsFailed", calls_failed_);
83   }
84   gpr_timespec ts =
85       grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME);
86   json_iterator =
87       grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
88                              gpr_format_timespec(ts), GRPC_JSON_STRING, true);
89 }
90 
ChannelNode(grpc_channel * channel,size_t channel_tracer_max_nodes,bool is_top_level_channel)91 ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
92                          bool is_top_level_channel)
93     : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel
94                                     : EntityType::kInternalChannel),
95       channel_(channel),
96       target_(UniquePtr<char>(grpc_channel_get_target(channel_))),
97       trace_(channel_tracer_max_nodes) {}
98 
~ChannelNode()99 ChannelNode::~ChannelNode() {}
100 
RenderJson()101 grpc_json* ChannelNode::RenderJson() {
102   // We need to track these three json objects to build our object
103   grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
104   grpc_json* json = top_level_json;
105   grpc_json* json_iterator = nullptr;
106   // create and fill the ref child
107   json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr,
108                                          GRPC_JSON_OBJECT, false);
109   json = json_iterator;
110   json_iterator = nullptr;
111   json_iterator = grpc_json_add_number_string_child(json, json_iterator,
112                                                     "channelId", uuid());
113   // reset json iterators to top level object
114   json = top_level_json;
115   json_iterator = nullptr;
116   // create and fill the data child.
117   grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr,
118                                            GRPC_JSON_OBJECT, false);
119   json = data;
120   json_iterator = nullptr;
121   // template method. Child classes may override this to add their specific
122   // functionality.
123   PopulateConnectivityState(json);
124   // populate the target.
125   GPR_ASSERT(target_.get() != nullptr);
126   grpc_json_create_child(nullptr, json, "target", target_.get(),
127                          GRPC_JSON_STRING, false);
128   // fill in the channel trace if applicable
129   grpc_json* trace_json = trace_.RenderJson();
130   if (trace_json != nullptr) {
131     trace_json->key = "trace";  // this object is named trace in channelz.proto
132     grpc_json_link_child(json, trace_json, nullptr);
133   }
134   // ask CallCountingHelper to populate trace and call count data.
135   call_counter_.PopulateCallCounts(json);
136   json = top_level_json;
137   // template method. Child classes may override this to add their specific
138   // functionality.
139   PopulateChildRefs(json);
140   return top_level_json;
141 }
142 
MakeChannelNode(grpc_channel * channel,size_t channel_tracer_max_nodes,bool is_top_level_channel)143 RefCountedPtr<ChannelNode> ChannelNode::MakeChannelNode(
144     grpc_channel* channel, size_t channel_tracer_max_nodes,
145     bool is_top_level_channel) {
146   return MakeRefCounted<grpc_core::channelz::ChannelNode>(
147       channel, channel_tracer_max_nodes, is_top_level_channel);
148 }
149 
ServerNode(size_t channel_tracer_max_nodes)150 ServerNode::ServerNode(size_t channel_tracer_max_nodes)
151     : BaseNode(EntityType::kServer), trace_(channel_tracer_max_nodes) {}
152 
~ServerNode()153 ServerNode::~ServerNode() {}
154 
RenderJson()155 grpc_json* ServerNode::RenderJson() {
156   // We need to track these three json objects to build our object
157   grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
158   grpc_json* json = top_level_json;
159   grpc_json* json_iterator = nullptr;
160   // create and fill the ref child
161   json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr,
162                                          GRPC_JSON_OBJECT, false);
163   json = json_iterator;
164   json_iterator = nullptr;
165   json_iterator = grpc_json_add_number_string_child(json, json_iterator,
166                                                     "serverId", uuid());
167   // reset json iterators to top level object
168   json = top_level_json;
169   json_iterator = nullptr;
170   // create and fill the data child.
171   grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr,
172                                            GRPC_JSON_OBJECT, false);
173   json = data;
174   json_iterator = nullptr;
175   // fill in the channel trace if applicable
176   grpc_json* trace_json = trace_.RenderJson();
177   if (trace_json != nullptr) {
178     trace_json->key = "trace";  // this object is named trace in channelz.proto
179     grpc_json_link_child(json, trace_json, nullptr);
180   }
181   // ask CallCountingHelper to populate trace and call count data.
182   call_counter_.PopulateCallCounts(json);
183   json = top_level_json;
184   return top_level_json;
185 }
186 
187 }  // namespace channelz
188 }  // namespace grpc_core
189