reviewable/pr16055/r4
ncteisen 7 years ago
parent 835dab6a46
commit f081cf67d1
  1. 16
      src/core/ext/filters/client_channel/client_channel_channelz.cc
  2. 2
      src/core/ext/filters/client_channel/client_channel_channelz.h
  3. 2
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  4. 2
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
  5. 42
      src/core/lib/channel/channel_trace.cc
  6. 26
      src/core/lib/channel/channel_trace.h
  7. 14
      src/core/lib/channel/channelz.cc
  8. 10
      src/core/lib/channel/channelz.h
  9. 100
      test/core/channel/channel_trace_test.cc
  10. 2
      test/core/channel/channelz_test.cc

@ -108,8 +108,8 @@ grpc_json* ClientChannelNode::RenderJson() {
GRPC_JSON_OBJECT, false);
json = json_iterator;
json_iterator = nullptr;
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "channelId", channel_uuid());
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;
@ -152,13 +152,9 @@ SubchannelNode::SubchannelNode(grpc_subchannel* subchannel,
channel_tracer_max_nodes),
subchannel_(subchannel),
target_(UniquePtr<char>(
gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {
subchannel_uuid_ = ChannelzRegistry::Register(this);
}
gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {}
SubchannelNode::~SubchannelNode() {
ChannelzRegistry::Unregister(subchannel_uuid_);
}
SubchannelNode::~SubchannelNode() {}
void SubchannelNode::PopulateConnectivityState(grpc_json* json) {
grpc_connectivity_state state;
@ -182,8 +178,8 @@ grpc_json* SubchannelNode::RenderJson() {
GRPC_JSON_OBJECT, false);
json = json_iterator;
json_iterator = nullptr;
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "subchannelId", subchannel_uuid_);
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;

@ -79,8 +79,6 @@ class SubchannelNode : public CallCountingAndTracingNode {
grpc_json* RenderJson() override;
intptr_t subchannel_uuid() { return subchannel_uuid_; }
private:
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW

@ -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());
}
}
}

@ -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());
}
}
}

@ -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),
@ -112,21 +110,11 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice 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(
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,18 +145,24 @@ 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) {
GPR_ASSERT(
referenced_entity_->type() == BaseNode::EntityType::kSubchannel ||
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",
(referenced_entity_->type() == BaseNode::EntityType::kSubchannel)
? "subchannelRef"
: "channelRef",
nullptr, GRPC_JSON_OBJECT, false);
json_iterator = grpc_json_create_child(
nullptr, child_ref,
(referenced_type_ == ReferencedType::Channel) ? "channelId"
: "subchannelId",
(referenced_entity_->type() == BaseNode::EntityType::kSubchannel)
? "subchannelId"
: "channelId",
uuid_str, GRPC_JSON_STRING, true);
json_iterator = child_ref;
}

@ -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,32 @@ 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);
RefCountedPtr<BaseNode> referenced_entity);
// void AddTraceEventWithReference(
// Severity severity, grpc_slice data,
// RefCountedPtr<SubchannelNode> referenced_entity);
// 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.
TraceEvent(Severity severity, grpc_slice data,
RefCountedPtr<ChannelNode> referenced_channel,
ReferencedType type);
RefCountedPtr<BaseNode> referenced);
// Constructor for a TraceEvent that does not reverence a different
// channel.
@ -105,10 +102,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

