Merge pull request #21242 from markdroth/json_new_api

Convert channelz code to use new JSON API
pull/21866/head
Mark D. Roth 5 years ago committed by GitHub
commit 2e7d6b94ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 78
      src/core/ext/filters/client_channel/client_channel_channelz.cc
  2. 4
      src/core/ext/filters/client_channel/client_channel_channelz.h
  3. 73
      src/core/lib/channel/channel_trace.cc
  4. 6
      src/core/lib/channel/channel_trace.h
  5. 406
      src/core/lib/channel/channelz.cc
  6. 19
      src/core/lib/channel/channelz.h
  7. 121
      src/core/lib/channel/channelz_registry.cc
  8. 8
      src/core/lib/channel/channelz_registry.h
  9. 5
      src/cpp/server/channelz/channelz_service.cc
  10. 60
      test/core/channel/channel_trace_test.cc
  11. 290
      test/core/channel/channelz_test.cc
  12. 65
      test/core/end2end/tests/channelz.cc
  13. 22
      test/core/end2end/tests/retry_streaming.cc
  14. 30
      test/cpp/util/channel_trace_proto_helper.cc
  15. 16
      test/cpp/util/channel_trace_proto_helper.h

@ -47,64 +47,48 @@ void SubchannelNode::SetChildSocket(RefCountedPtr<SocketNode> socket) {
child_socket_ = std::move(socket);
}
void SubchannelNode::PopulateConnectivityState(grpc_json* json) {
Json SubchannelNode::RenderJson() {
// Create and fill the data child.
grpc_connectivity_state state =
connectivity_state_.Load(MemoryOrder::RELAXED);
json = grpc_json_create_child(nullptr, json, "state", nullptr,
GRPC_JSON_OBJECT, false);
grpc_json_create_child(nullptr, json, "state", ConnectivityStateName(state),
GRPC_JSON_STRING, false);
}
Json::Object data = {
{"state",
Json::Object{
{"state", ConnectivityStateName(state)},
}},
{"target", target_},
};
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_.empty());
grpc_json_create_child(nullptr, json, "target", target_.c_str(),
GRPC_JSON_STRING, false);
// fill in the channel trace if applicable
grpc_json* trace_json = trace_.RenderJson();
if (trace_json != nullptr) {
trace_json->key = "trace"; // this object is named trace in channelz.proto
grpc_json_link_child(json, trace_json, nullptr);
// Fill in the channel trace if applicable
Json trace_json = trace_.RenderJson();
if (trace_json.type() != Json::Type::JSON_NULL) {
data["trace"] = std::move(trace_json);
}
// ask CallCountingHelper to populate trace and call count data.
call_counter_.PopulateCallCounts(json);
json = top_level_json;
// populate the child socket.
// Ask CallCountingHelper to populate call count data.
call_counter_.PopulateCallCounts(&data);
// Construct top-level object.
Json::Object object{
{"ref",
Json::Object{
{"subchannelId", std::to_string(uuid())},
}},
{"data", std::move(data)},
};
// Populate the child socket.
RefCountedPtr<SocketNode> child_socket;
{
MutexLock lock(&socket_mu_);
child_socket = child_socket_;
}
if (child_socket != nullptr && child_socket->uuid() != 0) {
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false);
json_iterator = grpc_json_create_child(json_iterator, array_parent, nullptr,
nullptr, GRPC_JSON_OBJECT, false);
grpc_json* sibling_iterator = grpc_json_add_number_string_child(
json_iterator, nullptr, "socketId", child_socket->uuid());
grpc_json_create_child(sibling_iterator, json_iterator, "name",
child_socket->name().c_str(), GRPC_JSON_STRING,
false);
object["socketRef"] = Json::Array{
Json::Object{
{"socketId", std::to_string(child_socket->uuid())},
{"name", child_socket->name()},
},
};
}
return top_level_json;
return object;
}
} // namespace channelz

