Home | History | Annotate | Download | only in channel
      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