@ -41,6 +41,12 @@
namespace grpc_core {
namespace channelz {
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);
@ -103,11 +109,9 @@ ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
: EntityType::kInternalChannel,
channel_tracer_max_nodes),
channel_(channel),
target_(UniquePtr<char>(grpc_channel_get_target(channel_))) {
channel_uuid_ = ChannelzRegistry::Register(this);
}
target_(UniquePtr<char>(grpc_channel_get_target(channel_))) {}
ChannelNode::~ChannelNode() { ChannelzRegistry::Unregister(channel_uuid_); }
ChannelNode::~ChannelNode() {}
grpc_json* ChannelNode::RenderJson() {
// We need to track these three json objects to build our object
@ -120,7 +124,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;

@ -60,9 +60,8 @@ class BaseNode : public RefCounted<BaseNode> {
kSocket,
};
// we track is_top_level_channel to support GetTopChannels
BaseNode(EntityType type) : type_(type) {}
virtual ~BaseNode() {}
BaseNode(EntityType type);
virtual ~BaseNode();
// All children must implement this function.
virtual grpc_json* RenderJson() GRPC_ABSTRACT;
@ -72,11 +71,14 @@ class BaseNode : public RefCounted<BaseNode> {
char* RenderJsonString();
EntityType type() const { return type_; }
intptr_t uuid() const { return uuid_; }
private:
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW
friend class ChannelTrace;
EntityType type_;
intptr_t uuid_;
};
// This class is the parent for the channelz entities that deal with Channels
@ -136,8 +138,6 @@ class ChannelNode : public CallCountingAndTracingNode {
bool ChannelIsDestroyed() { return channel_ == nullptr; }
intptr_t channel_uuid() { return channel_uuid_; }
protected:
ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
bool is_top_level_channel);

@ -156,7 +156,7 @@ 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());
@ -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());
@ -191,53 +191,55 @@ TEST_P(ChannelTracerTest, ComplexTest) {
sc2.reset(nullptr);
}
// Test a case in which the parent channel has subchannels and the subchannels
// have connections. Ensures that everything lives as long as it should then
// gets deleted.
TEST_P(ChannelTracerTest, TestNesting) {
grpc_core::ExecCtx exec_ctx;
ChannelTrace tracer(GetParam());
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 2, GetParam());
ChannelFixture channel1(GetParam());
RefCountedPtr<ChannelNode> sc1 =
MakeRefCounted<ChannelNode>(channel1.channel(), GetParam(), true);
tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
ValidateChannelTrace(&tracer, 3, GetParam());
AddSimpleTrace(sc1->trace());
ChannelFixture channel2(GetParam());
RefCountedPtr<ChannelNode> conn1 =
MakeRefCounted<ChannelNode>(channel2.channel(), GetParam(), true);
// nesting one level deeper.
sc1->trace()->AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("connection one created"), conn1);
ValidateChannelTrace(&tracer, 3, GetParam());
AddSimpleTrace(conn1->trace());
AddSimpleTrace(&tracer);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 5, GetParam());
ValidateChannelTrace(conn1->trace(), 1, GetParam());
ChannelFixture channel3(GetParam());
RefCountedPtr<ChannelNode> sc2 =
MakeRefCounted<ChannelNode>(channel3.channel(), GetParam(), true);
tracer.AddTraceEventReferencingSubchannel(
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
// present in the tracer.
tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("subchannel one inactive"), sc1);
AddSimpleTrace(&tracer);
ValidateChannelTrace(&tracer, 8, GetParam());
sc1.reset(nullptr);
sc2.reset(nullptr);
conn1.reset(nullptr);
}
// // Test a case in which the parent channel has subchannels and the
// subchannels
// // have connections. Ensures that everything lives as long as it should then
// // gets deleted.
// TEST_P(ChannelTracerTest, TestNesting) {
// grpc_core::ExecCtx exec_ctx;
// ChannelTrace tracer(GetParam());
// AddSimpleTrace(&tracer);
// AddSimpleTrace(&tracer);
// ValidateChannelTrace(&tracer, 2, GetParam());
// ChannelFixture channel1(GetParam());
// RefCountedPtr<ChannelNode> sc1 =
// MakeRefCounted<ChannelNode>(channel1.channel(), GetParam(), true);
// tracer.AddTraceEventReferencingChannel(
// ChannelTrace::Severity::Info,
// grpc_slice_from_static_string("subchannel one created"), sc1);
// ValidateChannelTrace(&tracer, 3, GetParam());
// AddSimpleTrace(sc1->trace());
// ChannelFixture channel2(GetParam());
// RefCountedPtr<ChannelNode> conn1 =
// MakeRefCounted<ChannelNode>(channel2.channel(), GetParam(), true);
// // nesting one level deeper.
// sc1->trace()->AddTraceEventReferencingChannel(
// ChannelTrace::Severity::Info,
// grpc_slice_from_static_string("connection one created"), conn1);
// ValidateChannelTrace(&tracer, 3, GetParam());
// AddSimpleTrace(conn1->trace());
// AddSimpleTrace(&tracer);
// AddSimpleTrace(&tracer);
// ValidateChannelTrace(&tracer, 5, GetParam());
// ValidateChannelTrace(conn1->trace(), 1, GetParam());
// ChannelFixture channel3(GetParam());
// RefCountedPtr<ChannelNode> sc2 =
// MakeRefCounted<ChannelNode>(channel3.channel(), GetParam(), true);
// 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
// // present in the tracer.
// tracer.AddTraceEventReferencingChannel(
// ChannelTrace::Severity::Warning,
// grpc_slice_from_static_string("subchannel one inactive"), sc1);
// AddSimpleTrace(&tracer);
// ValidateChannelTrace(&tracer, 8, GetParam());
// sc1.reset(nullptr);
// sc2.reset(nullptr);
// conn1.reset(nullptr);
// }
INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest,
::testing::Values(0, 1, 2, 6, 10, 15));

@ -158,7 +158,7 @@ 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);

Loading…
Cancel
Save