Skip to content

Commit 21df43f

Browse files
ctillerpaulosjca
authored andcommitted
[channelz] Export json & proto additional data
PiperOrigin-RevId: 777315819
1 parent 0d1591f commit 21df43f

File tree

20 files changed

+905
-173
lines changed

20 files changed

+905
-173
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build_autogenerated.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

include/grpc/support/json.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,30 @@ class Json {
4747
kArray, // Use array() for payload.
4848
};
4949

50+
template <typename Sink>
51+
friend void AbslStringify(Sink& sink, Type type) {
52+
switch (type) {
53+
case Type::kNull:
54+
sink.Append("null");
55+
break;
56+
case Type::kBoolean:
57+
sink.Append("boolean");
58+
break;
59+
case Type::kNumber:
60+
sink.Append("number");
61+
break;
62+
case Type::kString:
63+
sink.Append("string");
64+
break;
65+
case Type::kObject:
66+
sink.Append("object");
67+
break;
68+
case Type::kArray:
69+
sink.Append("array");
70+
break;
71+
}
72+
}
73+
5074
using Object = std::map<std::string, Json>;
5175
using Array = std::vector<Json>;
5276

src/core/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10194,8 +10194,10 @@ grpc_cc_library(
1019410194
"time",
1019510195
"upb_utils",
1019610196
"//:channelz_property_list_upb",
10197+
"//:channelz_upb",
1019710198
"//:gpr",
1019810199
"//:protobuf_any_upb",
10200+
"//:protobuf_empty_upb",
1019910201
],
1020010202
)
1020110203

src/core/channelz/channelz.cc

