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 #ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_H 20 #define GRPC_CORE_LIB_CHANNEL_CHANNELZ_H 21 22 #include <grpc/impl/codegen/port_platform.h> 23 24 #include <grpc/grpc.h> 25 26 #include "src/core/lib/channel/channel_trace.h" 27 #include "src/core/lib/gprpp/manual_constructor.h" 28 #include "src/core/lib/gprpp/ref_counted.h" 29 #include "src/core/lib/gprpp/ref_counted_ptr.h" 30 #include "src/core/lib/iomgr/error.h" 31 #include "src/core/lib/iomgr/exec_ctx.h" 32 #include "src/core/lib/json/json.h" 33 34 // Channel arg key for client channel factory. 35 #define GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC \ 36 "grpc.channelz_channel_node_creation_func" 37 38 // Channel arg key to signal that the channel is an internal channel. 39 #define GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL \ 40 "grpc.channelz_channel_is_internal_channel" 41 42 namespace grpc_core { 43 namespace channelz { 44 45 namespace testing { 46 class CallCountingHelperPeer; 47 class ChannelNodePeer; 48 } // namespace testing 49 50 // base class for all channelz entities 51 class BaseNode : public RefCounted<BaseNode> { 52 public: 53 // There are only four high level channelz entities. However, to support 54 // GetTopChannelsRequest, we split the Channel entity into two different 55 // types. All children of BaseNode must be one of these types. 56 enum class EntityType { 57 kTopLevelChannel, 58 kInternalChannel, 59 kSubchannel, 60 kServer, 61 kSocket, 62 }; 63 64 explicit BaseNode(EntityType type); 65 virtual ~BaseNode(); 66 67 // All children must implement this function. 68 virtual grpc_json* RenderJson() GRPC_ABSTRACT; 69 70 // Renders the json and returns allocated string that must be freed by the 71 // caller. 72 char* RenderJsonString(); 73 type()74 EntityType type() const { return type_; } uuid()75 intptr_t uuid() const { return uuid_; } 76 77 private: 78 const EntityType type_; 79 const intptr_t uuid_; 80 }; 81 82 // This class is a helper class for channelz entities that deal with Channels, 83 // Subchannels, and Servers, since those have similar proto definitions. 84 // This class has the ability to: 85 // - track calls_{started,succeeded,failed} 86 // - track last_call_started_timestamp 87 // - perform rendering of the above items 88 class CallCountingHelper { 89 public: 90 CallCountingHelper(); 91 ~CallCountingHelper(); 92 93 void RecordCallStarted(); RecordCallFailed()94 void RecordCallFailed() { 95 gpr_atm_no_barrier_fetch_add(&calls_failed_, (gpr_atm(1))); 96 } RecordCallSucceeded()97 void RecordCallSucceeded() { 98 gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); 99 } 100 101 // Common rendering of the call count data and last_call_started_timestamp. 102 void PopulateCallCounts(grpc_json* json); 103 104 private: 105 // testing peer friend. 106 friend class testing::CallCountingHelperPeer; 107 108 gpr_atm calls_started_ = 0; 109 gpr_atm calls_succeeded_ = 0; 110 gpr_atm calls_failed_ = 0; 111 gpr_atm last_call_started_millis_ = 0; 112 }; 113 114 // Handles channelz bookkeeping for channels 115 class ChannelNode : public BaseNode { 116 public: 117 static RefCountedPtr<ChannelNode> MakeChannelNode( 118 grpc_channel* channel, size_t channel_tracer_max_nodes, 119 bool is_top_level_channel); 120 121 ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, 122 bool is_top_level_channel); 123 ~ChannelNode() override; 124 125 grpc_json* RenderJson() override; 126 127 // template methods. RenderJSON uses these methods to render its JSON 128 // representation. These are virtual so that children classes may provide 129 // their specific mechanism for populating these parts of the channelz 130 // object. 131 // 132 // ChannelNode does not have a notion of connectivity state or child refs, 133 // so it leaves these implementations blank. 134 // 135 // This is utilizing the template method design pattern. 136 // 137 // TODO(ncteisen): remove these template methods in favor of manual traversal 138 // and mutation of the grpc_json object. PopulateConnectivityState(grpc_json * json)139 virtual void PopulateConnectivityState(grpc_json* json) {} PopulateChildRefs(grpc_json * json)140 virtual void PopulateChildRefs(grpc_json* json) {} 141 MarkChannelDestroyed()142 void MarkChannelDestroyed() { 143 GPR_ASSERT(channel_ != nullptr); 144 channel_ = nullptr; 145 } 146 ChannelIsDestroyed()147 bool ChannelIsDestroyed() { return channel_ == nullptr; } 148 149 // proxy methods to composed classes. AddTraceEvent(ChannelTrace::Severity severity,grpc_slice data)150 void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { 151 trace_.AddTraceEvent(severity, data); 152 } AddTraceEventWithReference(ChannelTrace::Severity severity,grpc_slice data,RefCountedPtr<BaseNode> referenced_channel)153 void AddTraceEventWithReference(ChannelTrace::Severity severity, 154 grpc_slice data, 155 RefCountedPtr<BaseNode> referenced_channel) { 156 trace_.AddTraceEventWithReference(severity, data, 157 std::move(referenced_channel)); 158 } RecordCallStarted()159 void RecordCallStarted() { call_counter_.RecordCallStarted(); } RecordCallFailed()160 void RecordCallFailed() { call_counter_.RecordCallFailed(); } RecordCallSucceeded()161 void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } 162 163 private: 164 // to allow the channel trace test to access trace_. 165 friend class testing::ChannelNodePeer; 166 grpc_channel* channel_ = nullptr; 167 UniquePtr<char> target_; 168 CallCountingHelper call_counter_; 169 ChannelTrace trace_; 170 }; 171 172 // Handles channelz bookkeeping for servers 173 class ServerNode : public BaseNode { 174 public: 175 explicit ServerNode(size_t channel_tracer_max_nodes); 176 ~ServerNode() override; 177 178 grpc_json* RenderJson() override; 179 180 // proxy methods to composed classes. AddTraceEvent(ChannelTrace::Severity severity,grpc_slice data)181 void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { 182 trace_.AddTraceEvent(severity, data); 183 } AddTraceEventWithReference(ChannelTrace::Severity severity,grpc_slice data,RefCountedPtr<BaseNode> referenced_channel)184 void AddTraceEventWithReference(ChannelTrace::Severity severity, 185 grpc_slice data, 186 RefCountedPtr<BaseNode> referenced_channel) { 187 trace_.AddTraceEventWithReference(severity, data, 188 std::move(referenced_channel)); 189 } RecordCallStarted()190 void RecordCallStarted() { call_counter_.RecordCallStarted(); } RecordCallFailed()191 void RecordCallFailed() { call_counter_.RecordCallFailed(); } RecordCallSucceeded()192 void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } 193 194 private: 195 CallCountingHelper call_counter_; 196 ChannelTrace trace_; 197 }; 198 199 // Handles channelz bookkeeping for sockets 200 // TODO(ncteisen): implement in subsequent PR. 201 class SocketNode : public BaseNode { 202 public: SocketNode()203 SocketNode() : BaseNode(EntityType::kSocket) {} ~SocketNode()204 ~SocketNode() override {} 205 }; 206 207 // Creation functions 208 209 typedef RefCountedPtr<ChannelNode> (*ChannelNodeCreationFunc)(grpc_channel*, 210 size_t, bool); 211 212 } // namespace channelz 213 } // namespace grpc_core 214 215 #endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_H */ 216