diff options
Diffstat (limited to 'src/core/lib/channel')
-rw-r--r-- | src/core/lib/channel/channel_trace.cc | 30 | ||||
-rw-r--r-- | src/core/lib/channel/channelz.cc | 142 | ||||
-rw-r--r-- | src/core/lib/channel/channelz.h | 131 | ||||
-rw-r--r-- | src/core/lib/channel/channelz_registry.cc | 16 |
4 files changed, 222 insertions, 97 deletions
diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index b3443310ac..dd6fdeed54 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -178,24 +178,26 @@ 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); - char* num_events_logged_str; - gpr_asprintf(&num_events_logged_str, "%" PRId64, num_events_logged_); grpc_json* json_iterator = nullptr; - json_iterator = - grpc_json_create_child(json_iterator, json, "numEventsLogged", - num_events_logged_str, GRPC_JSON_STRING, true); + if (num_events_logged_ > 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "numEventsLogged", num_events_logged_); + } json_iterator = grpc_json_create_child( json_iterator, json, "creationTimestamp", gpr_format_timespec(time_created_), GRPC_JSON_STRING, true); - grpc_json* events = grpc_json_create_child(json_iterator, json, "events", - nullptr, GRPC_JSON_ARRAY, false); - json_iterator = nullptr; - TraceEvent* it = head_trace_; - while (it != nullptr) { - json_iterator = grpc_json_create_child(json_iterator, events, nullptr, - nullptr, GRPC_JSON_OBJECT, false); - it->RenderTraceEvent(json_iterator); - it = it->next(); + // only add in the event list if it is non-empty. + if (num_events_logged_ > 0) { + grpc_json* events = grpc_json_create_child(json_iterator, json, "events", + nullptr, GRPC_JSON_ARRAY, false); + json_iterator = nullptr; + TraceEvent* it = head_trace_; + while (it != nullptr) { + json_iterator = grpc_json_create_child(json_iterator, events, nullptr, + nullptr, GRPC_JSON_OBJECT, false); + it->RenderTraceEvent(json_iterator); + it = it->next(); + } } return json; } diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 9d6002ed8a..7fe086da3c 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,69 +41,33 @@ namespace grpc_core { namespace channelz { -ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel) - : channel_(channel), - target_(nullptr), - channel_uuid_(-1), - is_top_level_channel_(is_top_level_channel) { +CallCountingBase::CallCountingBase(size_t channel_tracer_max_nodes) { trace_.Init(channel_tracer_max_nodes); - target_ = UniquePtr<char>(grpc_channel_get_target(channel_)); - channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -ChannelNode::~ChannelNode() { - trace_.Destroy(); - ChannelzRegistry::UnregisterChannelNode(channel_uuid_); -} +CallCountingBase::~CallCountingBase() { trace_.Destroy(); } -void ChannelNode::RecordCallStarted() { +void CallCountingBase::RecordCallStarted() { gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -void ChannelNode::PopulateConnectivityState(grpc_json* json) {} - -void ChannelNode::PopulateChildRefs(grpc_json* json) {} - -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; - grpc_json* json_iterator = nullptr; - // create and fill the ref child - json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, - GRPC_JSON_OBJECT, false); - json = json_iterator; - json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child(json, json_iterator, - "channelId", channel_uuid_); - // reset json iterators to top level object - json = top_level_json; - json_iterator = nullptr; - // create and fill the data child. - grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, - GRPC_JSON_OBJECT, false); - 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); +void CallCountingBase::PopulateTrace(grpc_json* json) { // fill in the channel trace if applicable - grpc_json* trace = trace_->RenderJson(); - if (trace != nullptr) { + grpc_json* trace_json = trace_->RenderJson(); + if (trace_json != nullptr) { // we manually link up and fill the child since it was created for us in // ChannelTrace::RenderJson - trace->key = "trace"; // this object is named trace in channelz.proto - json_iterator = grpc_json_link_child(json, trace, json_iterator); + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); } - // reset the parent to be the data object. - json = data; - json_iterator = nullptr; +} + +void CallCountingBase::PopulateCallData(grpc_json* json) { + grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( json, json_iterator, "callsStarted", calls_started_); @@ -121,19 +85,62 @@ grpc_json* ChannelNode::RenderJson() { json_iterator = grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp", gpr_format_timespec(ts), GRPC_JSON_STRING, true); - json = top_level_json; - json_iterator = nullptr; - PopulateChildRefs(json); - return top_level_json; } -char* ChannelNode::RenderJsonString() { +char* CallCountingBase::RenderJsonString() { grpc_json* json = RenderJson(); char* json_str = grpc_json_dump_to_string(json, 0); grpc_json_destroy(json); return json_str; } +ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel) + : CallCountingBase(channel_tracer_max_nodes), + channel_(channel), + is_top_level_channel_(is_top_level_channel) { + target_ = UniquePtr<char>(grpc_channel_get_target(channel_)); + channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); +} + +ChannelNode::~ChannelNode() { + ChannelzRegistry::UnregisterChannelNode(channel_uuid_); +} + +void ChannelNode::PopulateTarget(grpc_json* json) { + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); +} + +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; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "channelId", channel_uuid_); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + PopulateTarget(json); + PopulateTrace(json); + PopulateCallData(json); + PopulateChildRefs(json); + return top_level_json; +} + RefCountedPtr<ChannelNode> ChannelNode::MakeChannelNode( grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel) { @@ -141,7 +148,8 @@ RefCountedPtr<ChannelNode> ChannelNode::MakeChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } -SubchannelNode::SubchannelNode() { +SubchannelNode::SubchannelNode(size_t channel_tracer_max_nodes) + : CallCountingBase(channel_tracer_max_nodes) { subchannel_uuid_ = ChannelzRegistry::RegisterSubchannelNode(this); } @@ -149,5 +157,31 @@ SubchannelNode::~SubchannelNode() { ChannelzRegistry::UnregisterSubchannelNode(subchannel_uuid_); } +grpc_json* SubchannelNode::RenderJson() { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "subchannelId", subchannel_uuid_); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + PopulateTarget(json); + PopulateTrace(json); + PopulateCallData(json); + PopulateChildRefs(json); + return top_level_json; +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 07eb73d626..97e27c69fc 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -46,11 +46,44 @@ namespace testing { class ChannelNodePeer; } -class ChannelNode : public RefCounted<ChannelNode> { +// base class for all channelz entities +class ChannelzBaseNode : public RefCounted<ChannelzBaseNode> { public: - static RefCountedPtr<ChannelNode> MakeChannelNode( - grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel); + ChannelzBaseNode() {} + virtual ~ChannelzBaseNode() {} + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; + +// Handles channelz bookkeeping for sockets +// TODO(ncteisen): implement in subsequent PR. +class SocketNode : public ChannelzBaseNode { + public: + SocketNode() : ChannelzBaseNode() {} + ~SocketNode() override {} + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; + +// This class is the parent for the channelz entities that deal with Channels +// Subchannels, and Servers, since those have similar proto definitions. +// This class has the ability to: +// - track calls_{started,succeeded,failed} +// - track last_call_started_timestamp +// - hold the channel trace. +// - perform common rendering. +// +// This class also defines some fat interfaces so that its children can +// implement the functionality different. For example, querying the +// connectivity state looks different for channels and subchannels, and does +// not make sense for servers. So servers will not override, and channels and +// subchannels will override with their own way to query connectivity state. +class CallCountingBase : public ChannelzBaseNode { + public: + CallCountingBase(size_t channel_tracer_max_nodes); + ~CallCountingBase() override; void RecordCallStarted(); void RecordCallFailed() { @@ -59,66 +92,106 @@ class ChannelNode : public RefCounted<ChannelNode> { void RecordCallSucceeded() { gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); } + ChannelTrace* trace() { return trace_.get(); } + + // Fat interface for ConnectivityState. Default is to leave it out, however, + // things like Channel and Subchannel will override with their mechanism + // for querying connectivity state. + virtual void PopulateConnectivityState(grpc_json* json) {} + + // Fat interface for Targets. + virtual void PopulateTarget(grpc_json* json) {} + + // Fat interface for ChildRefs. Allows children to populate with whatever + // combination of child_refs, subchannel_refs, and socket_refs is correct. + virtual void PopulateChildRefs(grpc_json* json) {} - grpc_json* RenderJson(); + // All children must implement their custom JSON rendering. + virtual grpc_json* RenderJson() GRPC_ABSTRACT; + + // Common rendering of the channel trace. + void PopulateTrace(grpc_json* json); + + // Common rendering of the call count data and last_call_started_timestamp. + void PopulateCallData(grpc_json* json); + + // Common rendering of grpc_json from RenderJson() to allocated string. char* RenderJsonString(); - // helper for getting and populating connectivity state. It is virtual - // because it allows the client_channel specific code to live in ext/ - // instead of lib/ - virtual void PopulateConnectivityState(grpc_json* json); + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - virtual void PopulateChildRefs(grpc_json* json); + gpr_atm calls_started_ = 0; + gpr_atm calls_succeeded_ = 0; + gpr_atm calls_failed_ = 0; + gpr_atm last_call_started_millis_ = 0; + ManualConstructor<ChannelTrace> trace_; +}; - ChannelTrace* trace() { return trace_.get(); } +// Handles channelz bookkeeping for servers +// TODO(ncteisen): implement in subsequent PR. +class ServerNode : public CallCountingBase { + public: + ServerNode(size_t channel_tracer_max_nodes) + : CallCountingBase(channel_tracer_max_nodes) {} + ~ServerNode() override {} + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; + +// Overrides Channel specific functionality. +class ChannelNode : public CallCountingBase { + public: + static RefCountedPtr<ChannelNode> MakeChannelNode( + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); void MarkChannelDestroyed() { GPR_ASSERT(channel_ != nullptr); channel_ = nullptr; } + grpc_json* RenderJson() override; + + void PopulateTarget(grpc_json* json) override; + bool ChannelIsDestroyed() { return channel_ == nullptr; } intptr_t channel_uuid() { return channel_uuid_; } bool is_top_level_channel() { return is_top_level_channel_; } protected: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); - virtual ~ChannelNode(); + ~ChannelNode() override; private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + // testing peer friend. friend class testing::ChannelNodePeer; grpc_channel* channel_ = nullptr; UniquePtr<char> target_; - gpr_atm calls_started_ = 0; - gpr_atm calls_succeeded_ = 0; - 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_; }; -// Placeholds channelz class for subchannels. All this can do now is track its -// uuid (this information is needed by the parent channelz class). -// TODO(ncteisen): build this out to support the GetSubchannel channelz request. -class SubchannelNode : public RefCounted<SubchannelNode> { +// Overrides Subchannel specific functionality. +class SubchannelNode : public CallCountingBase { public: - SubchannelNode(); - virtual ~SubchannelNode(); - + SubchannelNode(size_t channel_tracer_max_nodes); + ~SubchannelNode() override; + grpc_json* RenderJson() override; intptr_t subchannel_uuid() { return subchannel_uuid_; } - protected: + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - - private: + intptr_t subchannel_uuid_; }; diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 38496b3d78..aeeb6958e4 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -142,3 +142,19 @@ char* grpc_channelz_get_channel(intptr_t channel_id) { grpc_json_destroy(top_level_json); return json_str; } + +char* grpc_channelz_get_subchannel(intptr_t subchannel_id) { + grpc_core::channelz::SubchannelNode* subchannel_node = + grpc_core::channelz::ChannelzRegistry::GetSubchannelNode(subchannel_id); + if (subchannel_node == nullptr) { + return nullptr; + } + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* subchannel_json = subchannel_node->RenderJson(); + subchannel_json->key = "subchannel"; + grpc_json_link_child(json, subchannel_json, nullptr); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} |