diff options
Diffstat (limited to 'src/core/lib')
-rw-r--r-- | src/core/lib/channel/channel_trace.cc | 2 | ||||
-rw-r--r-- | src/core/lib/channel/channel_trace.h | 2 | ||||
-rw-r--r-- | src/core/lib/channel/channelz.cc | 37 | ||||
-rw-r--r-- | src/core/lib/channel/channelz.h | 12 | ||||
-rw-r--r-- | src/core/lib/channel/channelz_registry.cc | 45 | ||||
-rw-r--r-- | src/core/lib/channel/channelz_registry.h | 7 | ||||
-rw-r--r-- | src/core/lib/surface/channel.cc | 7 |
7 files changed, 95 insertions, 17 deletions
diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index 0f655d8716..5a4cf8c7e1 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -206,7 +206,7 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { } } -grpc_json* ChannelTrace::RenderJSON() const { +grpc_json* ChannelTrace::RenderJson() const { if (!max_list_size_) return nullptr; // tracing is disabled if max_events == 0 grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT); diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index 0dd162a777..596af7402f 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -71,7 +71,7 @@ class ChannelTrace { // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. - grpc_json* RenderJSON() const; + grpc_json* RenderJson() const; private: // Types of objects that can be references by trace events. diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 923b8043cd..c8a1d179fa 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -110,7 +110,7 @@ void ChannelNode::RecordCallStarted() { void ChannelNode::PopulateConnectivityState(grpc_json* json) {} -char* ChannelNode::RenderJSON() { +grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; @@ -130,13 +130,14 @@ char* ChannelNode::RenderJSON() { json = data; json_iterator = nullptr; PopulateConnectivityState(json); + GPR_ASSERT(target_.get() != nullptr); json_iterator = grpc_json_create_child( json_iterator, json, "target", target_.get(), GRPC_JSON_STRING, false); // fill in the channel trace if applicable - grpc_json* trace = trace_->RenderJSON(); + grpc_json* trace = trace_->RenderJson(); if (trace != nullptr) { // we manuall link up and fill the child since it was created for us in - // ChannelTrace::RenderJSON + // ChannelTrace::RenderJson json_iterator = grpc_json_link_child(json, trace, json_iterator); trace->parent = json; trace->value = nullptr; @@ -146,22 +147,30 @@ char* ChannelNode::RenderJSON() { // reset the parent to be the data object. json = data; json_iterator = nullptr; - // We use -1 as sentinel values since proto default value for integers is - // zero, and the confuses the parser into thinking the value weren't present - json_iterator = - add_num_str(json, json_iterator, "callsStarted", calls_started_); - json_iterator = - add_num_str(json, json_iterator, "callsSucceeded", calls_succeeded_); - json_iterator = - add_num_str(json, json_iterator, "callsFailed", calls_failed_); + if (calls_started_ != 0) { + json_iterator = + add_num_str(json, json_iterator, "callsStarted", calls_started_); + } + if (calls_succeeded_ != 0) { + json_iterator = + add_num_str(json, json_iterator, "callsSucceeded", calls_succeeded_); + } + if (calls_failed_) { + json_iterator = + add_num_str(json, json_iterator, "callsFailed", calls_failed_); + } gpr_timespec ts = grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME); json_iterator = grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp", fmt_time(ts), GRPC_JSON_STRING, true); - // render and return the over json object - char* json_str = grpc_json_dump_to_string(top_level_json, 0); - grpc_json_destroy(top_level_json); + return top_level_json; +} + +char* ChannelNode::RenderJsonString() { + grpc_json* json = RenderJson(); + char* json_str = grpc_json_dump_to_string(json, 0); + grpc_json_destroy(json); return json_str; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 9bd01ece50..abcf907c2b 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -35,6 +35,10 @@ #define GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC \ "grpc.channelz_channel_node_creation_func" +// Channel arg key to signal that the channel is an internal channel. +#define GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL \ + "grpc.channelz_channel_is_internal_channel" + namespace grpc_core { namespace channelz { @@ -55,7 +59,8 @@ class ChannelNode : public RefCounted<ChannelNode> { gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); } - char* RenderJSON(); + grpc_json* RenderJson(); + char* RenderJsonString(); // helper for getting and populating connectivity state. It is virtual // because it allows the client_channel specific code to live in ext/ @@ -72,6 +77,10 @@ class ChannelNode : public RefCounted<ChannelNode> { bool ChannelIsDestroyed() { return channel_ == nullptr; } intptr_t channel_uuid() { return channel_uuid_; } + bool is_top_level_channel() { return is_top_level_channel_; } + void set_is_top_level_channel(bool is_top_level_channel) { + is_top_level_channel_ = is_top_level_channel; + } protected: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE @@ -90,6 +99,7 @@ class ChannelNode : public RefCounted<ChannelNode> { gpr_atm calls_failed_ = 0; gpr_atm last_call_started_millis_ = 0; intptr_t channel_uuid_; + bool is_top_level_channel_ = true; ManualConstructor<ChannelTrace> trace_; }; diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 43cace1975..b4dc3d1103 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -19,6 +19,7 @@ #include <grpc/impl/codegen/port_platform.h> #include "src/core/lib/channel/channel_trace.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/memory.h" @@ -64,6 +65,7 @@ void ChannelzRegistry::InternalUnregisterEntry(intptr_t uuid, EntityType type) { GPR_ASSERT(static_cast<size_t>(uuid) <= entities_.size()); GPR_ASSERT(entities_[uuid - 1].type == type); entities_[uuid - 1].object = nullptr; + entities_[uuid - 1].type = EntityType::kUnset; } void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) { @@ -78,5 +80,48 @@ void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) { } } +char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + InlinedVector<ChannelNode*, 10> top_level_channels; + // uuids index into entities one-off (idx 0 is really uuid 1, since 0 is + // reserver). However, we want to support requests coming in which + // start_channel_id=0, which signifies "give me everything." Hence this + // funky looking line below. + size_t start_idx = start_channel_id == 0 ? 0 : start_channel_id - 1; + for (size_t i = start_idx; i < entities_.size(); ++i) { + if (entities_[i].type == EntityType::kChannelNode) { + ChannelNode* channel_node = + static_cast<ChannelNode*>(entities_[i].object); + if (channel_node->is_top_level_channel()) { + top_level_channels.push_back(channel_node); + } + } + } + if (top_level_channels.size() > 0) { + // create list of channels + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "channel", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < top_level_channels.size(); ++i) { + grpc_json* channel_json = top_level_channels[i]->RenderJson(); + json_iterator = + grpc_json_link_child(array_parent, channel_json, json_iterator); + channel_json->parent = array_parent; + channel_json->value = nullptr; + channel_json->key = nullptr; + channel_json->owns_value = false; + } + } + // For now we do not have any pagination rules. In the future we could + // pick a constant for max_channels_sent for a GetTopChannels request. + // Tracking: https://github.com/grpc/grpc/issues/16019. + json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, + GRPC_JSON_TRUE, false); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h index cc069d9145..2fefc9f629 100644 --- a/src/core/lib/channel/channelz_registry.h +++ b/src/core/lib/channel/channelz_registry.h @@ -51,6 +51,11 @@ class ChannelzRegistry { return gotten == nullptr ? nullptr : static_cast<ChannelNode*>(gotten); } + // todo, protect me + static char* GetTopChannels(intptr_t start_channel_id) { + return Default()->InternalGetTopChannels(start_channel_id); + } + private: enum class EntityType { kChannelNode, @@ -84,6 +89,8 @@ class ChannelzRegistry { // returns the void* associated with that uuid. Else returns nullptr. void* InternalGetEntry(intptr_t uuid, EntityType type); + char* InternalGetTopChannels(intptr_t start_channel_id); + // protects entities_ and uuid_ gpr_mu mu_; InlinedVector<RegistryEntry, 20> entities_; diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 8f3ad6c191..dd3880f18e 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -105,6 +105,7 @@ grpc_channel* grpc_channel_create_with_builder( channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type); size_t channel_tracer_max_nodes = 0; // default to off bool channelz_enabled = false; + bool internal_channel = false; // this creates the default ChannelNode. Different types of channels may // override this to ensure a correct ChannelNode is created. grpc_core::channelz::ChannelNodeCreationFunc channel_node_create_func = @@ -158,6 +159,9 @@ grpc_channel* grpc_channel_create_with_builder( channel_node_create_func = reinterpret_cast<grpc_core::channelz::ChannelNodeCreationFunc>( args->args[i].value.pointer.p); + } else if (0 == strcmp(args->args[i].key, + GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL)) { + internal_channel = grpc_channel_arg_get_bool(&args->args[i], false); } } @@ -165,6 +169,9 @@ grpc_channel* grpc_channel_create_with_builder( if (channelz_enabled) { channel->channelz_channel = channel_node_create_func(channel, channel_tracer_max_nodes); + if (internal_channel || !channel->is_client) { + channel->channelz_channel->set_is_top_level_channel(false); + } channel->channelz_channel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); |