@ -47,7 +47,7 @@ class SubchannelNode : public BaseNode {
// subchannel unrefs the transport.
void SetChildSocket(RefCountedPtr<SocketNode> socket);
grpc_json* RenderJson() override;
Json RenderJson() override;
// proxy methods to composed classes.
void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
@ -64,8 +64,6 @@ class SubchannelNode : public BaseNode {
void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
private:
void PopulateConnectivityState(grpc_json* json);
Atomic<grpc_connectivity_state> connectivity_state_{GRPC_CHANNEL_IDLE};
Mutex socket_mu_;
RefCountedPtr<SocketNode> child_socket_;

@ -144,59 +144,50 @@ const char* severity_string(ChannelTrace::Severity severity) {
} // anonymous namespace
void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const {
grpc_json* json_iterator = nullptr;
json_iterator = grpc_json_create_child(json_iterator, json, "description",
grpc_slice_to_c_string(data_),
GRPC_JSON_STRING, true);
json_iterator = grpc_json_create_child(json_iterator, json, "severity",
severity_string(severity_),
GRPC_JSON_STRING, false);
json_iterator = grpc_json_create_child(json_iterator, json, "timestamp",
gpr_format_timespec(timestamp_),
GRPC_JSON_STRING, true);
Json ChannelTrace::TraceEvent::RenderTraceEvent() const {
char* description = grpc_slice_to_c_string(data_);
char* ts_str = gpr_format_timespec(timestamp_);
Json::Object object = {
{"description", description},
{"severity", severity_string(severity_)},
{"timestamp", ts_str},
};
gpr_free(description);
gpr_free(ts_str);
if (referenced_entity_ != nullptr) {
const bool is_channel =
(referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel ||
referenced_entity_->type() == BaseNode::EntityType::kInternalChannel);
char* uuid_str;
gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid());
grpc_json* child_ref = grpc_json_create_child(
json_iterator, json, is_channel ? "channelRef" : "subchannelRef",
nullptr, GRPC_JSON_OBJECT, false);
json_iterator = grpc_json_create_child(
nullptr, child_ref, is_channel ? "channelId" : "subchannelId", uuid_str,
GRPC_JSON_STRING, true);
json_iterator = child_ref;
object[is_channel ? "channelRef" : "subchannelRef"] = Json::Object{
{(is_channel ? "channelId" : "subchannelId"),
std::to_string(referenced_entity_->uuid())},
};
}
return object;
}
grpc_json* ChannelTrace::RenderJson() const {
if (max_event_memory_ == 0)
return nullptr; // tracing is disabled if max_event_memory_ == 0
grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json_iterator = nullptr;
Json ChannelTrace::RenderJson() const {
// Tracing is disabled if max_event_memory_ == 0.
if (max_event_memory_ == 0) {
return Json(); // JSON null
}
char* ts_str = gpr_format_timespec(time_created_);
Json::Object object = {
{"creationTimestamp", ts_str},
};
gpr_free(ts_str);
if (num_events_logged_ > 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "numEventsLogged", num_events_logged_);
object["numEventsLogged"] = std::to_string(num_events_logged_);
}
json_iterator = grpc_json_create_child(
json_iterator, json, "creationTimestamp",
gpr_format_timespec(time_created_), GRPC_JSON_STRING, true);
// only add in the event list if it is non-empty.
// Only add in the event list if it is non-empty.
if (head_trace_ != nullptr) {
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();
Json::Array array;
for (TraceEvent* it = head_trace_; it != nullptr; it = it->next()) {
array.emplace_back(it->RenderTraceEvent());
}
object["events"] = std::move(array);
}
return json;
return object;
}
} // namespace channelz

@ -75,9 +75,9 @@ class ChannelTrace {
void AddTraceEventWithReference(Severity severity, const grpc_slice& data,
RefCountedPtr<BaseNode> referenced_entity);
// Creates and returns the raw grpc_json object, so a parent channelz
// Creates and returns the raw Json object, so a parent channelz
// object may incorporate the json before rendering.
grpc_json* RenderJson() const;
Json RenderJson() const;
private:
friend size_t testing::GetSizeofTraceEvent(void);
@ -98,7 +98,7 @@ class ChannelTrace {
// Renders the data inside of this TraceEvent into a json object. This is
// used by the ChannelTrace, when it is rendering itself.
void RenderTraceEvent(grpc_json* json) const;
Json RenderTraceEvent() const;
// set and get for the next_ pointer.
TraceEvent* next() const { return next_; }

@ -94,12 +94,9 @@ BaseNode::BaseNode(EntityType type, std::string name)
BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); }
char* BaseNode::RenderJsonString() {
grpc_json* json = RenderJson();
GPR_ASSERT(json != nullptr);
char* json_str = grpc_json_dump_to_string(json, 0);
grpc_json_destroy(json);
return json_str;
std::string BaseNode::RenderJsonString() {
Json json = RenderJson();
return json.Dump();
}
//
@ -151,29 +148,23 @@ void CallCountingHelper::CollectData(CounterData* out) {
}
}
void CallCountingHelper::PopulateCallCounts(grpc_json* json) {
grpc_json* json_iterator = nullptr;
void CallCountingHelper::PopulateCallCounts(Json::Object* object) {
CounterData data;
CollectData(&data);
if (data.calls_started != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "callsStarted", data.calls_started);
(*object)["callsStarted"] = std::to_string(data.calls_started);
gpr_timespec ts = gpr_convert_clock_type(
gpr_cycle_counter_to_time(data.last_call_started_cycle),
GPR_CLOCK_REALTIME);
char* ts_str = gpr_format_timespec(ts);
(*object)["lastCallStartedTimestamp"] = ts_str;
gpr_free(ts_str);
}
if (data.calls_succeeded != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "callsSucceeded", data.calls_succeeded);
(*object)["callsSucceeded"] = std::to_string(data.calls_succeeded);
}
if (data.calls_failed) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "callsFailed", data.calls_failed);
}
if (data.calls_started != 0) {
gpr_timespec ts = gpr_convert_clock_type(
gpr_cycle_counter_to_time(data.last_call_started_cycle),
GPR_CLOCK_REALTIME);
json_iterator =
grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
(*object)["callsFailed"] = std::to_string(data.calls_failed);
}
}
@ -207,82 +198,60 @@ const char* ChannelNode::GetChannelConnectivityStateChangeString(
GPR_UNREACHABLE_CODE(return "UNKNOWN");
}
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;
// 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;
// connectivity state
Json ChannelNode::RenderJson() {
Json::Object data = {
{"target", target_},
};
// Connectivity state.
// If low-order bit is on, then the field is set.
int state_field = connectivity_state_.Load(MemoryOrder::RELAXED);
if ((state_field & 1) != 0) {
grpc_connectivity_state state =
static_cast<grpc_connectivity_state>(state_field >> 1);
json = grpc_json_create_child(nullptr, json, "state", nullptr,
GRPC_JSON_OBJECT, false);
grpc_json_create_child(nullptr, json, "state", ConnectivityStateName(state),
GRPC_JSON_STRING, false);
json = data;
data["state"] = Json::Object{
{"state", ConnectivityStateName(state)},
};
}
// populate the target.
GPR_ASSERT(!target_.empty());
grpc_json_create_child(nullptr, json, "target", target_.c_str(),
GRPC_JSON_STRING, false);
// fill in the channel trace if applicable
grpc_json* trace_json = trace_.RenderJson();
if (trace_json != nullptr) {
trace_json->key = "trace"; // this object is named trace in channelz.proto
grpc_json_link_child(json, trace_json, nullptr);
// Fill in the channel trace if applicable.
Json trace_json = trace_.RenderJson();
if (trace_json.type() != Json::Type::JSON_NULL) {
data["trace"] = std::move(trace_json);
}
// ask CallCountingHelper to populate trace and call count data.
call_counter_.PopulateCallCounts(json);
json = top_level_json;
// template method. Child classes may override this to add their specific
// Ask CallCountingHelper to populate call count data.
call_counter_.PopulateCallCounts(&data);
// Construct outer object.
Json::Object json = {
{"ref",
Json::Object{
{"channelId", std::to_string(uuid())},
}},
{"data", std::move(data)},
};
// Template method. Child classes may override this to add their specific
// functionality.
PopulateChildRefs(json);
return top_level_json;
PopulateChildRefs(&json);
return json;
}
void ChannelNode::PopulateChildRefs(grpc_json* json) {
void ChannelNode::PopulateChildRefs(Json::Object* json) {
MutexLock lock(&child_mu_);
grpc_json* json_iterator = nullptr;
if (!child_subchannels_.empty()) {
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "subchannelRef", nullptr, GRPC_JSON_ARRAY, false);
Json::Array array;
for (const auto& p : child_subchannels_) {
json_iterator =
grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
GRPC_JSON_OBJECT, false);
grpc_json_add_number_string_child(json_iterator, nullptr, "subchannelId",
p.first);
array.emplace_back(Json::Object{
{"subchannelId", std::to_string(p.first)},
});
}
(*json)["subchannelRef"] = std::move(array);
}
if (!child_channels_.empty()) {
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "channelRef", nullptr, GRPC_JSON_ARRAY, false);
json_iterator = nullptr;
Json::Array array;
for (const auto& p : child_channels_) {
json_iterator =
grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
GRPC_JSON_OBJECT, false);
grpc_json_add_number_string_child(json_iterator, nullptr, "channelId",
p.first);
array.emplace_back(Json::Object{
{"channelId", std::to_string(p.first)},
});
}
(*json)["channelRef"] = std::move(array);
}
}
@ -341,87 +310,66 @@ void ServerNode::RemoveChildListenSocket(intptr_t child_uuid) {
child_listen_sockets_.erase(child_uuid);
}
char* ServerNode::RenderServerSockets(intptr_t start_socket_id,
intptr_t max_results) {
std::string ServerNode::RenderServerSockets(intptr_t start_socket_id,
intptr_t max_results) {
// If user does not set max_results, we choose 500.
size_t pagination_limit = max_results == 0 ? 500 : max_results;
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json = top_level_json;
grpc_json* json_iterator = nullptr;
MutexLock lock(&child_mu_);
size_t sockets_rendered = 0;
if (!child_sockets_.empty()) {
// Create list of socket refs
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false);
const size_t limit = GPR_MIN(child_sockets_.size(), pagination_limit);
for (auto it = child_sockets_.lower_bound(start_socket_id);
it != child_sockets_.end() && sockets_rendered < limit;
++it, ++sockets_rendered) {
grpc_json* socket_ref_json = grpc_json_create_child(
nullptr, array_parent, nullptr, nullptr, GRPC_JSON_OBJECT, false);
json_iterator = grpc_json_add_number_string_child(
socket_ref_json, nullptr, "socketId", it->first);
grpc_json_create_child(json_iterator, socket_ref_json, "name",
it->second->name().c_str(), GRPC_JSON_STRING,
false);
Json::Object object;
{
MutexLock lock(&child_mu_);
size_t sockets_rendered = 0;
if (!child_sockets_.empty()) {
// Create list of socket refs.
Json::Array array;
const size_t limit = GPR_MIN(child_sockets_.size(), pagination_limit);
for (auto it = child_sockets_.lower_bound(start_socket_id);
it != child_sockets_.end() && sockets_rendered < limit;
++it, ++sockets_rendered) {
array.emplace_back(Json::Object{
{"socketId", std::to_string(it->first)},
{"name", it->second->name()},
});
}
object["socketRef"] = std::move(array);
}
if (sockets_rendered == child_sockets_.size()) object["end"] = true;
}
if (sockets_rendered == child_sockets_.size()) {
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;
Json json = std::move(object);
return json.Dump();
}
grpc_json* ServerNode::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,
"serverId", 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;
// fill in the channel trace if applicable
grpc_json* trace_json = trace_.RenderJson();
if (trace_json != nullptr) {
trace_json->key = "trace"; // this object is named trace in channelz.proto
grpc_json_link_child(json, trace_json, nullptr);
Json ServerNode::RenderJson() {
Json::Object data;
// Fill in the channel trace if applicable.
Json trace_json = trace_.RenderJson();
if (trace_json.type() != Json::Type::JSON_NULL) {
data["trace"] = std::move(trace_json);
}
// ask CallCountingHelper to populate trace and call count data.
call_counter_.PopulateCallCounts(json);
json = top_level_json;
// Render listen sockets
MutexLock lock(&child_mu_);
if (!child_listen_sockets_.empty()) {
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "listenSocket", nullptr, GRPC_JSON_ARRAY, false);
for (const auto& it : child_listen_sockets_) {
json_iterator =
grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
GRPC_JSON_OBJECT, false);
grpc_json* sibling_iterator = grpc_json_add_number_string_child(
json_iterator, nullptr, "socketId", it.first);
grpc_json_create_child(sibling_iterator, json_iterator, "name",
it.second->name().c_str(), GRPC_JSON_STRING,
false);
// Ask CallCountingHelper to populate call count data.
call_counter_.PopulateCallCounts(&data);
// Construct top-level object.
Json::Object object = {
{"ref",
Json::Object{
{"serverId", std::to_string(uuid())},
}},
{"data", std::move(data)},
};
// Render listen sockets.
{
MutexLock lock(&child_mu_);
if (!child_listen_sockets_.empty()) {
Json::Array array;
for (const auto& it : child_listen_sockets_) {
array.emplace_back(Json::Object{
{"socketId", std::to_string(it.first)},
{"name", it.second->name()},
});
}
object["listenSocket"] = std::move(array);
}
}
return top_level_json;
return object;
}
//
@ -430,14 +378,10 @@ grpc_json* ServerNode::RenderJson() {
namespace {
void PopulateSocketAddressJson(grpc_json* json, const char* name,
void PopulateSocketAddressJson(Json::Object* json, const char* name,
const char* addr_str) {
if (addr_str == nullptr) return;
grpc_json* json_iterator = nullptr;
json_iterator = grpc_json_create_child(json_iterator, json, name, nullptr,
GRPC_JSON_OBJECT, false);
json = json_iterator;
json_iterator = nullptr;
Json::Object data;
grpc_uri* uri = grpc_uri_parse(addr_str, true);
if ((uri != nullptr) && ((strcmp(uri->scheme, "ipv4") == 0) ||
(strcmp(uri->scheme, "ipv6") == 0))) {
@ -452,31 +396,22 @@ void PopulateSocketAddressJson(grpc_json* json, const char* name,
}
char* b64_host =
grpc_base64_encode(host.get(), strlen(host.get()), false, false);
json_iterator = grpc_json_create_child(json_iterator, json, "tcpip_address",
nullptr, GRPC_JSON_OBJECT, false);
json = json_iterator;
json_iterator = nullptr;
json_iterator = grpc_json_add_number_string_child(json, json_iterator,
"port", port_num);
json_iterator = grpc_json_create_child(json_iterator, json, "ip_address",
b64_host, GRPC_JSON_STRING, true);
data["tcpip_address"] = Json::Object{
{"port", port_num},
{"ip_address", b64_host},
};
gpr_free(b64_host);
} else if (uri != nullptr && strcmp(uri->scheme, "unix") == 0) {
json_iterator = grpc_json_create_child(json_iterator, json, "uds_address",
nullptr, GRPC_JSON_OBJECT, false);
json = json_iterator;
json_iterator = nullptr;
json_iterator =
grpc_json_create_child(json_iterator, json, "filename",
gpr_strdup(uri->path), GRPC_JSON_STRING, true);
data["uds_address"] = Json::Object{
{"filename", uri->path},
};
} else {
json_iterator = grpc_json_create_child(json_iterator, json, "other_address",
nullptr, GRPC_JSON_OBJECT, false);
json = json_iterator;
json_iterator = nullptr;
json_iterator = grpc_json_create_child(json_iterator, json, "name",
addr_str, GRPC_JSON_STRING, false);
data["other_address"] = Json::Object{
{"name", addr_str},
};
}
grpc_uri_destroy(uri);
(*json)[name] = std::move(data);
}
} // namespace
@ -509,45 +444,22 @@ void SocketNode::RecordMessageReceived() {
MemoryOrder::RELAXED);
}
grpc_json* SocketNode::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,
"socketId", uuid());
json_iterator = grpc_json_create_child(
json_iterator, json, "name", name().c_str(), GRPC_JSON_STRING, false);
json = top_level_json;
PopulateSocketAddressJson(json, "remote", remote_.c_str());
PopulateSocketAddressJson(json, "local", local_.c_str());
// 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;
Json SocketNode::RenderJson() {
// Create and fill the data child.
Json::Object data;
gpr_timespec ts;
int64_t streams_started = streams_started_.Load(MemoryOrder::RELAXED);
if (streams_started != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "streamsStarted", streams_started);
data["streamsStarted"] = std::to_string(streams_started);
gpr_cycle_counter last_local_stream_created_cycle =
last_local_stream_created_cycle_.Load(MemoryOrder::RELAXED);
if (last_local_stream_created_cycle != 0) {
ts = gpr_convert_clock_type(
gpr_cycle_counter_to_time(last_local_stream_created_cycle),
GPR_CLOCK_REALTIME);
json_iterator = grpc_json_create_child(
json_iterator, json, "lastLocalStreamCreatedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
char* ts_str = gpr_format_timespec(ts);
data["lastLocalStreamCreatedTimestamp"] = ts_str;
gpr_free(ts_str);
}
gpr_cycle_counter last_remote_stream_created_cycle =
last_remote_stream_created_cycle_.Load(MemoryOrder::RELAXED);
@ -555,51 +467,57 @@ grpc_json* SocketNode::RenderJson() {
ts = gpr_convert_clock_type(
gpr_cycle_counter_to_time(last_remote_stream_created_cycle),
GPR_CLOCK_REALTIME);
json_iterator = grpc_json_create_child(
json_iterator, json, "lastRemoteStreamCreatedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
char* ts_str = gpr_format_timespec(ts);
data["lastRemoteStreamCreatedTimestamp"] = ts_str;
gpr_free(ts_str);
}
}
int64_t streams_succeeded = streams_succeeded_.Load(MemoryOrder::RELAXED);
if (streams_succeeded != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "streamsSucceeded", streams_succeeded);
data["streamsSucceeded"] = std::to_string(streams_succeeded);
}
int64_t streams_failed = streams_failed_.Load(MemoryOrder::RELAXED);
if (streams_failed) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "streamsFailed", streams_failed);
if (streams_failed != 0) {
data["streamsFailed"] = std::to_string(streams_failed);
}
int64_t messages_sent = messages_sent_.Load(MemoryOrder::RELAXED);
if (messages_sent != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "messagesSent", messages_sent);
data["messagesSent"] = std::to_string(messages_sent);
ts = gpr_convert_clock_type(
gpr_cycle_counter_to_time(
last_message_sent_cycle_.Load(MemoryOrder::RELAXED)),
GPR_CLOCK_REALTIME);
json_iterator =
grpc_json_create_child(json_iterator, json, "lastMessageSentTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
char* ts_str = gpr_format_timespec(ts);
data["lastMessageSentTimestamp"] = ts_str;
gpr_free(ts_str);
}
int64_t messages_received = messages_received_.Load(MemoryOrder::RELAXED);
if (messages_received != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "messagesReceived", messages_received);
data["messagesReceived"] = std::to_string(messages_received);
ts = gpr_convert_clock_type(
gpr_cycle_counter_to_time(
last_message_received_cycle_.Load(MemoryOrder::RELAXED)),
GPR_CLOCK_REALTIME);
json_iterator = grpc_json_create_child(
json_iterator, json, "lastMessageReceivedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
char* ts_str = gpr_format_timespec(ts);
data["lastMessageReceivedTimestamp"] = ts_str;
gpr_free(ts_str);
}
int64_t keepalives_sent = keepalives_sent_.Load(MemoryOrder::RELAXED);
if (keepalives_sent != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "keepAlivesSent", keepalives_sent);
data["keepAlivesSent"] = std::to_string(keepalives_sent);
}
return top_level_json;
// Create and fill the parent object.
Json::Object object = {
{"ref",
Json::Object{
{"socketId", std::to_string(uuid())},
{"name", name()},
}},
{"data", std::move(data)},
};
PopulateSocketAddressJson(&object, "remote", remote_.c_str());
PopulateSocketAddressJson(&object, "local", local_.c_str());
return object;
}
//
@ -610,24 +528,16 @@ ListenSocketNode::ListenSocketNode(std::string local_addr, std::string name)
: BaseNode(EntityType::kSocket, std::move(name)),
local_addr_(std::move(local_addr)) {}
grpc_json* ListenSocketNode::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,
"socketId", uuid());
json_iterator = grpc_json_create_child(
json_iterator, json, "name", name().c_str(), GRPC_JSON_STRING, false);
json = top_level_json;
PopulateSocketAddressJson(json, "local", local_addr_.c_str());
return top_level_json;
Json ListenSocketNode::RenderJson() {
Json::Object object = {
{"ref",
Json::Object{
{"socketId", std::to_string(uuid())},
{"name", name()},
}},
};
PopulateSocketAddressJson(&object, "local", local_addr_.c_str());
return object;
}
} // namespace channelz

