aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc3
-rw-r--r--src/core/lib/channel/channel_trace.cc2
-rw-r--r--src/core/lib/channel/channel_trace.h2
-rw-r--r--src/core/lib/channel/channelz.cc37
-rw-r--r--src/core/lib/channel/channelz.h12
-rw-r--r--src/core/lib/channel/channelz_registry.cc45
-rw-r--r--src/core/lib/channel/channelz_registry.h7
-rw-r--r--src/core/lib/surface/channel.cc7
8 files changed, 98 insertions, 17 deletions
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 263b51ae89..01d05dbb14 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
@@ -1004,6 +1004,9 @@ grpc_channel_args* BuildBalancerChannelArgs(
// A channel arg indicating the target is a grpclb load balancer.
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1),
+ // A channel arg indicating the target is a grpclb load balancer.
+ grpc_channel_arg_integer_create(
+ const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL), 1),
};
// Construct channel args.
grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc
index 0f655d8716..5a4cf8c7e1 100644
--- a/src/core/lib/channel/channel_trace.cc
+++ b/src/core/lib/channel/channel_trace.cc
@@ -206,7 +206,7 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const {
}
}
-grpc_json* ChannelTrace::RenderJSON() const {
+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);
diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h
index 0dd162a777..596af7402f 100644
--- a/src/core/lib/channel/channel_trace.h
+++ b/src/core/lib/channel/channel_trace.h
@@ -71,7 +71,7 @@ class ChannelTrace {
// Creates and returns the raw grpc_json object, so a parent channelz
// object may incorporate the json before rendering.
- grpc_json* RenderJSON() const;
+ grpc_json* RenderJson() const;
private:
// Types of objects that can be references by trace events.
diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc
index 923b8043cd..c8a1d179fa 100644
--- a/src/core/lib/channel/channelz.cc
+++ b/src/core/lib/channel/channelz.cc
@@ -110,7 +110,7 @@ void ChannelNode::RecordCallStarted() {
void ChannelNode::PopulateConnectivityState(grpc_json* json) {}
-char* ChannelNode::RenderJSON() {
+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;
@@ -130,13 +130,14 @@ char* ChannelNode::RenderJSON() {
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);
// fill in the channel trace if applicable
- grpc_json* trace = trace_->RenderJSON();
+ grpc_json* trace = trace_->RenderJson();
if (trace != nullptr) {
// we manuall link up and fill the child since it was created for us in
- // ChannelTrace::RenderJSON
+ // ChannelTrace::RenderJson
json_iterator = grpc_json_link_child(json, trace, json_iterator);
trace->parent = json;
trace->value = nullptr;
@@ -146,22 +147,30 @@ char* ChannelNode::RenderJSON() {
// reset the parent to be the data object.
json = data;
json_iterator = nullptr;
- // We use -1 as sentinel values since proto default value for integers is
- // zero, and the confuses the parser into thinking the value weren't present
- json_iterator =
- add_num_str(json, json_iterator, "callsStarted", calls_started_);
- json_iterator =
- add_num_str(json, json_iterator, "callsSucceeded", calls_succeeded_);
- json_iterator =
- add_num_str(json, json_iterator, "callsFailed", calls_failed_);
+ if (calls_started_ != 0) {
+ json_iterator =
+ add_num_str(json, json_iterator, "callsStarted", calls_started_);
+ }
+ if (calls_succeeded_ != 0) {
+ json_iterator =
+ add_num_str(json, json_iterator, "callsSucceeded", calls_succeeded_);
+ }
+ if (calls_failed_) {
+ json_iterator =
+ add_num_str(json, json_iterator, "callsFailed", calls_failed_);
+ }
gpr_timespec ts =
grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME);
json_iterator =
grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
fmt_time(ts), GRPC_JSON_STRING, true);
- // render and return the over json object
- char* json_str = grpc_json_dump_to_string(top_level_json, 0);
- grpc_json_destroy(top_level_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;
}
diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h
index 9bd01ece50..abcf907c2b 100644
--- a/src/core/lib/channel/channelz.h
+++ b/src/core/lib/channel/channelz.h
@@ -35,6 +35,10 @@
#define GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC \
"grpc.channelz_channel_node_creation_func"
+// Channel arg key to signal that the channel is an internal channel.
+#define GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL \
+ "grpc.channelz_channel_is_internal_channel"
+
namespace grpc_core {
namespace channelz {
@@ -55,7 +59,8 @@ class ChannelNode : public RefCounted<ChannelNode> {
gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1)));
}
- char* RenderJSON();
+ grpc_json* RenderJson();
+ char* RenderJsonString();
// helper for getting and populating connectivity state. It is virtual
// because it allows the client_channel specific code to live in ext/
@@ -72,6 +77,10 @@ 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_; }
+ void set_is_top_level_channel(bool is_top_level_channel) {
+ is_top_level_channel_ = is_top_level_channel;
+ }
protected:
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
@@ -90,6 +99,7 @@ class ChannelNode : public RefCounted<ChannelNode> {
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_;
};
diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc
index 43cace1975..b4dc3d1103 100644
--- a/src/core/lib/channel/channelz_registry.cc
+++ b/src/core/lib/channel/channelz_registry.cc
@@ -19,6 +19,7 @@
#include <grpc/impl/codegen/port_platform.h>
#include "src/core/lib/channel/channel_trace.h"
+#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/memory.h"
@@ -64,6 +65,7 @@ void ChannelzRegistry::InternalUnregisterEntry(intptr_t uuid, EntityType type) {
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;
}
void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) {
@@ -78,5 +80,48 @@ void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) {
}
}
+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;
+ // uuids index into entities one-off (idx 0 is really uuid 1, since 0 is
+ // reserver). However, we want to support requests coming in which
+ // 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 (top_level_channels.size() > 0) {
+ // create list of channels
+ grpc_json* array_parent = grpc_json_create_child(
+ nullptr, json, "channel", nullptr, GRPC_JSON_ARRAY, false);
+ for (size_t i = 0; i < top_level_channels.size(); ++i) {
+ grpc_json* channel_json = top_level_channels[i]->RenderJson();
+ json_iterator =
+ grpc_json_link_child(array_parent, channel_json, json_iterator);
+ channel_json->parent = array_parent;
+ channel_json->value = nullptr;
+ channel_json->key = nullptr;
+ channel_json->owns_value = false;
+ }
+ }
+ // For now we do not have any pagination rules. In the future we could
+ // pick a constant for max_channels_sent for a GetTopChannels request.
+ // Tracking: https://github.com/grpc/grpc/issues/16019.
+ json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr,
+ GRPC_JSON_TRUE, false);
+ char* json_str = grpc_json_dump_to_string(top_level_json, 0);
+ grpc_json_destroy(top_level_json);
+ return json_str;
+}
+
} // namespace channelz
} // namespace grpc_core
diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h
index cc069d9145..2fefc9f629 100644
--- a/src/core/lib/channel/channelz_registry.h
+++ b/src/core/lib/channel/channelz_registry.h
@@ -51,6 +51,11 @@ class ChannelzRegistry {
return gotten == nullptr ? nullptr : static_cast<ChannelNode*>(gotten);
}
+ // todo, protect me
+ static char* GetTopChannels(intptr_t start_channel_id) {
+ return Default()->InternalGetTopChannels(start_channel_id);
+ }
+
private:
enum class EntityType {
kChannelNode,
@@ -84,6 +89,8 @@ class ChannelzRegistry {
// returns the void* associated with that uuid. Else returns nullptr.
void* InternalGetEntry(intptr_t uuid, EntityType type);
+ char* InternalGetTopChannels(intptr_t start_channel_id);
+
// protects entities_ and uuid_
gpr_mu mu_;
InlinedVector<RegistryEntry, 20> entities_;
diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc
index 8f3ad6c191..dd3880f18e 100644
--- a/src/core/lib/surface/channel.cc
+++ b/src/core/lib/surface/channel.cc
@@ -105,6 +105,7 @@ grpc_channel* grpc_channel_create_with_builder(
channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type);
size_t channel_tracer_max_nodes = 0; // default to off
bool channelz_enabled = false;
+ bool internal_channel = false;
// this creates the default ChannelNode. Different types of channels may
// override this to ensure a correct ChannelNode is created.
grpc_core::channelz::ChannelNodeCreationFunc channel_node_create_func =
@@ -158,6 +159,9 @@ grpc_channel* grpc_channel_create_with_builder(
channel_node_create_func =
reinterpret_cast<grpc_core::channelz::ChannelNodeCreationFunc>(
args->args[i].value.pointer.p);
+ } else if (0 == strcmp(args->args[i].key,
+ GRPC_ARG_CHANNELZ_CHANNEL_IS_INTERNAL_CHANNEL)) {
+ internal_channel = grpc_channel_arg_get_bool(&args->args[i], false);
}
}
@@ -165,6 +169,9 @@ grpc_channel* grpc_channel_create_with_builder(
if (channelz_enabled) {
channel->channelz_channel =
channel_node_create_func(channel, channel_tracer_max_nodes);
+ if (internal_channel || !channel->is_client) {
+ channel->channelz_channel->set_is_top_level_channel(false);
+ }
channel->channelz_channel->trace()->AddTraceEvent(
grpc_core::channelz::ChannelTrace::Severity::Info,
grpc_slice_from_static_string("Channel created"));