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.cc30
-rw-r--r--src/core/lib/channel/channelz.cc142
-rw-r--r--src/core/lib/channel/channelz.h131
-rw-r--r--src/core/lib/channel/channelz_registry.cc16
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;
+}