aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/grpc/grpc.h4
-rw-r--r--src/core/ext/filters/client_channel/client_channel.cc4
-rw-r--r--src/core/ext/filters/client_channel/client_channel_channelz.cc88
-rw-r--r--src/core/ext/filters/client_channel/client_channel_channelz.h47
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc2
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/subchannel_list.h2
-rw-r--r--src/core/ext/filters/client_channel/subchannel.cc55
-rw-r--r--src/core/ext/filters/client_channel/subchannel.h12
-rw-r--r--src/core/lib/channel/channel_trace.cc91
-rw-r--r--src/core/lib/channel/channel_trace.h28
-rw-r--r--src/core/lib/channel/channelz.cc126
-rw-r--r--src/core/lib/channel/channelz.h133
-rw-r--r--src/core/lib/channel/channelz_registry.cc60
-rw-r--r--src/core/lib/channel/channelz_registry.h50
-rw-r--r--src/core/lib/gprpp/ref_counted.h3
-rw-r--r--src/core/lib/surface/call.cc7
-rw-r--r--src/core/lib/surface/channel.cc5
-rw-r--r--test/core/channel/channel_stack_test.cc2
-rw-r--r--test/core/channel/channel_trace_test.cc30
-rw-r--r--test/core/channel/channelz_registry_test.cc30
-rw-r--r--test/core/channel/channelz_test.cc53
-rw-r--r--test/core/end2end/tests/channelz.cc4
-rw-r--r--test/cpp/util/channel_trace_proto_helper.cc4
-rw-r--r--test/cpp/util/channel_trace_proto_helper.h1
24 files changed, 526 insertions, 315 deletions
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index f0eb2c0121..942c83bcde 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -477,6 +477,10 @@ GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id);
is allocated and must be freed by the application. */
GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id);
+/* Returns a single Subchannel, or else a NOT_FOUND code. The returned string
+ is allocated and must be freed by the application. */
+GRPCAPI char* grpc_channelz_get_subchannel(intptr_t subchannel_id);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 024c9d737e..683cb0e01d 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -892,6 +892,7 @@ typedef struct client_channel_call_data {
grpc_millis deadline;
gpr_arena* arena;
grpc_call_stack* owning_call;
+ grpc_call* call;
grpc_call_combiner* call_combiner;
grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
@@ -2561,7 +2562,8 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) {
calld->arena, // arena
calld->pick.subchannel_call_context, // context
calld->call_combiner, // call_combiner
- parent_data_size // parent_data_size
+ parent_data_size, // parent_data_size
+ calld->call // call
};
grpc_error* new_error = calld->pick.connected_subchannel->CreateCall(
call_args, &calld->subchannel_call);
diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc
index 4c9c9a6bd6..b209acc2ea 100644
--- a/src/core/ext/filters/client_channel/client_channel_channelz.cc
+++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc
@@ -20,10 +20,13 @@
#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
+#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h"
+#include <grpc/support/string_util.h>
+
namespace grpc_core {
namespace channelz {
namespace {
@@ -95,6 +98,40 @@ void ClientChannelNode::PopulateChildRefs(grpc_json* json) {
}
}
+grpc_json* ClientChannelNode::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", 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);
+ // populate the target.
+ GPR_ASSERT(target_view() != nullptr);
+ grpc_json_create_child(nullptr, json, "target", target_view(),
+ GRPC_JSON_STRING, false);
+ // as CallCountingAndTracingNode to populate trace and call count data.
+ counter_and_tracer()->PopulateTrace(json);
+ counter_and_tracer()->PopulateCallData(json);
+ // reset to the top level
+ json = top_level_json;
+ PopulateChildRefs(json);
+ return top_level_json;
+}
+
grpc_arg ClientChannelNode::CreateChannelArg() {
return grpc_channel_arg_pointer_create(
const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC),
@@ -109,5 +146,56 @@ RefCountedPtr<ChannelNode> ClientChannelNode::MakeClientChannelNode(
channel, channel_tracer_max_nodes, is_top_level_channel);
}
+SubchannelNode::SubchannelNode(grpc_subchannel* subchannel,
+ size_t channel_tracer_max_nodes)
+ : BaseNode(EntityType::kSubchannel),
+ subchannel_(subchannel),
+ target_(
+ UniquePtr<char>(gpr_strdup(grpc_subchannel_get_target(subchannel_)))),
+ counter_and_tracer_(channel_tracer_max_nodes) {}
+
+SubchannelNode::~SubchannelNode() {}
+
+void SubchannelNode::PopulateConnectivityState(grpc_json* json) {
+ grpc_connectivity_state state;
+ if (subchannel_ == nullptr) {
+ state = GRPC_CHANNEL_SHUTDOWN;
+ } else {
+ state = grpc_subchannel_check_connectivity(subchannel_, nullptr);
+ }
+ json = grpc_json_create_child(nullptr, json, "state", nullptr,
+ GRPC_JSON_OBJECT, false);
+ grpc_json_create_child(nullptr, json, "state",
+ grpc_connectivity_state_name(state), GRPC_JSON_STRING,
+ false);
+}
+
+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", 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);
+ grpc_json_create_child(nullptr, json, "target", target_.get(),
+ GRPC_JSON_STRING, false);
+ counter_and_tracer_.PopulateTrace(json);
+ counter_and_tracer_.PopulateCallData(json);
+ return top_level_json;
+}
+
} // namespace channelz
} // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h
index 6f27b5c8b7..f5344c049e 100644
--- a/src/core/ext/filters/client_channel/client_channel_channelz.h
+++ b/src/core/ext/filters/client_channel/client_channel_channelz.h
@@ -26,6 +26,8 @@
#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/gprpp/inlined_vector.h"
+typedef struct grpc_subchannel grpc_subchannel;
+
namespace grpc_core {
// TODO(ncteisen), this only contains the uuids of the children for now,
@@ -43,26 +45,47 @@ class ClientChannelNode : public ChannelNode {
grpc_channel* channel, size_t channel_tracer_max_nodes,
bool is_top_level_channel);
- // Override this functionality since client_channels have a notion of
- // channel connectivity.
- void PopulateConnectivityState(grpc_json* json) override;
+ ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
+ bool is_top_level_channel);
+ virtual ~ClientChannelNode() {}
- // Override this functionality since client_channels have subchannels
- void PopulateChildRefs(grpc_json* json) override;
+ grpc_json* RenderJson() override;
// Helper to create a channel arg to ensure this type of ChannelNode is
// created.
static grpc_arg CreateChannelArg();
- protected:
- GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
- GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW
- ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
- bool is_top_level_channel);
- virtual ~ClientChannelNode() {}
-
private:
grpc_channel_element* client_channel_;
+
+ // helpers
+ void PopulateConnectivityState(grpc_json* json);
+ void PopulateChildRefs(grpc_json* json);
+};
+
+// Handles channelz bookkeeping for sockets
+class SubchannelNode : public BaseNode {
+ public:
+ SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes);
+ ~SubchannelNode() override;
+
+ void MarkSubchannelDestroyed() {
+ GPR_ASSERT(subchannel_ != nullptr);
+ subchannel_ = nullptr;
+ }
+
+ grpc_json* RenderJson() override;
+
+ CallCountingAndTracingNode* counter_and_tracer() {
+ return &counter_and_tracer_;
+ }
+
+ private:
+ grpc_subchannel* subchannel_;
+ UniquePtr<char> target_;
+ CallCountingAndTracingNode counter_and_tracer_;
+
+ void PopulateConnectivityState(grpc_json* json);
};
} // namespace channelz
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index 959c7441a3..dc475d3d68 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -1294,7 +1294,7 @@ void GrpcLb::FillChildRefsForChannelz(ChildRefsList* child_subchannels,
grpc_core::channelz::ChannelNode* channel_node =
grpc_channel_get_channelz_node(lb_channel_);
if (channel_node != nullptr) {
- child_channels->push_back(channel_node->channel_uuid());
+ child_channels->push_back(channel_node->uuid());
}
}
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
index 018ac3bb86..199b9a3c13 100644
--- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
+++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
@@ -196,7 +196,7 @@ class SubchannelList
grpc_core::channelz::SubchannelNode* subchannel_node =
grpc_subchannel_get_channelz_node(subchannels_[i].subchannel());
if (subchannel_node != nullptr) {
- refs_list->push_back(subchannel_node->subchannel_uuid());
+ refs_list->push_back(subchannel_node->uuid());
}
}
}
diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc
index 71ef8c518b..d7b64a900f 100644
--- a/src/core/ext/filters/client_channel/subchannel.cc
+++ b/src/core/ext/filters/client_channel/subchannel.cc
@@ -46,6 +46,7 @@
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/transport/connectivity_state.h"
@@ -181,7 +182,13 @@ static void connection_destroy(void* arg, grpc_error* error) {
static void subchannel_destroy(void* arg, grpc_error* error) {
grpc_subchannel* c = static_cast<grpc_subchannel*>(arg);
- c->channelz_subchannel.reset();
+ if (c->channelz_subchannel != nullptr) {
+ c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent(
+ grpc_core::channelz::ChannelTrace::Severity::Info,
+ grpc_slice_from_static_string("Subchannel destroyed"));
+ c->channelz_subchannel->MarkSubchannelDestroyed();
+ c->channelz_subchannel.reset();
+ }
gpr_free((void*)c->filters);
grpc_channel_args_destroy(c->args);
grpc_connectivity_state_destroy(&c->state_tracker);
@@ -381,9 +388,18 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
const grpc_arg* arg =
grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ);
bool channelz_enabled = grpc_channel_arg_get_bool(arg, false);
+ arg = grpc_channel_args_find(c->args,
+ GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
+ const grpc_integer_options options = {0, 0, INT_MAX};
+ size_t channel_tracer_max_nodes =
+ (size_t)grpc_channel_arg_get_integer(arg, options);
if (channelz_enabled) {
c->channelz_subchannel =
- grpc_core::MakeRefCounted<grpc_core::channelz::SubchannelNode>();
+ grpc_core::MakeRefCounted<grpc_core::channelz::SubchannelNode>(
+ c, channel_tracer_max_nodes);
+ c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent(
+ grpc_core::channelz::ChannelTrace::Severity::Info,
+ grpc_slice_from_static_string("Subchannel created"));
}
return grpc_subchannel_index_register(key, c);
@@ -625,8 +641,8 @@ static bool publish_transport_locked(grpc_subchannel* c) {
}
/* publish */
- c->connected_subchannel.reset(
- grpc_core::New<grpc_core::ConnectedSubchannel>(stk));
+ c->connected_subchannel.reset(grpc_core::New<grpc_core::ConnectedSubchannel>(
+ stk, c->channelz_subchannel.get()));
gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
c->connected_subchannel.get(), c);
@@ -757,6 +773,14 @@ void grpc_get_subchannel_address_arg(const grpc_channel_args* args,
}
}
+const char* grpc_subchannel_get_target(grpc_subchannel* subchannel) {
+ const grpc_arg* addr_arg =
+ grpc_channel_args_find(subchannel->args, GRPC_ARG_SUBCHANNEL_ADDRESS);
+ const char* addr_str = grpc_channel_arg_get_string(addr_arg);
+ GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy.
+ return addr_str;
+}
+
const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args) {
const grpc_arg* addr_arg =
grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS);
@@ -773,9 +797,12 @@ grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) {
namespace grpc_core {
-ConnectedSubchannel::ConnectedSubchannel(grpc_channel_stack* channel_stack)
+ConnectedSubchannel::ConnectedSubchannel(
+ grpc_channel_stack* channel_stack,
+ channelz::SubchannelNode* channelz_subchannel)
: RefCountedWithTracing<ConnectedSubchannel>(&grpc_trace_stream_refcount),
- channel_stack_(channel_stack) {}
+ channel_stack_(channel_stack),
+ channelz_subchannel_(channelz_subchannel) {}
ConnectedSubchannel::~ConnectedSubchannel() {
GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
@@ -822,14 +849,14 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args,
connection.release(); // Ref is passed to the grpc_subchannel_call object.
(*call)->connection = this;
const grpc_call_element_args call_args = {
- callstk, /* call_stack */
- nullptr, /* server_transport_data */
- args.context, /* context */
- args.path, /* path */
- args.start_time, /* start_time */
- args.deadline, /* deadline */
- args.arena, /* arena */
- args.call_combiner /* call_combiner */
+ callstk, /* call_stack */
+ nullptr, /* server_transport_data */
+ args.context, /* context */
+ args.path, /* path */
+ args.start_time, /* start_time */
+ args.deadline, /* deadline */
+ args.arena, /* arena */
+ args.call_combiner, /* call_combiner */
};
grpc_error* error = grpc_call_stack_init(
channel_stack_, 1, subchannel_call_destroy, *call, &call_args);
diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h
index 9e53f7d542..d62348488e 100644
--- a/src/core/ext/filters/client_channel/subchannel.h
+++ b/src/core/ext/filters/client_channel/subchannel.h
@@ -83,9 +83,11 @@ class ConnectedSubchannel : public RefCountedWithTracing<ConnectedSubchannel> {
grpc_call_context_element* context;
grpc_call_combiner* call_combiner;
size_t parent_data_size;
+ grpc_call* call;
};
- explicit ConnectedSubchannel(grpc_channel_stack* channel_stack);
+ explicit ConnectedSubchannel(grpc_channel_stack* channel_stack,
+ channelz::SubchannelNode* channelz_subchannel);
~ConnectedSubchannel();
grpc_channel_stack* channel_stack() { return channel_stack_; }
@@ -94,9 +96,15 @@ class ConnectedSubchannel : public RefCountedWithTracing<ConnectedSubchannel> {
grpc_closure* closure);
void Ping(grpc_closure* on_initiate, grpc_closure* on_ack);
grpc_error* CreateCall(const CallArgs& args, grpc_subchannel_call** call);
+ channelz::SubchannelNode* channelz_subchannel() {
+ return channelz_subchannel_;
+ }
private:
grpc_channel_stack* channel_stack_;
+ // backpointer to the channelz node in this connected subchannel's
+ // owning subchannel.
+ channelz::SubchannelNode* channelz_subchannel_;
};
} // namespace grpc_core
@@ -177,6 +185,8 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
void grpc_get_subchannel_address_arg(const grpc_channel_args* args,
grpc_resolved_address* addr);
+const char* grpc_subchannel_get_target(grpc_subchannel* subchannel);
+
/// Returns the URI string for the address to connect to.
const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args);
diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc
index b3443310ac..7d8bb391f8 100644
--- a/src/core/lib/channel/channel_trace.cc
+++ b/src/core/lib/channel/channel_trace.cc
@@ -43,14 +43,23 @@ namespace channelz {
ChannelTrace::TraceEvent::TraceEvent(
Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_channel, ReferencedType type)
+ RefCountedPtr<ChannelNode> referenced_channel)
: 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_channel_(std::move(referenced_channel)) {}
+
+// ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data,
+// RefCountedPtr<SubchannelNode>
+// referenced_subchannel)
+// : severity_(severity),
+// data_(data),
+// timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(),
+// GPR_CLOCK_REALTIME)),
+// next_(nullptr),
+// referenced_subchannel_(std::move(referenced_subchannel)) {}
ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data)
: severity_(severity),
@@ -115,19 +124,18 @@ void ChannelTrace::AddTraceEventReferencingChannel(
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));
+ AddTraceEventHelper(
+ New<TraceEvent>(severity, data, std::move(referenced_channel)));
}
-void ChannelTrace::AddTraceEventReferencingSubchannel(
- Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_subchannel) {
- 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));
-}
+// void ChannelTrace::AddTraceEventReferencingSubchannel(
+// Severity severity, grpc_slice data,
+// RefCountedPtr<SubchannelNode> referenced_subchannel) {
+// 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)));
+// }
namespace {
@@ -159,43 +167,50 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const {
GRPC_JSON_STRING, true);
if (referenced_channel_ != nullptr) {
char* uuid_str;
- gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->channel_uuid());
+ gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->uuid());
grpc_json* child_ref = grpc_json_create_child(
- json_iterator, json,
- (referenced_type_ == ReferencedType::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);
+ json_iterator, json, "channelRef", nullptr, GRPC_JSON_OBJECT, false);
+ json_iterator = grpc_json_create_child(nullptr, child_ref, "channelId",
+ uuid_str, GRPC_JSON_STRING, true);
json_iterator = child_ref;
}
+ // else {
+ // char* uuid_str;
+ // gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_subchannel_->uuid());
+ // grpc_json* child_ref = grpc_json_create_child(
+ // json_iterator, json, "subchannelRef",
+ // nullptr, GRPC_JSON_OBJECT, false);
+ // json_iterator = grpc_json_create_child(
+ // nullptr, child_ref, "subchannelId",
+ // uuid_str, GRPC_JSON_STRING, true);
+ // json_iterator = child_ref;
+ // }
}
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..543eabf13a 100644
--- a/src/core/lib/channel/channel_trace.h
+++ b/src/core/lib/channel/channel_trace.h
@@ -31,6 +31,7 @@ namespace grpc_core {
namespace channelz {
class ChannelNode;
+class SubchannelNode;
// Object used to hold live data for a channel. This data is exposed via the
// channelz service:
@@ -55,9 +56,9 @@ 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
@@ -65,25 +66,26 @@ class ChannelTrace {
void AddTraceEventReferencingChannel(
Severity severity, grpc_slice data,
RefCountedPtr<ChannelNode> referenced_channel);
- void AddTraceEventReferencingSubchannel(
- Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_subchannel);
+ // void AddTraceEventReferencingSubchannel(
+ // Severity severity, grpc_slice data,
+ // RefCountedPtr<SubchannelNode> referenced_subchannel);
// 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);
+
+ // Constructor for a TraceEvent that references a subchannel.
TraceEvent(Severity severity, grpc_slice data,
- RefCountedPtr<ChannelNode> referenced_channel,
- ReferencedType type);
+ RefCountedPtr<SubchannelNode> referenced_subchannel);
// Constructor for a TraceEvent that does not reverence a different
// channel.
@@ -106,9 +108,7 @@ class ChannelTrace {
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<SubchannelNode> referenced_subchannel_;
}; // 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..ee1717ce9f 100644
--- a/src/core/lib/channel/channelz.cc
+++ b/src/core/lib/channel/channelz.cc
@@ -41,69 +41,46 @@
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) {
+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;
+}
+
+CallCountingAndTracingNode::CallCountingAndTracingNode(
+ 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_);
-}
+CallCountingAndTracingNode::~CallCountingAndTracingNode() { trace_.Destroy(); }
-void ChannelNode::RecordCallStarted() {
+void CallCountingAndTracingNode::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 CallCountingAndTracingNode::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 CallCountingAndTracingNode::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 +98,48 @@ grpc_json* ChannelNode::RenderJson() {
json_iterator =
grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
+}
+
+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_))),
+ counter_and_tracer_(channel_tracer_max_nodes) {}
+
+ChannelNode::~ChannelNode() {}
+
+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", uuid());
+ // reset json iterators to top level object
json = top_level_json;
json_iterator = nullptr;
- PopulateChildRefs(json);
+ // 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;
+ // populate the target.
+ GPR_ASSERT(target_.get() != nullptr);
+ grpc_json_create_child(nullptr, json, "target", target_.get(),
+ GRPC_JSON_STRING, false);
+ // as CallCountingAndTracingNode to populate trace and call count data.
+ counter_and_tracer_.PopulateTrace(json);
+ counter_and_tracer_.PopulateCallData(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 +147,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..7bc4567ad2 100644
--- a/src/core/lib/channel/channelz.h
+++ b/src/core/lib/channel/channelz.h
@@ -43,14 +43,53 @@ namespace grpc_core {
namespace channelz {
namespace testing {
-class ChannelNodePeer;
+class CallCountingAndTracingNodePeer;
}
-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,
+ };
+
+ 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:
+ friend class ChannelTrace;
+ EntityType type_;
+ const intptr_t uuid_;
+};
+
+// 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.
+class CallCountingAndTracingNode {
+ public:
+ CallCountingAndTracingNode(size_t channel_tracer_max_nodes);
+ ~CallCountingAndTracingNode();
void RecordCallStarted();
void RecordCallFailed() {
@@ -59,18 +98,37 @@ class ChannelNode : public RefCounted<ChannelNode> {
void RecordCallSucceeded() {
gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1)));
}
+ ChannelTrace* trace() { return trace_.get(); }
- grpc_json* RenderJson();
- char* RenderJsonString();
+ // Common rendering of the channel trace.
+ void PopulateTrace(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);
+ // Common rendering of the call count data and last_call_started_timestamp.
+ void PopulateCallData(grpc_json* json);
- virtual void PopulateChildRefs(grpc_json* json);
+ private:
+ // testing peer friend.
+ friend class testing::CallCountingAndTracingNodePeer;
- ChannelTrace* trace() { return trace_.get(); }
+ 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_;
+};
+
+// 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;
void MarkChannelDestroyed() {
GPR_ASSERT(channel_ != nullptr);
@@ -79,47 +137,34 @@ 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_; }
+ CallCountingAndTracingNode* counter_and_tracer() {
+ return &counter_and_tracer_;
+ }
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();
+ // provides view of target for child.
+ char* target_view() { return target_.get(); }
private:
- // 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_;
+ CallCountingAndTracingNode counter_and_tracer_;
};
-// 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
+ 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 38496b3d78..d2c403cc1b 100644
--- a/src/core/lib/channel/channelz_registry.cc
+++ b/src/core/lib/channel/channelz_registry.cc
@@ -52,54 +52,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) {
mu_guard guard(&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);
mu_guard guard(&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) {
mu_guard guard(&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);
@@ -128,9 +120,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);
@@ -142,3 +138,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
diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h
index ddac5bd475..3d6a32ddcf 100644
--- a/src/core/lib/gprpp/ref_counted.h
+++ b/src/core/lib/gprpp/ref_counted.h
@@ -73,7 +73,8 @@ class RefCounted {
private:
// Allow RefCountedPtr<> to access IncrementRefCount().
- friend class RefCountedPtr<Child>;
+ template <typename T>
+ friend class RefCountedPtr;
void IncrementRefCount() { gpr_ref(&refs_); }
diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc
index 847bb87f7e..03b7cedcdb 100644
--- a/src/core/lib/surface/call.cc
+++ b/src/core/lib/surface/call.cc
@@ -489,7 +489,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args,
grpc_core::channelz::ChannelNode* channelz_channel =
grpc_channel_get_channelz_node(call->channel);
if (channelz_channel != nullptr) {
- channelz_channel->RecordCallStarted();
+ channelz_channel->counter_and_tracer()->RecordCallStarted();
}
grpc_slice_unref_internal(path);
@@ -1264,13 +1264,14 @@ static void post_batch_completion(batch_control* bctl) {
get_final_status(call, set_cancelled_value,
call->final_op.server.cancelled, nullptr, nullptr);
}
+ // Record channelz data for the channel.
grpc_core::channelz::ChannelNode* channelz_channel =
grpc_channel_get_channelz_node(call->channel);
if (channelz_channel != nullptr) {
if (*call->final_op.client.status != GRPC_STATUS_OK) {
- channelz_channel->RecordCallFailed();
+ channelz_channel->counter_and_tracer()->RecordCallFailed();
} else {
- channelz_channel->RecordCallSucceeded();
+ channelz_channel->counter_and_tracer()->RecordCallSucceeded();
}
}
GRPC_ERROR_UNREF(error);
diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc
index 7cbd61adef..16d3322a9d 100644
--- a/src/core/lib/surface/channel.cc
+++ b/src/core/lib/surface/channel.cc
@@ -170,7 +170,7 @@ grpc_channel* grpc_channel_create_with_builder(
bool is_top_level_channel = channel->is_client && !internal_channel;
channel->channelz_channel = channel_node_create_func(
channel, channel_tracer_max_nodes, is_top_level_channel);
- channel->channelz_channel->trace()->AddTraceEvent(
+ channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent(
grpc_core::channelz::ChannelTrace::Severity::Info,
grpc_slice_from_static_string("Channel created"));
}
@@ -417,6 +417,9 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) {
static void destroy_channel(void* arg, grpc_error* error) {
grpc_channel* channel = static_cast<grpc_channel*>(arg);
if (channel->channelz_channel != nullptr) {
+ channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent(
+ grpc_core::channelz::ChannelTrace::Severity::Info,
+ grpc_slice_from_static_string("Channel destroyed"));
channel->channelz_channel->MarkChannelDestroyed();
channel->channelz_channel.reset();
}
diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc
index 2f5329a96d..6f0bfa06d2 100644
--- a/test/core/channel/channel_stack_test.cc
+++ b/test/core/channel/channel_stack_test.cc
@@ -124,7 +124,7 @@ static void test_create_channel_stack(void) {
gpr_now(GPR_CLOCK_MONOTONIC), /* start_time */
GRPC_MILLIS_INF_FUTURE, /* deadline */
nullptr, /* arena */
- nullptr /* call_combiner */
+ nullptr, /* call_combiner */
};
grpc_error* error =
grpc_call_stack_init(channel_stack, 1, free_call, call_stack, &args);
diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc
index 99d9a4847f..3d6aff03eb 100644
--- a/test/core/channel/channel_trace_test.cc
+++ b/test/core/channel/channel_trace_test.cc
@@ -156,18 +156,18 @@ TEST_P(ChannelTracerTest, ComplexTest) {
ChannelFixture channel1(GetParam());
RefCountedPtr<ChannelNode> sc1 =
MakeRefCounted<ChannelNode>(channel1.channel(), GetParam(), true);
- tracer.AddTraceEventReferencingSubchannel(
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
ValidateChannelTrace(&tracer, 3, GetParam());
- AddSimpleTrace(sc1->trace());
- AddSimpleTrace(sc1->trace());
- AddSimpleTrace(sc1->trace());
- ValidateChannelTrace(sc1->trace(), 3, GetParam());
- AddSimpleTrace(sc1->trace());
- AddSimpleTrace(sc1->trace());
- AddSimpleTrace(sc1->trace());
- ValidateChannelTrace(sc1->trace(), 6, GetParam());
+ AddSimpleTrace(sc1->counter_and_tracer()->trace());
+ AddSimpleTrace(sc1->counter_and_tracer()->trace());
+ AddSimpleTrace(sc1->counter_and_tracer()->trace());
+ ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 3, GetParam());
+ AddSimpleTrace(sc1->counter_and_tracer()->trace());
+ AddSimpleTrace(sc1->counter_and_tracer()->trace());
+ AddSimpleTrace(sc1->counter_and_tracer()->trace());
+ ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 6, GetParam());
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 5, GetParam());
@@ -177,7 +177,7 @@ TEST_P(ChannelTracerTest, ComplexTest) {
tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("LB channel two created"), sc2);
- tracer.AddTraceEventReferencingSubchannel(
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("subchannel one inactive"), sc1);
ValidateChannelTrace(&tracer, 7, GetParam());
@@ -207,24 +207,24 @@ TEST_P(ChannelTracerTest, TestNesting) {
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
ValidateChannelTrace(&tracer, 3, GetParam());
- AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->counter_and_tracer()->trace());
ChannelFixture channel2(GetParam());
RefCountedPtr<ChannelNode> conn1 =
MakeRefCounted<ChannelNode>(channel2.channel(), GetParam(), true);
// nesting one level deeper.
- sc1->trace()->AddTraceEventReferencingSubchannel(
+ sc1->counter_and_tracer()->trace()->AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("connection one created"), conn1);
ValidateChannelTrace(&tracer, 3, GetParam());
- AddSimpleTrace(conn1->trace());
+ AddSimpleTrace(conn1->counter_and_tracer()->trace());
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 5, GetParam());
- ValidateChannelTrace(conn1->trace(), 1, GetParam());
+ ValidateChannelTrace(conn1->counter_and_tracer()->trace(), 1, GetParam());
ChannelFixture channel3(GetParam());
RefCountedPtr<ChannelNode> sc2 =
MakeRefCounted<ChannelNode>(channel3.channel(), GetParam(), true);
- tracer.AddTraceEventReferencingSubchannel(
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel two created"), sc2);
// this trace should not get added to the parents children since it is already
diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc
index 581e867584..c02d525c81 100644
--- a/test/core/channel/channelz_registry_test.cc
+++ b/test/core/channel/channelz_registry_test.cc
@@ -44,22 +44,22 @@ namespace channelz {
namespace testing {
TEST(ChannelzRegistryTest, UuidStartsAboveZeroTest) {
- ChannelNode* channelz_channel = nullptr;
- intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel);
+ BaseNode* channelz_channel = nullptr;
+ intptr_t uuid = ChannelzRegistry::Register(channelz_channel);
EXPECT_GT(uuid, 0) << "First uuid chose must be greater than zero. Zero if "
"reserved according to "
"https://github.com/grpc/proposal/blob/master/"
"A14-channelz.md";
- ChannelzRegistry::UnregisterChannelNode(uuid);
+ ChannelzRegistry::Unregister(uuid);
}
TEST(ChannelzRegistryTest, UuidsAreIncreasing) {
- ChannelNode* channelz_channel = nullptr;
+ BaseNode* channelz_channel = nullptr;
std::vector<intptr_t> uuids;
uuids.reserve(10);
for (int i = 0; i < 10; ++i) {
// reregister the same object. It's ok since we are just testing uuids
- uuids.push_back(ChannelzRegistry::RegisterChannelNode(channelz_channel));
+ uuids.push_back(ChannelzRegistry::Register(channelz_channel));
}
for (size_t i = 1; i < uuids.size(); ++i) {
EXPECT_LT(uuids[i - 1], uuids[i]) << "Uuids must always be increasing";
@@ -68,30 +68,30 @@ TEST(ChannelzRegistryTest, UuidsAreIncreasing) {
TEST(ChannelzRegistryTest, RegisterGetTest) {
// we hackily jam an intptr_t into this pointer to check for equality later
- ChannelNode* channelz_channel = (ChannelNode*)42;
- intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel);
- ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid);
+ BaseNode* channelz_channel = (BaseNode*)42;
+ intptr_t uuid = ChannelzRegistry::Register(channelz_channel);
+ BaseNode* retrieved = ChannelzRegistry::Get(uuid);
EXPECT_EQ(channelz_channel, retrieved);
}
TEST(ChannelzRegistryTest, RegisterManyItems) {
// we hackily jam an intptr_t into this pointer to check for equality later
- ChannelNode* channelz_channel = (ChannelNode*)42;
+ BaseNode* channelz_channel = (BaseNode*)42;
for (int i = 0; i < 100; i++) {
- intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel);
- ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid);
+ intptr_t uuid = ChannelzRegistry::Register(channelz_channel);
+ BaseNode* retrieved = ChannelzRegistry::Get(uuid);
EXPECT_EQ(channelz_channel, retrieved);
}
}
TEST(ChannelzRegistryTest, NullIfNotPresentTest) {
// we hackily jam an intptr_t into this pointer to check for equality later
- ChannelNode* channelz_channel = (ChannelNode*)42;
- intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel);
+ BaseNode* channelz_channel = (BaseNode*)42;
+ intptr_t uuid = ChannelzRegistry::Register(channelz_channel);
// try to pull out a uuid that does not exist.
- ChannelNode* nonexistant = ChannelzRegistry::GetChannelNode(uuid + 1);
+ BaseNode* nonexistant = ChannelzRegistry::Get(uuid + 1);
EXPECT_EQ(nonexistant, nullptr);
- ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid);
+ BaseNode* retrieved = ChannelzRegistry::Get(uuid);
EXPECT_EQ(channelz_channel, retrieved);
}
diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc
index ad5f86d934..5e9a3f89a2 100644
--- a/test/core/channel/channelz_test.cc
+++ b/test/core/channel/channelz_test.cc
@@ -44,16 +44,17 @@ namespace channelz {
namespace testing {
// testing peer to access channel internals
-class ChannelNodePeer {
+class CallCountingAndTracingNodePeer {
public:
- ChannelNodePeer(ChannelNode* channel) : channel_(channel) {}
+ CallCountingAndTracingNodePeer(CallCountingAndTracingNode* node)
+ : node_(node) {}
grpc_millis last_call_started_millis() {
return (grpc_millis)gpr_atm_no_barrier_load(
- &channel_->last_call_started_millis_);
+ &node_->last_call_started_millis_);
}
private:
- ChannelNode* channel_;
+ CallCountingAndTracingNode* node_;
};
namespace {
@@ -157,14 +158,14 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) {
ValidateCounters(json_str, args);
gpr_free(json_str);
// also check that the core API formats this the correct way
- char* core_api_json_str = grpc_channelz_get_channel(channel->channel_uuid());
+ char* core_api_json_str = grpc_channelz_get_channel(channel->uuid());
grpc::testing::ValidateGetChannelResponseProtoJsonTranslation(
core_api_json_str);
gpr_free(core_api_json_str);
}
-grpc_millis GetLastCallStartedMillis(ChannelNode* channel) {
- ChannelNodePeer peer(channel);
+grpc_millis GetLastCallStartedMillis(CallCountingAndTracingNode* channel) {
+ CallCountingAndTracingNodePeer peer(channel);
return peer.last_call_started_millis();
}
@@ -200,16 +201,16 @@ TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) {
ChannelFixture channel(GetParam());
ChannelNode* channelz_channel =
grpc_channel_get_channelz_node(channel.channel());
- channelz_channel->RecordCallStarted();
- channelz_channel->RecordCallFailed();
- channelz_channel->RecordCallSucceeded();
+ channelz_channel->counter_and_tracer()->RecordCallStarted();
+ channelz_channel->counter_and_tracer()->RecordCallFailed();
+ channelz_channel->counter_and_tracer()->RecordCallSucceeded();
ValidateChannel(channelz_channel, {1, 1, 1});
- channelz_channel->RecordCallStarted();
- channelz_channel->RecordCallFailed();
- channelz_channel->RecordCallSucceeded();
- channelz_channel->RecordCallStarted();
- channelz_channel->RecordCallFailed();
- channelz_channel->RecordCallSucceeded();
+ channelz_channel->counter_and_tracer()->RecordCallStarted();
+ channelz_channel->counter_and_tracer()->RecordCallFailed();
+ channelz_channel->counter_and_tracer()->RecordCallSucceeded();
+ channelz_channel->counter_and_tracer()->RecordCallStarted();
+ channelz_channel->counter_and_tracer()->RecordCallFailed();
+ channelz_channel->counter_and_tracer()->RecordCallSucceeded();
ValidateChannel(channelz_channel, {3, 3, 3});
}
@@ -219,23 +220,27 @@ TEST_P(ChannelzChannelTest, LastCallStartedMillis) {
ChannelNode* channelz_channel =
grpc_channel_get_channelz_node(channel.channel());
// start a call to set the last call started timestamp
- channelz_channel->RecordCallStarted();
- grpc_millis millis1 = GetLastCallStartedMillis(channelz_channel);
+ channelz_channel->counter_and_tracer()->RecordCallStarted();
+ grpc_millis millis1 =
+ GetLastCallStartedMillis(channelz_channel->counter_and_tracer());
// time gone by should not affect the timestamp
ChannelzSleep(100);
- grpc_millis millis2 = GetLastCallStartedMillis(channelz_channel);
+ grpc_millis millis2 =
+ GetLastCallStartedMillis(channelz_channel->counter_and_tracer());
EXPECT_EQ(millis1, millis2);
// calls succeeded or failed should not affect the timestamp
ChannelzSleep(100);
- channelz_channel->RecordCallFailed();
- channelz_channel->RecordCallSucceeded();
- grpc_millis millis3 = GetLastCallStartedMillis(channelz_channel);
+ channelz_channel->counter_and_tracer()->RecordCallFailed();
+ channelz_channel->counter_and_tracer()->RecordCallSucceeded();
+ grpc_millis millis3 =
+ GetLastCallStartedMillis(channelz_channel->counter_and_tracer());
EXPECT_EQ(millis1, millis3);
// another call started should affect the timestamp
// sleep for extra long to avoid flakes (since we cache Now())
ChannelzSleep(5000);
- channelz_channel->RecordCallStarted();
- grpc_millis millis4 = GetLastCallStartedMillis(channelz_channel);
+ channelz_channel->counter_and_tracer()->RecordCallStarted();
+ grpc_millis millis4 =
+ GetLastCallStartedMillis(channelz_channel->counter_and_tracer());
EXPECT_NE(millis1, millis4);
}
diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc
index 533703a2be..754c3d3741 100644
--- a/test/core/end2end/tests/channelz.cc
+++ b/test/core/end2end/tests/channelz.cc
@@ -241,6 +241,10 @@ static void test_channelz(grpc_end2end_test_config config) {
GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\""));
gpr_free(json);
+ json = grpc_channelz_get_subchannel(2);
+ gpr_log(GPR_INFO, "%s", json);
+ gpr_free(json);
+
end_test(&f);
config.tear_down_data(&f);
}
diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc
index b4704bfe6a..e416a0375f 100644
--- a/test/cpp/util/channel_trace_proto_helper.cc
+++ b/test/cpp/util/channel_trace_proto_helper.cc
@@ -82,5 +82,9 @@ void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str) {
json_c_str);
}
+void ValidateSubchannelProtoJsonTranslation(char* json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::Subchannel>(json_c_str);
+}
+
} // namespace testing
} // namespace grpc
diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h
index 18e3d54b6b..a1ebbcd110 100644
--- a/test/cpp/util/channel_trace_proto_helper.h
+++ b/test/cpp/util/channel_trace_proto_helper.h
@@ -26,6 +26,7 @@ void ValidateChannelTraceProtoJsonTranslation(char* json_c_str);
void ValidateChannelProtoJsonTranslation(char* json_c_str);
void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str);
void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str);
+void ValidateSubchannelProtoJsonTranslation(char* json_c_str);
} // namespace testing
} // namespace grpc