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 44 BaseNode::BaseNode(EntityType type) 45 : type_(type), uuid_(ChannelzRegistry::Register(this)) {} 46 47 BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); } 48 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 57 CallCountingHelper::CallCountingHelper() { 58 gpr_atm_no_barrier_store(&last_call_started_millis_, 59 (gpr_atm)ExecCtx::Get()->Now()); 60 } 61 62 CallCountingHelper::~CallCountingHelper() {} 63 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 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 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 99 ChannelNode::~ChannelNode() {} 100 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 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 150 ServerNode::ServerNode(size_t channel_tracer_max_nodes) 151 : BaseNode(EntityType::kServer), trace_(channel_tracer_max_nodes) {} 152 153 ServerNode::~ServerNode() {} 154 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