Lines changed: 30 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -57,67 +57,32 @@ namespace channelz {
5757
// DataSink
5858
//
5959

60-
void DataSinkImplementation::AddAdditionalInfo(absl::string_view name,
61-
Json::Object additional_info) {
60+
void DataSinkImplementation::AddData(absl::string_view name,
61+
std::unique_ptr<Data> data) {
6262
MutexLock lock(&mu_);
63-
additional_info_.emplace(std::string(name), std::move(additional_info));
63+
additional_info_.emplace(name, std::move(data));
6464
}
6565

66-
void DataSinkImplementation::AddChildObjects(
67-
std::vector<RefCountedPtr<BaseNode>> child_objects) {
66+
Json::Object DataSinkImplementation::Finalize(bool) {
6867
MutexLock lock(&mu_);
69-
for (auto& node : child_objects) {
70-
child_objects_.push_back(std::move(node));
71-
}
72-
}
73-
74-
Json::Object DataSinkImplementation::Finalize(bool timed_out) {
75-
if (timed_out) {
76-
AddAdditionalInfo("channelzState", {{"timedOut", Json::FromBool(true)}});
77-
}
78-
MutexLock lock(&mu_);
79-
MergeChildObjectsIntoAdditionalInfo();
8068
Json::Object out;
8169
for (auto& [name, additional_info] : additional_info_) {
82-
out[name] = Json::FromObject(std::move(additional_info));
70+
out[name] = Json::FromObject(additional_info->ToJson());
8371
}
8472
return out;
8573
}
8674

87-
void DataSinkImplementation::MergeChildObjectsIntoAdditionalInfo() {
88-
if (child_objects_.empty()) return;
89-
Json::Object subobjects;
90-
std::map<BaseNode::EntityType, std::set<int64_t>> child_objects_by_type;
91-
for (auto& node : child_objects_) {
92-
child_objects_by_type[node->type()].insert(node->uuid());
93-
}
94-
for (const auto& [type, child_objects] : child_objects_by_type) {
95-
std::string key;
96-
switch (type) {
97-
case BaseNode::EntityType::kTopLevelChannel:
98-
case BaseNode::EntityType::kSubchannel:
99-
case BaseNode::EntityType::kListenSocket:
100-
case BaseNode::EntityType::kServer:
101-
case BaseNode::EntityType::kInternalChannel: {
102-
LOG(ERROR) << "Nodes of type " << BaseNode::EntityTypeString(type)
103-
<< " not supported for child object collection in DataSink";
104-
continue;
105-
}
106-
case BaseNode::EntityType::kSocket:
107-
key = "subSockets";
108-
break;
109-
case BaseNode::EntityType::kCall:
110-
key = "calls";
111-
break;
112-
}
113-
Json::Array uuids;
114-
uuids.reserve(child_objects.size());
115-
for (int64_t uuid : child_objects) {
116-
uuids.push_back(Json::FromNumber(uuid));
117-
}
118-
subobjects[key] = Json::FromArray(std::move(uuids));
75+
void DataSinkImplementation::Finalize(bool timed_out,
76+
grpc_channelz_v2_Entity* entity,
77+
upb_Arena* arena) {
78+
MutexLock lock(&mu_);
79+
grpc_channelz_v2_Entity_set_timed_out(entity, timed_out);
80+
for (auto& [name, additional_info] : additional_info_) {
81+
auto* staple = grpc_channelz_v2_Entity_add_data(entity, arena);
82+
grpc_channelz_v2_Data_set_name(staple, StdStringToUpbString(name));
83+
additional_info->FillProto(
84+
grpc_channelz_v2_Data_mutable_value(staple, arena), arena);
11985
}
120-
additional_info_.emplace("childObjects", std::move(subobjects));
12186
}
12287

12388
//
@@ -222,6 +187,21 @@ void BaseNode::SerializeEntity(grpc_channelz_v2_Entity* entity,
222187
}
223188
}
224189
grpc_channelz_v2_Entity_set_orphaned(entity, orphaned_index_ != 0);
190+
191+
auto done = std::make_shared<Notification>();
192+
auto sink_impl = std::make_shared<DataSinkImplementation>();
193+
{
194+
MutexLock lock(&data_sources_mu_);
195+
auto done_notifier = std::make_shared<DataSinkCompletionNotification>(
196+
[done]() { done->Notify(); });
197+
for (DataSource* data_source : data_sources_) {
198+
data_source->AddData(DataSink(sink_impl, done_notifier));
199+
}
200+
}
201+
bool completed =
202+
done->WaitForNotificationWithTimeout(absl::Milliseconds(100));
203+
sink_impl->Finalize(!completed, entity, arena);
204+
225205
trace_.Render(entity, arena);
226206
}
227207

src/core/channelz/channelz.h

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -267,16 +267,22 @@ class ZTrace {
267267
// the collection is complete (or has timed out).
268268
class DataSinkImplementation {
269269
public:
270-
void AddAdditionalInfo(absl::string_view name, Json::Object additional_info);
271-
void AddChildObjects(std::vector<RefCountedPtr<BaseNode>> child_objects);
270+
class Data {
271+
public:
272+
virtual ~Data() = default;
273+
virtual Json::Object ToJson() = 0;
274+
virtual void FillProto(google_protobuf_Any* any, upb_Arena* arena) = 0;
275+
};
276+
277+
void AddData(absl::string_view name, std::unique_ptr<Data> data);
272278
Json::Object Finalize(bool timed_out);
279+
void Finalize(bool timed_out, grpc_channelz_v2_Entity* entity,
280+
upb_Arena* arena);
273281

274282
private:
275-
void MergeChildObjectsIntoAdditionalInfo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
276-
277283
Mutex mu_;
278-
std::map<std::string, Json::Object> additional_info_ ABSL_GUARDED_BY(mu_);
279-
std::vector<RefCountedPtr<BaseNode>> child_objects_ ABSL_GUARDED_BY(mu_);
284+
std::map<std::string, std::unique_ptr<Data>> additional_info_
285+
ABSL_GUARDED_BY(mu_);
280286
};
281287

282288
// Wrapper around absl::AnyInvocable<void()> that is used to notify when the
@@ -300,22 +306,28 @@ class DataSink {
300306
: impl_(impl), notification_(std::move(notification)) {}
301307

302308
template <typename T>
303-
std::void_t<decltype(std::declval<T>().TakeJsonObject())> AddAdditionalInfo(
309+
std::void_t<decltype(std::declval<T>().TakeJsonObject())> AddData(
304310
absl::string_view name, T value) {
305-
AddAdditionalInfo(name, value.TakeJsonObject());
306-
}
307-
308-
void AddChildObjects(std::vector<RefCountedPtr<BaseNode>> children) {
309-
auto impl = impl_.lock();
310-
if (impl == nullptr) return;
311-
impl->AddChildObjects(std::move(children));
311+
class DataImpl final : public DataSinkImplementation::Data {
312+
public:
313+
explicit DataImpl(T value) : value_(std::move(value)) {}
314+
Json::Object ToJson() override { return value_.TakeJsonObject(); }
315+
void FillProto(google_protobuf_Any* any, upb_Arena* arena) override {
316+
value_.FillAny(any, arena);
317+
}
318+
319+
private:
320+
T value_;
321+
};
322+
AddData(name, std::make_unique<DataImpl>(std::move(value)));
312323
}
313324

314325
private:
315-
void AddAdditionalInfo(absl::string_view name, Json::Object additional_info) {
326+
void AddData(absl::string_view name,
327+
std::unique_ptr<DataSinkImplementation::Data> data) {
316328
auto impl = impl_.lock();
317329
if (impl == nullptr) return;
318-
impl->AddAdditionalInfo(name, std::move(additional_info));
330+
impl->AddData(name, std::move(data));
319331
}
320332

321333
std::weak_ptr<DataSinkImplementation> impl_;

0 commit comments

Comments
 (0)