Home | History | Annotate | Download | only in channel
      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 
     74   EntityType type() const { return type_; }
     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();
     94   void RecordCallFailed() {
     95     gpr_atm_no_barrier_fetch_add(&calls_failed_, (gpr_atm(1)));
     96   }
     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.
    139   virtual void PopulateConnectivityState(grpc_json* json) {}
    140   virtual void PopulateChildRefs(grpc_json* json) {}
    141 
    142   void MarkChannelDestroyed() {
    143     GPR_ASSERT(channel_ != nullptr);
    144     channel_ = nullptr;
    145   }
    146 
    147   bool ChannelIsDestroyed() { return channel_ == nullptr; }
    148 
    149   // proxy methods to composed classes.
    150   void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) {
    151     trace_.AddTraceEvent(severity, data);
    152   }
    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   }
    159   void RecordCallStarted() { call_counter_.RecordCallStarted(); }
    160   void RecordCallFailed() { call_counter_.RecordCallFailed(); }
    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.
    181   void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) {
    182     trace_.AddTraceEvent(severity, data);
    183   }
    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   }
    190   void RecordCallStarted() { call_counter_.RecordCallStarted(); }
    191   void RecordCallFailed() { call_counter_.RecordCallFailed(); }
    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:
    203   SocketNode() : BaseNode(EntityType::kSocket) {}
    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