@ -91,11 +91,11 @@ class BaseNode : public RefCounted<BaseNode> {
virtual ~BaseNode();
// All children must implement this function.
virtual grpc_json* RenderJson() = 0;
virtual Json RenderJson() = 0;
// Renders the json and returns allocated string that must be freed by the
// caller.
char* RenderJsonString();
std::string RenderJsonString();
EntityType type() const { return type_; }
intptr_t uuid() const { return uuid_; }
@ -124,7 +124,7 @@ class CallCountingHelper {
void RecordCallSucceeded();
// Common rendering of the call count data and last_call_started_timestamp.
void PopulateCallCounts(grpc_json* json);
void PopulateCallCounts(Json::Object* json);
private:
// testing peer friend.
@ -187,7 +187,7 @@ class ChannelNode : public BaseNode {
intptr_t parent_uuid() const { return parent_uuid_; }
grpc_json* RenderJson() override;
Json RenderJson() override;
// proxy methods to composed classes.
void AddTraceEvent(ChannelTrace::Severity severity, const grpc_slice& data) {
@ -216,7 +216,7 @@ class ChannelNode : public BaseNode {
void RemoveChildSubchannel(intptr_t child_uuid);
private:
void PopulateChildRefs(grpc_json* json);
void PopulateChildRefs(Json::Object* json);
// to allow the channel trace test to access trace_.
friend class testing::ChannelNodePeer;
@ -245,9 +245,10 @@ class ServerNode : public BaseNode {
~ServerNode() override;
grpc_json* RenderJson() override;
Json RenderJson() override;
char* RenderServerSockets(intptr_t start_socket_id, intptr_t max_results);
std::string RenderServerSockets(intptr_t start_socket_id,
intptr_t max_results);
void AddChildSocket(RefCountedPtr<SocketNode> node);
@ -285,7 +286,7 @@ class SocketNode : public BaseNode {
SocketNode(std::string local, std::string remote, std::string name);
~SocketNode() override {}
grpc_json* RenderJson() override;
Json RenderJson() override;
void RecordStreamStartedFromLocal();
void RecordStreamStartedFromRemote();
@ -324,7 +325,7 @@ class ListenSocketNode : public BaseNode {
ListenSocketNode(std::string local_addr, std::string name);
~ListenSocketNode() override {}
grpc_json* RenderJson() override;
Json RenderJson() override;
private:
std::string local_addr_;

@ -30,6 +30,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
namespace grpc_core {
@ -79,10 +80,8 @@ RefCountedPtr<BaseNode> ChannelzRegistry::InternalGet(intptr_t uuid) {
return RefCountedPtr<BaseNode>(node);
}
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;
std::string ChannelzRegistry::InternalGetTopChannels(
intptr_t start_channel_id) {
InlinedVector<RefCountedPtr<BaseNode>, 10> top_level_channels;
RefCountedPtr<BaseNode> node_after_pagination_limit;
{
@ -106,29 +105,21 @@ char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) {
}
}
}
Json::Object object;
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);
// Create list of channels.
Json::Array array;
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);
array.emplace_back(top_level_channels[i]->RenderJson());
}
object["channel"] = std::move(array);
}
if (node_after_pagination_limit == nullptr) {
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;
if (node_after_pagination_limit == nullptr) object["end"] = true;
Json json(std::move(object));
return json.Dump();
}
char* ChannelzRegistry::InternalGetServers(intptr_t start_server_id) {
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json = top_level_json;
grpc_json* json_iterator = nullptr;
std::string ChannelzRegistry::InternalGetServers(intptr_t start_server_id) {
InlinedVector<RefCountedPtr<BaseNode>, 10> servers;
RefCountedPtr<BaseNode> node_after_pagination_limit;
{
@ -152,23 +143,18 @@ char* ChannelzRegistry::InternalGetServers(intptr_t start_server_id) {
}
}
}
Json::Object object;
if (!servers.empty()) {
// create list of servers
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "server", nullptr, GRPC_JSON_ARRAY, false);
// Create list of servers.
Json::Array array;
for (size_t i = 0; i < servers.size(); ++i) {
grpc_json* server_json = servers[i]->RenderJson();
json_iterator =
grpc_json_link_child(array_parent, server_json, json_iterator);
array.emplace_back(servers[i]->RenderJson());
}
object["server"] = std::move(array);
}
if (node_after_pagination_limit == nullptr) {
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;
if (node_after_pagination_limit == nullptr) object["end"] = true;
Json json(std::move(object));
return json.Dump();
}
void ChannelzRegistry::InternalLogAllEntities() {
@ -183,9 +169,8 @@ void ChannelzRegistry::InternalLogAllEntities() {
}
}
for (size_t i = 0; i < nodes.size(); ++i) {
char* json = nodes[i]->RenderJsonString();
gpr_log(GPR_INFO, "%s", json);
gpr_free(json);
std::string json = nodes[i]->RenderJsonString();
gpr_log(GPR_INFO, "%s", json.c_str());
}
}
@ -193,12 +178,15 @@ void ChannelzRegistry::InternalLogAllEntities() {
} // namespace grpc_core
char* grpc_channelz_get_top_channels(intptr_t start_channel_id) {
return grpc_core::channelz::ChannelzRegistry::GetTopChannels(
start_channel_id);
return gpr_strdup(
grpc_core::channelz::ChannelzRegistry::GetTopChannels(start_channel_id)
.c_str());
}
char* grpc_channelz_get_servers(intptr_t start_server_id) {
return grpc_core::channelz::ChannelzRegistry::GetServers(start_server_id);
return gpr_strdup(
grpc_core::channelz::ChannelzRegistry::GetServers(start_server_id)
.c_str());
}
char* grpc_channelz_get_server(intptr_t server_id) {
@ -209,14 +197,10 @@ char* grpc_channelz_get_server(intptr_t server_id) {
grpc_core::channelz::BaseNode::EntityType::kServer) {
return nullptr;
}
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json = top_level_json;
grpc_json* channel_json = server_node->RenderJson();
channel_json->key = "server";
grpc_json_link_child(json, channel_json, nullptr);
char* json_str = grpc_json_dump_to_string(top_level_json, 0);
grpc_json_destroy(top_level_json);
return json_str;
grpc_core::Json json = grpc_core::Json::Object{
{"server", server_node->RenderJson()},
};
return gpr_strdup(json.Dump().c_str());
}
char* grpc_channelz_get_server_sockets(intptr_t server_id,
@ -229,10 +213,11 @@ char* grpc_channelz_get_server_sockets(intptr_t server_id,
return nullptr;
}
// This cast is ok since we have just checked to make sure base_node is
// actually a server node
// actually a server node.
grpc_core::channelz::ServerNode* server_node =
static_cast<grpc_core::channelz::ServerNode*>(base_node.get());
return server_node->RenderServerSockets(start_socket_id, max_results);
return gpr_strdup(
server_node->RenderServerSockets(start_socket_id, max_results).c_str());
}
char* grpc_channelz_get_channel(intptr_t channel_id) {
@ -245,14 +230,10 @@ char* grpc_channelz_get_channel(intptr_t channel_id) {
grpc_core::channelz::BaseNode::EntityType::kInternalChannel)) {
return nullptr;
}
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json = top_level_json;
grpc_json* channel_json = channel_node->RenderJson();
channel_json->key = "channel";
grpc_json_link_child(json, channel_json, nullptr);
char* json_str = grpc_json_dump_to_string(top_level_json, 0);
grpc_json_destroy(top_level_json);
return json_str;
grpc_core::Json json = grpc_core::Json::Object{
{"channel", channel_node->RenderJson()},
};
return gpr_strdup(json.Dump().c_str());
}
char* grpc_channelz_get_subchannel(intptr_t subchannel_id) {
@ -263,14 +244,10 @@ char* grpc_channelz_get_subchannel(intptr_t subchannel_id) {
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;
grpc_core::Json json = grpc_core::Json::Object{
{"subchannel", subchannel_node->RenderJson()},
};
return gpr_strdup(json.Dump().c_str());
}
char* grpc_channelz_get_socket(intptr_t socket_id) {
@ -281,12 +258,8 @@ char* grpc_channelz_get_socket(intptr_t socket_id) {
grpc_core::channelz::BaseNode::EntityType::kSocket) {
return nullptr;
}
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json = top_level_json;
grpc_json* socket_json = socket_node->RenderJson();
socket_json->key = "socket";
grpc_json_link_child(json, socket_json, nullptr);
char* json_str = grpc_json_dump_to_string(top_level_json, 0);
grpc_json_destroy(top_level_json);
return json_str;
grpc_core::Json json = grpc_core::Json::Object{
{"socket", socket_node->RenderJson()},
};
return gpr_strdup(json.Dump().c_str());
}

@ -51,13 +51,13 @@ class ChannelzRegistry {
// Returns the allocated JSON string that represents the proto
// GetTopChannelsResponse as per channelz.proto.
static char* GetTopChannels(intptr_t start_channel_id) {
static std::string GetTopChannels(intptr_t start_channel_id) {
return Default()->InternalGetTopChannels(start_channel_id);
}
// Returns the allocated JSON string that represents the proto
// GetServersResponse as per channelz.proto.
static char* GetServers(intptr_t start_server_id) {
static std::string GetServers(intptr_t start_server_id) {
return Default()->InternalGetServers(start_server_id);
}
@ -80,8 +80,8 @@ class ChannelzRegistry {
// returns the void* associated with that uuid. Else returns nullptr.
RefCountedPtr<BaseNode> InternalGet(intptr_t uuid);
char* InternalGetTopChannels(intptr_t start_channel_id);
char* InternalGetServers(intptr_t start_server_id);
std::string InternalGetTopChannels(intptr_t start_channel_id);
std::string InternalGetServers(intptr_t start_server_id);
void InternalLogAllEntities();

@ -24,6 +24,9 @@
#include <grpc/support/alloc.h>
namespace grpc {
namespace {
grpc::protobuf::util::Status ParseJson(const char* json_str,
grpc::protobuf::Message* message) {
grpc::protobuf::json::JsonParseOptions options;
@ -31,6 +34,8 @@ grpc::protobuf::util::Status ParseJson(const char* json_str,
return grpc::protobuf::json::JsonStringToMessage(json_str, message, options);
}
} // namespace
Status ChannelzService::GetTopChannels(
ServerContext* /*unused*/,
const channelz::v1::GetTopChannelsRequest* request,

@ -57,44 +57,28 @@ size_t GetSizeofTraceEvent() { return sizeof(ChannelTrace::TraceEvent); }
namespace {
grpc_json* GetJsonChild(grpc_json* parent, const char* key) {
EXPECT_NE(parent, nullptr);
for (grpc_json* child = parent->child; child != nullptr;
child = child->next) {
if (child->key != nullptr && strcmp(child->key, key) == 0) return child;
void ValidateJsonArraySize(const Json& array, size_t expected) {
if (expected == 0) {
ASSERT_EQ(array.type(), Json::Type::JSON_NULL);
} else {
ASSERT_EQ(array.type(), Json::Type::ARRAY);
EXPECT_EQ(array.array_value().size(), expected);
}
return nullptr;
}
void ValidateJsonArraySize(grpc_json* json, const char* key,
size_t expected_size) {
grpc_json* arr = GetJsonChild(json, key);
// the events array should not be present if there are no events.
if (expected_size == 0) {
EXPECT_EQ(arr, nullptr);
return;
}
ASSERT_NE(arr, nullptr);
ASSERT_EQ(arr->type, GRPC_JSON_ARRAY);
size_t count = 0;
for (grpc_json* child = arr->child; child != nullptr; child = child->next) {
++count;
}
ASSERT_EQ(count, expected_size);
}
void ValidateChannelTraceData(grpc_json* json,
void ValidateChannelTraceData(const Json& json,
size_t num_events_logged_expected,
size_t actual_num_events_expected) {
ASSERT_NE(json, nullptr);
grpc_json* num_events_logged_json = GetJsonChild(json, "numEventsLogged");
ASSERT_NE(num_events_logged_json, nullptr);
grpc_json* start_time = GetJsonChild(json, "creationTimestamp");
ASSERT_NE(start_time, nullptr);
ASSERT_EQ(json.type(), Json::Type::OBJECT);
Json::Object object = json.object_value();
Json& num_events_logged_json = object["numEventsLogged"];
ASSERT_EQ(num_events_logged_json.type(), Json::Type::STRING);
size_t num_events_logged =
(size_t)strtol(num_events_logged_json->value, nullptr, 0);
(size_t)strtol(num_events_logged_json.string_value().c_str(), nullptr, 0);
ASSERT_EQ(num_events_logged, num_events_logged_expected);
ValidateJsonArraySize(json, "events", actual_num_events_expected);
Json& start_time_json = object["creationTimestamp"];
ASSERT_EQ(start_time_json.type(), Json::Type::STRING);
ValidateJsonArraySize(object["events"], actual_num_events_expected);
}
void AddSimpleTrace(ChannelTrace* tracer) {
@ -105,15 +89,11 @@ void AddSimpleTrace(ChannelTrace* tracer) {
// checks for the existence of all the required members of the tracer.
void ValidateChannelTraceCustom(ChannelTrace* tracer, size_t num_events_logged,
size_t num_events_expected) {
grpc_json* json = tracer->RenderJson();
EXPECT_NE(json, nullptr);
char* json_str = grpc_json_dump_to_string(json, 0);
grpc_json_destroy(json);
grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateChannelTraceData(parsed_json, num_events_logged, num_events_expected);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
Json json = tracer->RenderJson();
ASSERT_EQ(json.type(), Json::Type::OBJECT);
std::string json_str = json.Dump();
grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str.c_str());
ValidateChannelTraceData(json, num_events_logged, num_events_expected);
}
void ValidateChannelTrace(ChannelTrace* tracer, size_t num_events_logged) {

@ -61,57 +61,60 @@ class CallCountingHelperPeer {
namespace {
grpc_json* GetJsonChild(grpc_json* parent, const char* key) {
EXPECT_NE(parent, nullptr);
for (grpc_json* child = parent->child; child != nullptr;
child = child->next) {
if (child->key != nullptr && strcmp(child->key, key) == 0) return child;
std::vector<intptr_t> GetUuidListFromArray(const Json::Array& arr) {
std::vector<intptr_t> uuids;
for (const Json& value : arr) {
EXPECT_EQ(value.type(), Json::Type::OBJECT);
if (value.type() != Json::Type::OBJECT) continue;
const Json::Object& object = value.object_value();
auto it = object.find("ref");
EXPECT_NE(it, object.end());
if (it == object.end()) continue;
EXPECT_EQ(it->second.type(), Json::Type::OBJECT);
if (it->second.type() != Json::Type::OBJECT) continue;
const Json::Object& ref_object = it->second.object_value();
it = ref_object.find("channelId");
EXPECT_NE(it, ref_object.end());
if (it != ref_object.end()) {
uuids.push_back(atoi(it->second.string_value().c_str()));
}
}
return nullptr;
return uuids;
}
void ValidateJsonArraySize(grpc_json* json, const char* key,
size_t expected_size) {
grpc_json* arr = GetJsonChild(json, key);
if (expected_size == 0) {
ASSERT_EQ(arr, nullptr);
return;
}
ASSERT_NE(arr, nullptr);
ASSERT_EQ(arr->type, GRPC_JSON_ARRAY);
size_t count = 0;
for (grpc_json* child = arr->child; child != nullptr; child = child->next) {
++count;
void ValidateJsonArraySize(const Json& array, size_t expected) {
if (expected == 0) {
ASSERT_EQ(array.type(), Json::Type::JSON_NULL);
} else {
ASSERT_EQ(array.type(), Json::Type::ARRAY);
EXPECT_EQ(array.array_value().size(), expected);
}
EXPECT_EQ(count, expected_size);
}
std::vector<intptr_t> GetUuidListFromArray(grpc_json* arr) {
EXPECT_EQ(arr->type, GRPC_JSON_ARRAY);
std::vector<intptr_t> uuids;
for (grpc_json* child = arr->child; child != nullptr; child = child->next) {
grpc_json* it = GetJsonChild(child, "ref");
EXPECT_NE(it, nullptr);
it = GetJsonChild(it, "channelId");
EXPECT_NE(it, nullptr);
uuids.push_back(atoi(it->value));
void ValidateJsonEnd(const Json& json, bool end) {
auto it = json.object_value().find("end");
if (end) {
ASSERT_NE(it, json.object_value().end());
EXPECT_EQ(it->second.type(), Json::Type::JSON_TRUE);
} else {
ASSERT_EQ(it, json.object_value().end());
}
return uuids;
}
void ValidateGetTopChannels(size_t expected_channels) {
char* json_str = ChannelzRegistry::GetTopChannels(0);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
std::string json_str = ChannelzRegistry::GetTopChannels(0);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
json_str.c_str());
grpc_error* error = GRPC_ERROR_NONE;
Json parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
// This check will naturally have to change when we support pagination.
// tracked: https://github.com/grpc/grpc/issues/16019.
ValidateJsonArraySize(parsed_json, "channel", expected_channels);
grpc_json* end = GetJsonChild(parsed_json, "end");
ASSERT_NE(end, nullptr);
EXPECT_EQ(end->type, GRPC_JSON_TRUE);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
// also check that the core API formats this correctly
ValidateJsonArraySize((*parsed_json.mutable_object())["channel"],
expected_channels);
ValidateJsonEnd(parsed_json, true);
// Also check that the core API formats this correctly.
char* core_api_json_str = grpc_channelz_get_top_channels(0);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
core_api_json_str);
@ -119,18 +122,19 @@ void ValidateGetTopChannels(size_t expected_channels) {
}
void ValidateGetServers(size_t expected_servers) {
char* json_str = ChannelzRegistry::GetServers(0);
grpc::testing::ValidateGetServersResponseProtoJsonTranslation(json_str);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
std::string json_str = ChannelzRegistry::GetServers(0);
grpc::testing::ValidateGetServersResponseProtoJsonTranslation(
json_str.c_str());
grpc_error* error = GRPC_ERROR_NONE;
Json parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
// This check will naturally have to change when we support pagination.
// tracked: https://github.com/grpc/grpc/issues/16019.
ValidateJsonArraySize(parsed_json, "server", expected_servers);
grpc_json* end = GetJsonChild(parsed_json, "end");
ASSERT_NE(end, nullptr);
EXPECT_EQ(end->type, GRPC_JSON_TRUE);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
// also check that the core API formats this correctly
ValidateJsonArraySize((*parsed_json.mutable_object())["server"],
expected_servers);
ValidateJsonEnd(parsed_json, true);
// Also check that the core API formats this correctly.
char* core_api_json_str = grpc_channelz_get_servers(0);
grpc::testing::ValidateGetServersResponseProtoJsonTranslation(
core_api_json_str);
@ -181,38 +185,46 @@ class ServerFixture {
grpc_server* server_;
};
struct validate_channel_data_args {
struct ValidateChannelDataArgs {
int64_t calls_started;
int64_t calls_failed;
int64_t calls_succeeded;
};
void ValidateChildInteger(grpc_json* json, int64_t expect, const char* key) {
grpc_json* gotten_json = GetJsonChild(json, key);
if (expect == 0) {
ASSERT_EQ(gotten_json, nullptr);
void ValidateChildInteger(const Json::Object& object, const std::string& key,
int64_t expected) {
auto it = object.find(key);
if (expected == 0) {
ASSERT_EQ(it, object.end());
return;
}
ASSERT_NE(gotten_json, nullptr);
int64_t gotten_number = (int64_t)strtol(gotten_json->value, nullptr, 0);
EXPECT_EQ(gotten_number, expect);
ASSERT_NE(it, object.end());
ASSERT_EQ(it->second.type(), Json::Type::STRING);
int64_t gotten_number =
(int64_t)strtol(it->second.string_value().c_str(), nullptr, 0);
EXPECT_EQ(gotten_number, expected);
}
void ValidateCounters(char* json_str, validate_channel_data_args args) {
grpc_json* json = grpc_json_parse_string(json_str);
ASSERT_NE(json, nullptr);
grpc_json* data = GetJsonChild(json, "data");
ValidateChildInteger(data, args.calls_started, "callsStarted");
ValidateChildInteger(data, args.calls_failed, "callsFailed");
ValidateChildInteger(data, args.calls_succeeded, "callsSucceeded");
grpc_json_destroy(json);
void ValidateCounters(const std::string& json_str,
const ValidateChannelDataArgs& args) {
grpc_error* error = GRPC_ERROR_NONE;
Json json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(json.type(), Json::Type::OBJECT);
Json::Object* object = json.mutable_object();
Json& data = (*object)["data"];
ASSERT_EQ(data.type(), Json::Type::OBJECT);
ValidateChildInteger(data.object_value(), "callsStarted", args.calls_started);
ValidateChildInteger(data.object_value(), "callsFailed", args.calls_failed);
ValidateChildInteger(data.object_value(), "callsSucceeded",
args.calls_succeeded);
}
void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) {
char* json_str = channel->RenderJsonString();
grpc::testing::ValidateChannelProtoJsonTranslation(json_str);
void ValidateChannel(ChannelNode* channel,
const ValidateChannelDataArgs& args) {
std::string json_str = channel->RenderJsonString();
grpc::testing::ValidateChannelProtoJsonTranslation(json_str.c_str());
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->uuid());
grpc::testing::ValidateGetChannelResponseProtoJsonTranslation(
@ -220,11 +232,10 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) {
gpr_free(core_api_json_str);
}
void ValidateServer(ServerNode* server, validate_channel_data_args args) {
char* json_str = server->RenderJsonString();
grpc::testing::ValidateServerProtoJsonTranslation(json_str);
void ValidateServer(ServerNode* server, const ValidateChannelDataArgs& args) {
std::string json_str = server->RenderJsonString();
grpc::testing::ValidateServerProtoJsonTranslation(json_str.c_str());
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_server(server->uuid());
grpc::testing::ValidateGetServerResponseProtoJsonTranslation(
@ -348,28 +359,29 @@ TEST_F(ChannelzRegistryBasedTest, ManyChannelsTest) {
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsPagination) {
grpc_core::ExecCtx exec_ctx;
// this is over the pagination limit.
// This is over the pagination limit.
ChannelFixture channels[150];
(void)channels; // suppress unused variable error
char* json_str = ChannelzRegistry::GetTopChannels(0);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
std::string json_str = ChannelzRegistry::GetTopChannels(0);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
json_str.c_str());
grpc_error* error = GRPC_ERROR_NONE;
Json parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
// 100 is the pagination limit.
ValidateJsonArraySize(parsed_json, "channel", 100);
grpc_json* end = GetJsonChild(parsed_json, "end");
EXPECT_EQ(end, nullptr);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
// Now we get the rest
ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], 100);
ValidateJsonEnd(parsed_json, false);
// Now we get the rest.
json_str = ChannelzRegistry::GetTopChannels(101);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str);
parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", 50);
end = GetJsonChild(parsed_json, "end");
ASSERT_NE(end, nullptr);
EXPECT_EQ(end->type, GRPC_JSON_TRUE);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
json_str.c_str());
error = GRPC_ERROR_NONE;
parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], 50);
ValidateJsonEnd(parsed_json, true);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidCheck) {
@ -377,16 +389,17 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidCheck) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture channels[kNumChannels];
(void)channels; // suppress unused variable error
char* json_str = ChannelzRegistry::GetTopChannels(0);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", kNumChannels);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
std::string json_str = ChannelzRegistry::GetTopChannels(0);
grpc_error* error = GRPC_ERROR_NONE;
Json parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
Json& array = (*parsed_json.mutable_object())["channel"];
ValidateJsonArraySize(array, kNumChannels);
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
for (int i = 0; i < kNumChannels; ++i) {
EXPECT_EQ(i + 1, uuids[i]);
}
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMiddleUuidCheck) {
@ -395,17 +408,18 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMiddleUuidCheck) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture channels[kNumChannels];
(void)channels; // suppress unused variable error
// only query for the end of the channels
char* json_str = ChannelzRegistry::GetTopChannels(kMidQuery);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", kNumChannels - kMidQuery + 1);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
for (size_t i = 0; i < uuids.size(); ++i) {
// Only query for the end of the channels.
std::string json_str = ChannelzRegistry::GetTopChannels(kMidQuery);
grpc_error* error = GRPC_ERROR_NONE;
Json parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
Json& array = (*parsed_json.mutable_object())["channel"];
ValidateJsonArraySize(array, kNumChannels - kMidQuery + 1);
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
for (int i = 0; i < uuids.size(); ++i) {
EXPECT_EQ(static_cast<intptr_t>(kMidQuery + i), uuids[i]);
}
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsNoHitUuid) {
@ -416,17 +430,18 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsNoHitUuid) {
(void)servers; // suppress unused variable error
ChannelFixture channels[10]; // will take uuid[51, 60]
(void)channels; // suppress unused variable error
// query in the middle of the server channels
char* json_str = ChannelzRegistry::GetTopChannels(45);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", 10);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
for (size_t i = 0; i < uuids.size(); ++i) {
// Query in the middle of the server channels.
std::string json_str = ChannelzRegistry::GetTopChannels(45);
grpc_error* error = GRPC_ERROR_NONE;
Json parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
Json& array = (*parsed_json.mutable_object())["channel"];
ValidateJsonArraySize(array, 10);
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
for (int i = 0; i < uuids.size(); ++i) {
EXPECT_EQ(static_cast<intptr_t>(51 + i), uuids[i]);
}
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMoreGaps) {
@ -437,23 +452,25 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMoreGaps) {
{ ServerFixture server_with_uuid4; }
ChannelFixture channel_with_uuid5;
// Current state of list: [1, NULL, 3, NULL, 5]
char* json_str = ChannelzRegistry::GetTopChannels(2);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", 2);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
std::string json_str = ChannelzRegistry::GetTopChannels(2);
grpc_error* error = GRPC_ERROR_NONE;
Json parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
Json array = (*parsed_json.mutable_object())["channel"];
ValidateJsonArraySize(array, 2);
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
EXPECT_EQ(static_cast<intptr_t>(3), uuids[0]);
EXPECT_EQ(static_cast<intptr_t>(5), uuids[1]);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
json_str = ChannelzRegistry::GetTopChannels(4);
parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", 1);
json_channels = GetJsonChild(parsed_json, "channel");
uuids = GetUuidListFromArray(json_channels);
error = GRPC_ERROR_NONE;
parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
array = (*parsed_json.mutable_object())["channel"];
ValidateJsonArraySize(array, 1);
uuids = GetUuidListFromArray(array.array_value());
EXPECT_EQ(static_cast<intptr_t>(5), uuids[0]);
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidAfterCompaction) {
@ -468,17 +485,18 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidAfterCompaction) {
even_channels.push_back(grpc_core::MakeUnique<ChannelFixture>());
}
}
char* json_str = ChannelzRegistry::GetTopChannels(0);
grpc_json* parsed_json = grpc_json_parse_string(json_str);
ValidateJsonArraySize(parsed_json, "channel", kLoopIterations);
grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
std::string json_str = ChannelzRegistry::GetTopChannels(0);
grpc_error* error = GRPC_ERROR_NONE;
Json parsed_json = Json::Parse(json_str, &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
Json& array = (*parsed_json.mutable_object())["channel"];
ValidateJsonArraySize(array, kLoopIterations);
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
for (int i = 0; i < kLoopIterations; ++i) {
// only the even uuids will still be present.
EXPECT_EQ((i + 1) * 2, uuids[i]);
}
grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
TEST_F(ChannelzRegistryBasedTest, InternalChannelTest) {

@ -217,51 +217,42 @@ static void test_channelz(grpc_end2end_test_config config) {
grpc_server_get_channelz_node(f.server);
GPR_ASSERT(channelz_server != nullptr);
char* json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
std::string json = channelz_channel->RenderJsonString();
// nothing is present yet
GPR_ASSERT(nullptr == strstr(json, "\"callsStarted\""));
GPR_ASSERT(nullptr == strstr(json, "\"callsFailed\""));
GPR_ASSERT(nullptr == strstr(json, "\"callsSucceeded\""));
gpr_free(json);
GPR_ASSERT(json.find("\"callsStarted\"") == json.npos);
GPR_ASSERT(json.find("\"callsFailed\"") == json.npos);
GPR_ASSERT(json.find("\"callsSucceeded\"") == json.npos);
// one successful request
run_one_request(config, f, true);
json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"1\""));
GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
gpr_free(json);
GPR_ASSERT(json.find("\"callsStarted\":\"1\"") != json.npos);
GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos);
// one failed request
run_one_request(config, f, false);
json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\""));
GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\""));
GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
GPR_ASSERT(json.find("\"callsStarted\":\"2\"") != json.npos);
GPR_ASSERT(json.find("\"callsFailed\":\"1\"") != json.npos);
GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos);
// channel tracing is not enabled, so these should not be preset.
GPR_ASSERT(nullptr == strstr(json, "\"trace\""));
GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\""));
GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\""));
gpr_free(json);
GPR_ASSERT(json.find("\"trace\"") == json.npos);
GPR_ASSERT(json.find("\"description\":\"Channel created\"") == json.npos);
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") == json.npos);
json = channelz_server->RenderJsonString();
GPR_ASSERT(json != nullptr);
GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\""));
GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\""));
GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
GPR_ASSERT(json.find("\"callsStarted\":\"2\"") != json.npos);
GPR_ASSERT(json.find("\"callsFailed\":\"1\"") != json.npos);
GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos);
// channel tracing is not enabled, so these should not be preset.
GPR_ASSERT(nullptr == strstr(json, "\"trace\""));
GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\""));
GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\""));
gpr_free(json);
GPR_ASSERT(json.find("\"trace\"") == json.npos);
GPR_ASSERT(json.find("\"description\":\"Channel created\"") == json.npos);
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") == json.npos);
json = channelz_server->RenderServerSockets(0, 100);
GPR_ASSERT(nullptr != strstr(json, "\"end\":true"));
gpr_free(json);
GPR_ASSERT(json.find("\"end\":true") != json.npos);
end_test(&f);
config.tear_down_data(&f);
@ -289,19 +280,15 @@ static void test_channelz_with_channel_trace(grpc_end2end_test_config config) {
run_one_request(config, f, true);
char* json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
GPR_ASSERT(nullptr != strstr(json, "\"trace\""));
GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Channel created\""));
GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\""));
gpr_free(json);
std::string json = channelz_channel->RenderJsonString();
GPR_ASSERT(json.find("\"trace\"") != json.npos);
GPR_ASSERT(json.find("\"description\":\"Channel created\"") != json.npos);
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") != json.npos);
json = channelz_server->RenderJsonString();
GPR_ASSERT(json != nullptr);
GPR_ASSERT(nullptr != strstr(json, "\"trace\""));
GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Server created\""));
GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\""));
gpr_free(json);
GPR_ASSERT(json.find("\"trace\"") != json.npos);
GPR_ASSERT(json.find("\"description\":\"Server created\"") != json.npos);
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") != json.npos);
end_test(&f);
config.tear_down_data(&f);

