aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/channel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lib/channel')
-rw-r--r--src/core/lib/channel/channel_trace.cc73
-rw-r--r--src/core/lib/channel/channel_trace.h28
-rw-r--r--src/core/lib/channel/channelz.cc119
-rw-r--r--src/core/lib/channel/channelz.h154
-rw-r--r--src/core/lib/channel/channelz_registry.cc60
-rw-r--r--src/core/lib/channel/channelz_registry.h50
6 files changed, 252 insertions, 232 deletions
diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc
index b3443310ac..cfb2faba51 100644
--- a/src/core/lib/channel/channel_trace.cc
+++ b/src/core/lib/channel/channel_trace.cc
@@ -41,16 +41,14 @@
namespace grpc_core {
namespace channelz {
-ChannelTrace::TraceEvent::TraceEvent(
- Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_channel, ReferencedType type)
+ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data,
+ RefCountedPtr<BaseNode> referenced_entity)
: severity_(severity),
data_(data),
timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(),
GPR_CLOCK_REALTIME)),
next_(nullptr),
- referenced_channel_(std::move(referenced_channel)),
- referenced_type_(type) {}
+ referenced_entity_(std::move(referenced_entity)) {}
ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data)
: severity_(severity),
@@ -110,23 +108,13 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) {
AddTraceEventHelper(New<TraceEvent>(severity, data));
}
-void ChannelTrace::AddTraceEventReferencingChannel(
- Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_channel) {
- if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
- // create and fill up the new event
- AddTraceEventHelper(New<TraceEvent>(
- severity, data, std::move(referenced_channel), ReferencedType::Channel));
-}
-
-void ChannelTrace::AddTraceEventReferencingSubchannel(
+void ChannelTrace::AddTraceEventWithReference(
Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_subchannel) {
+ RefCountedPtr<BaseNode> referenced_entity) {
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
// create and fill up the new event
- AddTraceEventHelper(New<TraceEvent>(severity, data,
- std::move(referenced_subchannel),
- ReferencedType::Subchannel));
+ AddTraceEventHelper(
+ New<TraceEvent>(severity, data, std::move(referenced_entity)));
}
namespace {
@@ -157,19 +145,18 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const {
json_iterator = grpc_json_create_child(json_iterator, json, "timestamp",
gpr_format_timespec(timestamp_),
GRPC_JSON_STRING, true);
- if (referenced_channel_ != nullptr) {
+ if (referenced_entity_ != nullptr) {
+ const bool is_channel =
+ (referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel ||
+ referenced_entity_->type() == BaseNode::EntityType::kInternalChannel);
char* uuid_str;
- gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->channel_uuid());
+ gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid());
grpc_json* child_ref = grpc_json_create_child(
- json_iterator, json,
- (referenced_type_ == ReferencedType::Channel) ? "channelRef"
- : "subchannelRef",
+ json_iterator, json, is_channel ? "channelRef" : "subchannelRef",
nullptr, GRPC_JSON_OBJECT, false);
json_iterator = grpc_json_create_child(
- nullptr, child_ref,
- (referenced_type_ == ReferencedType::Channel) ? "channelId"
- : "subchannelId",
- uuid_str, GRPC_JSON_STRING, true);
+ nullptr, child_ref, is_channel ? "channelId" : "subchannelId", uuid_str,
+ GRPC_JSON_STRING, true);
json_iterator = child_ref;
}
}
@@ -178,24 +165,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/channel_trace.h b/src/core/lib/channel/channel_trace.h
index 596af7402f..230faa483e 100644
--- a/src/core/lib/channel/channel_trace.h
+++ b/src/core/lib/channel/channel_trace.h
@@ -30,7 +30,7 @@
namespace grpc_core {
namespace channelz {
-class ChannelNode;
+class BaseNode;
// Object used to hold live data for a channel. This data is exposed via the
// channelz service:
@@ -55,35 +55,28 @@ class ChannelTrace {
void AddTraceEvent(Severity severity, grpc_slice data);
// Adds a new trace event to the tracing object. This trace event refers to a
- // an event on a child of the channel. For example, if this channel has
- // created a new subchannel, then it would record that with a TraceEvent
- // referencing the new subchannel.
+ // an event that concerns a different channelz entity. For example, if this
+ // channel has created a new subchannel, then it would record that with
+ // a TraceEvent referencing the new subchannel.
//
// TODO(ncteisen): as this call is used more and more throughout the gRPC
// stack, determine if it makes more sense to accept a char* instead of a
// slice.
- void AddTraceEventReferencingChannel(
- Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_channel);
- void AddTraceEventReferencingSubchannel(
- Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_subchannel);
+ void AddTraceEventWithReference(Severity severity, grpc_slice data,
+ RefCountedPtr<BaseNode> referenced_channel);
// Creates and returns the raw grpc_json object, so a parent channelz
// object may incorporate the json before rendering.
grpc_json* RenderJson() const;
private:
- // Types of objects that can be references by trace events.
- enum class ReferencedType { Channel, Subchannel };
// Private class to encapsulate all the data and bookkeeping needed for a
// a trace event.
class TraceEvent {
public:
- // Constructor for a TraceEvent that references a different channel.
+ // Constructor for a TraceEvent that references a channel.
TraceEvent(Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_channel,
- ReferencedType type);
+ RefCountedPtr<BaseNode> referenced_entity_);
// Constructor for a TraceEvent that does not reverence a different
// channel.
@@ -105,10 +98,7 @@ class ChannelTrace {
gpr_timespec timestamp_;
TraceEvent* next_;
// the tracer object for the (sub)channel that this trace event refers to.
- RefCountedPtr<ChannelNode> referenced_channel_;
- // the type that the referenced tracer points to. Unused if this trace
- // does not point to any channel or subchannel
- ReferencedType referenced_type_;
+ RefCountedPtr<BaseNode> referenced_entity_;
}; // TraceEvent
// Internal helper to add and link in a trace event
diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc
index 9d6002ed8a..9f54850002 100644
--- a/src/core/lib/channel/channelz.cc
+++ b/src/core/lib/channel/channelz.cc
@@ -41,33 +41,61 @@
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) {
- trace_.Init(channel_tracer_max_nodes);
- target_ = UniquePtr<char>(grpc_channel_get_target(channel_));
- channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this);
+BaseNode::BaseNode(EntityType type)
+ : type_(type), uuid_(ChannelzRegistry::Register(this)) {}
+
+BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); }
+
+char* BaseNode::RenderJsonString() {
+ grpc_json* json = RenderJson();
+ char* json_str = grpc_json_dump_to_string(json, 0);
+ grpc_json_destroy(json);
+ return json_str;
+}
+
+CallCountingHelper::CallCountingHelper() {
gpr_atm_no_barrier_store(&last_call_started_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
-ChannelNode::~ChannelNode() {
- trace_.Destroy();
- ChannelzRegistry::UnregisterChannelNode(channel_uuid_);
-}
+CallCountingHelper::~CallCountingHelper() {}
-void ChannelNode::RecordCallStarted() {
+void CallCountingHelper::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 CallCountingHelper::PopulateCallCounts(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_);
+ }
+ if (calls_succeeded_ != 0) {
+ json_iterator = grpc_json_add_number_string_child(
+ json, json_iterator, "callsSucceeded", calls_succeeded_);
+ }
+ if (calls_failed_) {
+ json_iterator = grpc_json_add_number_string_child(
+ 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",
+ gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+}
-void ChannelNode::PopulateChildRefs(grpc_json* json) {}
+ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
+ bool is_top_level_channel)
+ : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel
+ : EntityType::kInternalChannel),
+ channel_(channel),
+ target_(UniquePtr<char>(grpc_channel_get_target(channel_))),
+ trace_(channel_tracer_max_nodes) {}
+
+ChannelNode::~ChannelNode() {}
grpc_json* ChannelNode::RenderJson() {
// We need to track these three json objects to build our object
@@ -80,7 +108,7 @@ grpc_json* ChannelNode::RenderJson() {
json = json_iterator;
json_iterator = nullptr;
json_iterator = grpc_json_add_number_string_child(json, json_iterator,
- "channelId", channel_uuid_);
+ "channelId", uuid());
// reset json iterators to top level object
json = top_level_json;
json_iterator = nullptr;
@@ -89,51 +117,28 @@ grpc_json* ChannelNode::RenderJson() {
GRPC_JSON_OBJECT, false);
json = data;
json_iterator = nullptr;
+ // template method. Child classes may override this to add their specific
+ // functionality.
PopulateConnectivityState(json);
+ // populate the target.
GPR_ASSERT(target_.get() != nullptr);
- json_iterator = grpc_json_create_child(
- json_iterator, json, "target", target_.get(), GRPC_JSON_STRING, false);
+ grpc_json_create_child(nullptr, json, "target", target_.get(),
+ GRPC_JSON_STRING, false);
// fill in the channel trace if applicable
- grpc_json* trace = trace_->RenderJson();
- if (trace != 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);
- }
- // reset the parent to be the data object.
- json = data;
- json_iterator = nullptr;
- if (calls_started_ != 0) {
- json_iterator = grpc_json_add_number_string_child(
- json, json_iterator, "callsStarted", calls_started_);
- }
- if (calls_succeeded_ != 0) {
- json_iterator = grpc_json_add_number_string_child(
- json, json_iterator, "callsSucceeded", calls_succeeded_);
- }
- if (calls_failed_) {
- json_iterator = grpc_json_add_number_string_child(
- json, json_iterator, "callsFailed", calls_failed_);
+ grpc_json* trace_json = trace_.RenderJson();
+ if (trace_json != nullptr) {
+ trace_json->key = "trace"; // this object is named trace in channelz.proto
+ grpc_json_link_child(json, trace_json, nullptr);
}
- gpr_timespec ts =
- grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME);
- json_iterator =
- grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
- gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+ // ask CallCountingHelper to populate trace and call count data.
+ call_counter_.PopulateCallCounts(json);
json = top_level_json;
- json_iterator = nullptr;
+ // template method. Child classes may override this to add their specific
+ // functionality.
PopulateChildRefs(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;
-}
-
RefCountedPtr<ChannelNode> ChannelNode::MakeChannelNode(
grpc_channel* channel, size_t channel_tracer_max_nodes,
bool is_top_level_channel) {
@@ -141,13 +146,5 @@ RefCountedPtr<ChannelNode> ChannelNode::MakeChannelNode(
channel, channel_tracer_max_nodes, is_top_level_channel);
}
-SubchannelNode::SubchannelNode() {
- subchannel_uuid_ = ChannelzRegistry::RegisterSubchannelNode(this);
-}
-
-SubchannelNode::~SubchannelNode() {
- ChannelzRegistry::UnregisterSubchannelNode(subchannel_uuid_);
-}
-
} // namespace channelz
} // namespace grpc_core
diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h
index 07eb73d626..db5d05140d 100644
--- a/src/core/lib/channel/channelz.h
+++ b/src/core/lib/channel/channelz.h
@@ -43,14 +43,52 @@ namespace grpc_core {
namespace channelz {
namespace testing {
+class CallCountingHelperPeer;
class ChannelNodePeer;
-}
+} // namespace testing
-class ChannelNode : public RefCounted<ChannelNode> {
+// base class for all channelz entities
+class BaseNode : public RefCounted<BaseNode> {
public:
- static RefCountedPtr<ChannelNode> MakeChannelNode(
- grpc_channel* channel, size_t channel_tracer_max_nodes,
- bool is_top_level_channel);
+ // There are only four high level channelz entities. However, to support
+ // GetTopChannelsRequest, we split the Channel entity into two different
+ // types. All children of BaseNode must be one of these types.
+ enum class EntityType {
+ kTopLevelChannel,
+ kInternalChannel,
+ kSubchannel,
+ kServer,
+ kSocket,
+ };
+
+ explicit BaseNode(EntityType type);
+ virtual ~BaseNode();
+
+ // All children must implement this function.
+ virtual grpc_json* RenderJson() GRPC_ABSTRACT;
+
+ // Renders the json and returns allocated string that must be freed by the
+ // caller.
+ char* RenderJsonString();
+
+ EntityType type() const { return type_; }
+ intptr_t uuid() const { return uuid_; }
+
+ private:
+ const EntityType type_;
+ const intptr_t uuid_;
+};
+
+// This class is a helper class for 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
+// - perform rendering of the above items
+class CallCountingHelper {
+ public:
+ CallCountingHelper();
+ ~CallCountingHelper();
void RecordCallStarted();
void RecordCallFailed() {
@@ -60,17 +98,46 @@ class ChannelNode : public RefCounted<ChannelNode> {
gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1)));
}
- grpc_json* RenderJson();
- char* RenderJsonString();
+ // Common rendering of the call count data and last_call_started_timestamp.
+ void PopulateCallCounts(grpc_json* json);
- // 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:
+ // testing peer friend.
+ friend class testing::CallCountingHelperPeer;
- 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;
+};
- ChannelTrace* trace() { return trace_.get(); }
+// Handles channelz bookkeeping for channels
+class ChannelNode : public BaseNode {
+ public:
+ static RefCountedPtr<ChannelNode> MakeChannelNode(
+ grpc_channel* channel, size_t channel_tracer_max_nodes,
+ bool is_top_level_channel);
+
+ ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
+ bool is_top_level_channel);
+ ~ChannelNode() override;
+
+ grpc_json* RenderJson() override;
+
+ // template methods. RenderJSON uses these methods to render its JSON
+ // representation. These are virtual so that children classes may provide
+ // their specific mechanism for populating these parts of the channelz
+ // object.
+ //
+ // ChannelNode does not have a notion of connectivity state or child refs,
+ // so it leaves these implementations blank.
+ //
+ // This is utilizing the template method design pattern.
+ //
+ // TODO(ncteisen): remove these template methods in favor of manual traversal
+ // and mutation of the grpc_json object.
+ virtual void PopulateConnectivityState(grpc_json* json) {}
+ virtual void PopulateChildRefs(grpc_json* json) {}
void MarkChannelDestroyed() {
GPR_ASSERT(channel_ != nullptr);
@@ -79,47 +146,44 @@ 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_; }
-
- 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();
+ // proxy methods to composed classes.
+ void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) {
+ trace_.AddTraceEvent(severity, data);
+ }
+ void AddTraceEventWithReference(ChannelTrace::Severity severity,
+ grpc_slice data,
+ RefCountedPtr<BaseNode> referenced_channel) {
+ trace_.AddTraceEventWithReference(severity, data,
+ std::move(referenced_channel));
+ }
+ void RecordCallStarted() { call_counter_.RecordCallStarted(); }
+ void RecordCallFailed() { call_counter_.RecordCallFailed(); }
+ void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
private:
- // testing peer friend.
+ // to allow the channel trace test to access trace_.
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_;
+ CallCountingHelper call_counter_;
+ 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> {
+// Handles channelz bookkeeping for servers
+// TODO(ncteisen): implement in subsequent PR.
+class ServerNode : public BaseNode {
public:
- SubchannelNode();
- virtual ~SubchannelNode();
-
- intptr_t subchannel_uuid() { return subchannel_uuid_; }
-
- protected:
- GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
- GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW
+ explicit ServerNode(size_t channel_tracer_max_nodes)
+ : BaseNode(EntityType::kServer) {}
+ ~ServerNode() override {}
+};
- private:
- intptr_t subchannel_uuid_;
+// Handles channelz bookkeeping for sockets
+// TODO(ncteisen): implement in subsequent PR.
+class SocketNode : public BaseNode {
+ public:
+ SocketNode() : BaseNode(EntityType::kSocket) {}
+ ~SocketNode() override {}
};
// Creation functions
diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc
index f79d2f0c17..972c61c1d6 100644
--- a/src/core/lib/channel/channelz_registry.cc
+++ b/src/core/lib/channel/channelz_registry.cc
@@ -53,54 +53,46 @@ ChannelzRegistry::ChannelzRegistry() { gpr_mu_init(&mu_); }
ChannelzRegistry::~ChannelzRegistry() { gpr_mu_destroy(&mu_); }
-intptr_t ChannelzRegistry::InternalRegisterEntry(const RegistryEntry& entry) {
+intptr_t ChannelzRegistry::InternalRegister(BaseNode* node) {
MutexLock lock(&mu_);
- entities_.push_back(entry);
+ entities_.push_back(node);
intptr_t uuid = entities_.size();
return uuid;
}
-void ChannelzRegistry::InternalUnregisterEntry(intptr_t uuid, EntityType type) {
+void ChannelzRegistry::InternalUnregister(intptr_t uuid) {
GPR_ASSERT(uuid >= 1);
MutexLock lock(&mu_);
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;
+ entities_[uuid - 1] = nullptr;
}
-void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) {
+BaseNode* ChannelzRegistry::InternalGet(intptr_t uuid) {
MutexLock lock(&mu_);
if (uuid < 1 || uuid > static_cast<intptr_t>(entities_.size())) {
return nullptr;
}
- if (entities_[uuid - 1].type == type) {
- return entities_[uuid - 1].object;
- } else {
- return nullptr;
- }
+ return entities_[uuid - 1];
}
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;
+ InlinedVector<BaseNode*, 10> top_level_channels;
// uuids index into entities one-off (idx 0 is really uuid 1, since 0 is
// reserved). However, we want to support requests coming in with
// 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 (entities_[i] != nullptr &&
+ entities_[i]->type() ==
+ grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel) {
+ top_level_channels.push_back(entities_[i]);
}
}
- if (top_level_channels.size() > 0) {
+ if (!top_level_channels.empty()) {
// create list of channels
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "channel", nullptr, GRPC_JSON_ARRAY, false);
@@ -129,9 +121,13 @@ char* grpc_channelz_get_top_channels(intptr_t start_channel_id) {
}
char* grpc_channelz_get_channel(intptr_t channel_id) {
- grpc_core::channelz::ChannelNode* channel_node =
- grpc_core::channelz::ChannelzRegistry::GetChannelNode(channel_id);
- if (channel_node == nullptr) {
+ grpc_core::channelz::BaseNode* channel_node =
+ grpc_core::channelz::ChannelzRegistry::Get(channel_id);
+ if (channel_node == nullptr ||
+ (channel_node->type() !=
+ grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel &&
+ channel_node->type() !=
+ grpc_core::channelz::BaseNode::EntityType::kInternalChannel)) {
return nullptr;
}
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
@@ -143,3 +139,21 @@ 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::BaseNode* subchannel_node =
+ grpc_core::channelz::ChannelzRegistry::Get(subchannel_id);
+ if (subchannel_node == nullptr ||
+ subchannel_node->type() !=
+ grpc_core::channelz::BaseNode::EntityType::kSubchannel) {
+ 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;
+}
diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h
index 5d7c936726..142c039220 100644
--- a/src/core/lib/channel/channelz_registry.h
+++ b/src/core/lib/channel/channelz_registry.h
@@ -40,32 +40,11 @@ class ChannelzRegistry {
// To be called in grpc_shutdown();
static void Shutdown();
- // Register/Unregister/Get for ChannelNode
- static intptr_t RegisterChannelNode(ChannelNode* channel_node) {
- RegistryEntry entry(channel_node, EntityType::kChannelNode);
- return Default()->InternalRegisterEntry(entry);
- }
- static void UnregisterChannelNode(intptr_t uuid) {
- Default()->InternalUnregisterEntry(uuid, EntityType::kChannelNode);
- }
- static ChannelNode* GetChannelNode(intptr_t uuid) {
- void* gotten = Default()->InternalGetEntry(uuid, EntityType::kChannelNode);
- return gotten == nullptr ? nullptr : static_cast<ChannelNode*>(gotten);
- }
-
- // Register/Unregister/Get for SubchannelNode
- static intptr_t RegisterSubchannelNode(SubchannelNode* channel_node) {
- RegistryEntry entry(channel_node, EntityType::kSubchannelNode);
- return Default()->InternalRegisterEntry(entry);
- }
- static void UnregisterSubchannelNode(intptr_t uuid) {
- Default()->InternalUnregisterEntry(uuid, EntityType::kSubchannelNode);
- }
- static SubchannelNode* GetSubchannelNode(intptr_t uuid) {
- void* gotten =
- Default()->InternalGetEntry(uuid, EntityType::kSubchannelNode);
- return gotten == nullptr ? nullptr : static_cast<SubchannelNode*>(gotten);
+ static intptr_t Register(BaseNode* node) {
+ return Default()->InternalRegister(node);
}
+ static void Unregister(intptr_t uuid) { Default()->InternalUnregister(uuid); }
+ static BaseNode* Get(intptr_t uuid) { return Default()->InternalGet(uuid); }
// Returns the allocated JSON string that represents the proto
// GetTopChannelsResponse as per channelz.proto.
@@ -74,19 +53,6 @@ class ChannelzRegistry {
}
private:
- enum class EntityType {
- kChannelNode,
- kSubchannelNode,
- kUnset,
- };
-
- struct RegistryEntry {
- RegistryEntry(void* object_in, EntityType type_in)
- : object(object_in), type(type_in) {}
- void* object;
- EntityType type;
- };
-
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
@@ -97,21 +63,21 @@ class ChannelzRegistry {
static ChannelzRegistry* Default();
// globally registers an Entry. Returns its unique uuid
- intptr_t InternalRegisterEntry(const RegistryEntry& entry);
+ intptr_t InternalRegister(BaseNode* node);
// globally unregisters the object that is associated to uuid. Also does
// sanity check that an object doesn't try to unregister the wrong type.
- void InternalUnregisterEntry(intptr_t uuid, EntityType type);
+ void InternalUnregister(intptr_t uuid);
// if object with uuid has previously been registered as the correct type,
// returns the void* associated with that uuid. Else returns nullptr.
- void* InternalGetEntry(intptr_t uuid, EntityType type);
+ BaseNode* InternalGet(intptr_t uuid);
char* InternalGetTopChannels(intptr_t start_channel_id);
// protects entities_ and uuid_
gpr_mu mu_;
- InlinedVector<RegistryEntry, 20> entities_;
+ InlinedVector<BaseNode*, 20> entities_;
};
} // namespace channelz