@ -396,18 +396,16 @@ static void test_retry_streaming(grpc_end2end_test_config config) {
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(channelz_channel != nullptr);
char* json = channelz_channel->RenderJsonString();
GPR_ASSERT(json != nullptr);
gpr_log(GPR_INFO, "%s", json);
GPR_ASSERT(nullptr != strstr(json, "\"trace\""));
GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Channel created\""));
GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\""));
GPR_ASSERT(nullptr != strstr(json, "Resolution event"));
GPR_ASSERT(nullptr != strstr(json, "Created new LB policy"));
GPR_ASSERT(nullptr != strstr(json, "Service config changed"));
GPR_ASSERT(nullptr != strstr(json, "Address list became non-empty"));
GPR_ASSERT(nullptr != strstr(json, "Channel state change to CONNECTING"));
gpr_free(json);
std::string json = channelz_channel->RenderJsonString();
gpr_log(GPR_INFO, "%s", json.c_str());
GPR_ASSERT(json.find("\"trace\"") != json.npos);
GPR_ASSERT(json.find("\"description\":\"Channel created\"") != json.npos);
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") != json.npos);
GPR_ASSERT(json.find("Resolution event") != json.npos);
GPR_ASSERT(json.find("Created new LB policy") != json.npos);
GPR_ASSERT(json.find("Service config changed") != json.npos);
GPR_ASSERT(json.find("Address list became non-empty") != json.npos);
GPR_ASSERT(json.find("Channel state change to CONNECTING") != json.npos);
grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);

@ -26,6 +26,8 @@
#include <grpcpp/impl/codegen/config_protobuf.h>
#include <gtest/gtest.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json.h"
#include "src/proto/grpc/channelz/channelz.pb.h"
namespace grpc {
@ -36,8 +38,7 @@ namespace {
// then back to json. This ensures that the json string was correctly formatted
// according to https://developers.google.com/protocol-buffers/docs/proto3#json
template <typename Message>
void VaidateProtoJsonTranslation(char* json_c_str) {
grpc::string json_str(json_c_str);
void VaidateProtoJsonTranslation(const std::string& json_str) {
Message msg;
grpc::protobuf::json::JsonParseOptions parse_options;
// If the following line is failing, then uncomment the last line of the
@ -55,6 +56,14 @@ void VaidateProtoJsonTranslation(char* json_c_str) {
// print_options.always_print_primitive_fields = true;
s = grpc::protobuf::json::MessageToJsonString(msg, &proto_json_str);
EXPECT_TRUE(s.ok());
// Parse JSON and re-dump to string, to make sure formatting is the
// same as what would be generated by our JSON library.
grpc_error* error = GRPC_ERROR_NONE;
grpc_core::Json parsed_json =
grpc_core::Json::Parse(proto_json_str.c_str(), &error);
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
ASSERT_EQ(parsed_json.type(), grpc_core::Json::Type::OBJECT);
proto_json_str = parsed_json.Dump();
// uncomment these to compare the json strings.
// gpr_log(GPR_ERROR, "tracer json: %s", json_str.c_str());
// gpr_log(GPR_ERROR, "proto json: %s", proto_json_str.c_str());
@ -65,38 +74,39 @@ void VaidateProtoJsonTranslation(char* json_c_str) {
namespace testing {
void ValidateChannelTraceProtoJsonTranslation(char* json_c_str) {
void ValidateChannelTraceProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::ChannelTrace>(json_c_str);
}
void ValidateChannelProtoJsonTranslation(char* json_c_str) {
void ValidateChannelProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Channel>(json_c_str);
}
void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str) {
void ValidateGetTopChannelsResponseProtoJsonTranslation(
const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::GetTopChannelsResponse>(
json_c_str);
}
void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str) {
void ValidateGetChannelResponseProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::GetChannelResponse>(
json_c_str);
}
void ValidateGetServerResponseProtoJsonTranslation(char* json_c_str) {
void ValidateGetServerResponseProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::GetServerResponse>(
json_c_str);
}
void ValidateSubchannelProtoJsonTranslation(char* json_c_str) {
void ValidateSubchannelProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Subchannel>(json_c_str);
}
void ValidateServerProtoJsonTranslation(char* json_c_str) {
void ValidateServerProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::Server>(json_c_str);
}
void ValidateGetServersResponseProtoJsonTranslation(char* json_c_str) {
void ValidateGetServersResponseProtoJsonTranslation(const char* json_c_str) {
VaidateProtoJsonTranslation<grpc::channelz::v1::GetServersResponse>(
json_c_str);
}

@ -22,14 +22,14 @@
namespace grpc {
namespace testing {
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 ValidateGetServerResponseProtoJsonTranslation(char* json_c_str);
void ValidateSubchannelProtoJsonTranslation(char* json_c_str);
void ValidateServerProtoJsonTranslation(char* json_c_str);
void ValidateGetServersResponseProtoJsonTranslation(char* json_c_str);
void ValidateChannelTraceProtoJsonTranslation(const char* json_c_str);
void ValidateChannelProtoJsonTranslation(const char* json_c_str);
void ValidateGetTopChannelsResponseProtoJsonTranslation(const char* json_c_str);
void ValidateGetChannelResponseProtoJsonTranslation(const char* json_c_str);
void ValidateGetServerResponseProtoJsonTranslation(const char* json_c_str);
void ValidateSubchannelProtoJsonTranslation(const char* json_c_str);
void ValidateServerProtoJsonTranslation(const char* json_c_str);
void ValidateGetServersResponseProtoJsonTranslation(const char* json_c_str);
} // namespace testing
} // namespace grpc

Loading…
Cancel
Save