Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / test / cpp / util / channelz_sampler.cc
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 #include <grpc/support/port_platform.h>
19
20 #include <unistd.h>
21
22 #include <cstdlib>
23 #include <fstream>
24 #include <iostream>
25 #include <memory>
26 #include <ostream>
27 #include <queue>
28 #include <string>
29
30 #include "absl/flags/flag.h"
31 #include "absl/strings/str_format.h"
32 #include "absl/strings/str_join.h"
33 #include "google/protobuf/text_format.h"
34
35 #include <grpc/grpc.h>
36 #include <grpcpp/channel.h>
37 #include <grpcpp/client_context.h>
38 #include <grpcpp/create_channel.h>
39 #include <grpcpp/ext/channelz_service_plugin.h>
40 #include <grpcpp/grpcpp.h>
41 #include <grpcpp/security/credentials.h>
42 #include <grpcpp/security/server_credentials.h>
43 #include <grpcpp/server.h>
44 #include <grpcpp/server_builder.h>
45 #include <grpcpp/server_context.h>
46
47 #include "src/core/lib/json/json.h"
48 #include "src/cpp/server/channelz/channelz_service.h"
49 #include "src/proto/grpc/channelz/channelz.pb.h"
50 #include "test/core/util/test_config.h"
51 #include "test/cpp/util/test_config.h"
52 #include "test/cpp/util/test_credentials_provider.h"
53
54 ABSL_FLAG(std::string, server_address, "", "channelz server address");
55 ABSL_FLAG(std::string, custom_credentials_type, "", "custom credentials type");
56 ABSL_FLAG(int64_t, sampling_times, 1, "number of sampling");
57 // TODO(Capstan): Consider using absl::Duration
58 ABSL_FLAG(int64_t, sampling_interval_seconds, 0,
59           "sampling interval in seconds");
60 ABSL_FLAG(std::string, output_json, "", "output filename in json format");
61
62 namespace {
63 using grpc::ClientContext;
64 using grpc::Status;
65 using grpc::StatusCode;
66 using grpc::channelz::v1::GetChannelRequest;
67 using grpc::channelz::v1::GetChannelResponse;
68 using grpc::channelz::v1::GetServersRequest;
69 using grpc::channelz::v1::GetServersResponse;
70 using grpc::channelz::v1::GetSocketRequest;
71 using grpc::channelz::v1::GetSocketResponse;
72 using grpc::channelz::v1::GetSubchannelRequest;
73 using grpc::channelz::v1::GetSubchannelResponse;
74 using grpc::channelz::v1::GetTopChannelsRequest;
75 using grpc::channelz::v1::GetTopChannelsResponse;
76 }  // namespace
77
78 class ChannelzSampler final {
79  public:
80   // Get server_id of a server
81   int64_t GetServerID(const grpc::channelz::v1::Server& server) {
82     return server.ref().server_id();
83   }
84
85   // Get channel_id of a channel
86   inline int64_t GetChannelID(const grpc::channelz::v1::Channel& channel) {
87     return channel.ref().channel_id();
88   }
89
90   // Get subchannel_id of a subchannel
91   inline int64_t GetSubchannelID(
92       const grpc::channelz::v1::Subchannel& subchannel) {
93     return subchannel.ref().subchannel_id();
94   }
95
96   // Get socket_id of a socket
97   inline int64_t GetSocketID(const grpc::channelz::v1::Socket& socket) {
98     return socket.ref().socket_id();
99   }
100
101   // Get name of a server
102   inline std::string GetServerName(const grpc::channelz::v1::Server& server) {
103     return server.ref().name();
104   }
105
106   // Get name of a channel
107   inline std::string GetChannelName(
108       const grpc::channelz::v1::Channel& channel) {
109     return channel.ref().name();
110   }
111
112   // Get name of a subchannel
113   inline std::string GetSubchannelName(
114       const grpc::channelz::v1::Subchannel& subchannel) {
115     return subchannel.ref().name();
116   }
117
118   // Get name of a socket
119   inline std::string GetSocketName(const grpc::channelz::v1::Socket& socket) {
120     return socket.ref().name();
121   }
122
123   // Get a channel based on channel_id
124   grpc::channelz::v1::Channel GetChannelRPC(int64_t channel_id) {
125     GetChannelRequest get_channel_request;
126     get_channel_request.set_channel_id(channel_id);
127     GetChannelResponse get_channel_response;
128     ClientContext get_channel_context;
129     get_channel_context.set_deadline(
130         grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
131     Status status = channelz_stub_->GetChannel(
132         &get_channel_context, get_channel_request, &get_channel_response);
133     if (!status.ok()) {
134       gpr_log(GPR_ERROR, "GetChannelRPC failed: %s",
135               get_channel_context.debug_error_string().c_str());
136       GPR_ASSERT(0);
137     }
138     return get_channel_response.channel();
139   }
140
141   // Get a subchannel based on subchannel_id
142   grpc::channelz::v1::Subchannel GetSubchannelRPC(int64_t subchannel_id) {
143     GetSubchannelRequest get_subchannel_request;
144     get_subchannel_request.set_subchannel_id(subchannel_id);
145     GetSubchannelResponse get_subchannel_response;
146     ClientContext get_subchannel_context;
147     get_subchannel_context.set_deadline(
148         grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
149     Status status = channelz_stub_->GetSubchannel(&get_subchannel_context,
150                                                   get_subchannel_request,
151                                                   &get_subchannel_response);
152     if (!status.ok()) {
153       gpr_log(GPR_ERROR, "GetSubchannelRPC failed: %s",
154               get_subchannel_context.debug_error_string().c_str());
155       GPR_ASSERT(0);
156     }
157     return get_subchannel_response.subchannel();
158   }
159
160   // get a socket based on socket_id
161   grpc::channelz::v1::Socket GetSocketRPC(int64_t socket_id) {
162     GetSocketRequest get_socket_request;
163     get_socket_request.set_socket_id(socket_id);
164     GetSocketResponse get_socket_response;
165     ClientContext get_socket_context;
166     get_socket_context.set_deadline(
167         grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
168     Status status = channelz_stub_->GetSocket(
169         &get_socket_context, get_socket_request, &get_socket_response);
170     if (!status.ok()) {
171       gpr_log(GPR_ERROR, "GetSocketRPC failed: %s",
172               get_socket_context.debug_error_string().c_str());
173       GPR_ASSERT(0);
174     }
175     return get_socket_response.socket();
176   }
177
178   // get the descedent channels/subchannels/sockets of a channel
179   // push descedent channels/subchannels to queue for layer traverse
180   // store descedent channels/subchannels/sockets for dumping data
181   void GetChannelDescedence(
182       const grpc::channelz::v1::Channel& channel,
183       std::queue<grpc::channelz::v1::Channel>& channel_queue,
184       std::queue<grpc::channelz::v1::Subchannel>& subchannel_queue) {
185     std::cout << "    Channel ID" << GetChannelID(channel) << "_"
186               << GetChannelName(channel) << " descendence - ";
187     if (channel.channel_ref_size() > 0 || channel.subchannel_ref_size() > 0) {
188       if (channel.channel_ref_size() > 0) {
189         std::cout << "channel: ";
190         for (const auto& _channelref : channel.channel_ref()) {
191           int64_t ch_id = _channelref.channel_id();
192           std::cout << "ID" << ch_id << "_" << _channelref.name() << " ";
193           grpc::channelz::v1::Channel ch = GetChannelRPC(ch_id);
194           channel_queue.push(ch);
195           if (CheckID(ch_id)) {
196             all_channels_.push_back(ch);
197             StoreChannelInJson(ch);
198           }
199         }
200         if (channel.subchannel_ref_size() > 0) {
201           std::cout << ", ";
202         }
203       }
204       if (channel.subchannel_ref_size() > 0) {
205         std::cout << "subchannel: ";
206         for (const auto& _subchannelref : channel.subchannel_ref()) {
207           int64_t subch_id = _subchannelref.subchannel_id();
208           std::cout << "ID" << subch_id << "_" << _subchannelref.name() << " ";
209           grpc::channelz::v1::Subchannel subch = GetSubchannelRPC(subch_id);
210           subchannel_queue.push(subch);
211           if (CheckID(subch_id)) {
212             all_subchannels_.push_back(subch);
213             StoreSubchannelInJson(subch);
214           }
215         }
216       }
217     } else if (channel.socket_ref_size() > 0) {
218       std::cout << "socket: ";
219       for (const auto& _socketref : channel.socket_ref()) {
220         int64_t so_id = _socketref.socket_id();
221         std::cout << "ID" << so_id << "_" << _socketref.name() << " ";
222         grpc::channelz::v1::Socket so = GetSocketRPC(so_id);
223         if (CheckID(so_id)) {
224           all_sockets_.push_back(so);
225           StoreSocketInJson(so);
226         }
227       }
228     }
229     std::cout << std::endl;
230   }
231
232   // get the descedent channels/subchannels/sockets of a subchannel
233   // push descedent channels/subchannels to queue for layer traverse
234   // store descedent channels/subchannels/sockets for dumping data
235   void GetSubchannelDescedence(
236       grpc::channelz::v1::Subchannel& subchannel,
237       std::queue<grpc::channelz::v1::Channel>& channel_queue,
238       std::queue<grpc::channelz::v1::Subchannel>& subchannel_queue) {
239     std::cout << "    Subchannel ID" << GetSubchannelID(subchannel) << "_"
240               << GetSubchannelName(subchannel) << " descendence - ";
241     if (subchannel.channel_ref_size() > 0 ||
242         subchannel.subchannel_ref_size() > 0) {
243       if (subchannel.channel_ref_size() > 0) {
244         std::cout << "channel: ";
245         for (const auto& _channelref : subchannel.channel_ref()) {
246           int64_t ch_id = _channelref.channel_id();
247           std::cout << "ID" << ch_id << "_" << _channelref.name() << " ";
248           grpc::channelz::v1::Channel ch = GetChannelRPC(ch_id);
249           channel_queue.push(ch);
250           if (CheckID(ch_id)) {
251             all_channels_.push_back(ch);
252             StoreChannelInJson(ch);
253           }
254         }
255         if (subchannel.subchannel_ref_size() > 0) {
256           std::cout << ", ";
257         }
258       }
259       if (subchannel.subchannel_ref_size() > 0) {
260         std::cout << "subchannel: ";
261         for (const auto& _subchannelref : subchannel.subchannel_ref()) {
262           int64_t subch_id = _subchannelref.subchannel_id();
263           std::cout << "ID" << subch_id << "_" << _subchannelref.name() << " ";
264           grpc::channelz::v1::Subchannel subch = GetSubchannelRPC(subch_id);
265           subchannel_queue.push(subch);
266           if (CheckID(subch_id)) {
267             all_subchannels_.push_back(subch);
268             StoreSubchannelInJson(subch);
269           }
270         }
271       }
272     } else if (subchannel.socket_ref_size() > 0) {
273       std::cout << "socket: ";
274       for (const auto& _socketref : subchannel.socket_ref()) {
275         int64_t so_id = _socketref.socket_id();
276         std::cout << "ID" << so_id << "_" << _socketref.name() << " ";
277         grpc::channelz::v1::Socket so = GetSocketRPC(so_id);
278         if (CheckID(so_id)) {
279           all_sockets_.push_back(so);
280           StoreSocketInJson(so);
281         }
282       }
283     }
284     std::cout << std::endl;
285   }
286
287   // Set up the channelz sampler client
288   // Initialize json as an array
289   void Setup(const std::string& custom_credentials_type,
290              const std::string& server_address) {
291     json_ = grpc_core::Json::Array();
292     rpc_timeout_seconds_ = 20;
293     grpc::ChannelArguments channel_args;
294     std::shared_ptr<grpc::ChannelCredentials> channel_creds =
295         grpc::testing::GetCredentialsProvider()->GetChannelCredentials(
296             custom_credentials_type, &channel_args);
297     if (!channel_creds) {
298       gpr_log(GPR_ERROR,
299               "Wrong user credential type: %s. Allowed credential types: "
300               "INSECURE_CREDENTIALS, ssl, alts, google_default_credentials.",
301               custom_credentials_type.c_str());
302       GPR_ASSERT(0);
303     }
304     std::shared_ptr<grpc::Channel> channel =
305         CreateChannel(server_address, channel_creds);
306     channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel);
307   }
308
309   // Get all servers, keep querying until getting all
310   // Store servers for dumping data
311   // Need to check id repeating for servers
312   void GetServersRPC() {
313     int64_t server_start_id = 0;
314     while (true) {
315       GetServersRequest get_servers_request;
316       GetServersResponse get_servers_response;
317       ClientContext get_servers_context;
318       get_servers_context.set_deadline(
319           grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
320       get_servers_request.set_start_server_id(server_start_id);
321       Status status = channelz_stub_->GetServers(
322           &get_servers_context, get_servers_request, &get_servers_response);
323       if (!status.ok()) {
324         if (status.error_code() == StatusCode::UNIMPLEMENTED) {
325           gpr_log(GPR_ERROR,
326                   "Error status UNIMPLEMENTED. Please check and make sure "
327                   "channelz has been registered on the server being queried.");
328         } else {
329           gpr_log(GPR_ERROR,
330                   "GetServers RPC with GetServersRequest.server_start_id=%d, "
331                   "failed: %s",
332                   int(server_start_id),
333                   get_servers_context.debug_error_string().c_str());
334         }
335         GPR_ASSERT(0);
336       }
337       for (const auto& _server : get_servers_response.server()) {
338         all_servers_.push_back(_server);
339         StoreServerInJson(_server);
340       }
341       if (!get_servers_response.end()) {
342         server_start_id = GetServerID(all_servers_.back()) + 1;
343       } else {
344         break;
345       }
346     }
347     std::cout << "Number of servers = " << all_servers_.size() << std::endl;
348   }
349
350   // Get sockets that belongs to servers
351   // Store sockets for dumping data
352   void GetSocketsOfServers() {
353     for (const auto& _server : all_servers_) {
354       std::cout << "Server ID" << GetServerID(_server) << "_"
355                 << GetServerName(_server) << " listen_socket - ";
356       for (const auto& _socket : _server.listen_socket()) {
357         int64_t so_id = _socket.socket_id();
358         std::cout << "ID" << so_id << "_" << _socket.name() << " ";
359         if (CheckID(so_id)) {
360           grpc::channelz::v1::Socket so = GetSocketRPC(so_id);
361           all_sockets_.push_back(so);
362           StoreSocketInJson(so);
363         }
364       }
365       std::cout << std::endl;
366     }
367   }
368
369   // Get all top channels, keep querying until getting all
370   // Store channels for dumping data
371   // No need to check id repeating for top channels
372   void GetTopChannelsRPC() {
373     int64_t channel_start_id = 0;
374     while (true) {
375       GetTopChannelsRequest get_top_channels_request;
376       GetTopChannelsResponse get_top_channels_response;
377       ClientContext get_top_channels_context;
378       get_top_channels_context.set_deadline(
379           grpc_timeout_seconds_to_deadline(rpc_timeout_seconds_));
380       get_top_channels_request.set_start_channel_id(channel_start_id);
381       Status status = channelz_stub_->GetTopChannels(
382           &get_top_channels_context, get_top_channels_request,
383           &get_top_channels_response);
384       if (!status.ok()) {
385         gpr_log(GPR_ERROR,
386                 "GetTopChannels RPC with "
387                 "GetTopChannelsRequest.channel_start_id=%d failed: %s",
388                 int(channel_start_id),
389                 get_top_channels_context.debug_error_string().c_str());
390         GPR_ASSERT(0);
391       }
392       for (const auto& _topchannel : get_top_channels_response.channel()) {
393         top_channels_.push_back(_topchannel);
394         all_channels_.push_back(_topchannel);
395         StoreChannelInJson(_topchannel);
396       }
397       if (!get_top_channels_response.end()) {
398         channel_start_id = GetChannelID(top_channels_.back()) + 1;
399       } else {
400         break;
401       }
402     }
403     std::cout << std::endl
404               << "Number of top channels = " << top_channels_.size()
405               << std::endl;
406   }
407
408   // layer traverse for each top channel
409   void TraverseTopChannels() {
410     for (const auto& _topchannel : top_channels_) {
411       int tree_depth = 0;
412       std::queue<grpc::channelz::v1::Channel> channel_queue;
413       std::queue<grpc::channelz::v1::Subchannel> subchannel_queue;
414       std::cout << "Tree depth = " << tree_depth << std::endl;
415       GetChannelDescedence(_topchannel, channel_queue, subchannel_queue);
416       while (!channel_queue.empty() || !subchannel_queue.empty()) {
417         ++tree_depth;
418         std::cout << "Tree depth = " << tree_depth << std::endl;
419         int ch_q_size = channel_queue.size();
420         int subch_q_size = subchannel_queue.size();
421         for (int i = 0; i < ch_q_size; ++i) {
422           grpc::channelz::v1::Channel ch = channel_queue.front();
423           channel_queue.pop();
424           GetChannelDescedence(ch, channel_queue, subchannel_queue);
425         }
426         for (int i = 0; i < subch_q_size; ++i) {
427           grpc::channelz::v1::Subchannel subch = subchannel_queue.front();
428           subchannel_queue.pop();
429           GetSubchannelDescedence(subch, channel_queue, subchannel_queue);
430         }
431       }
432       std::cout << std::endl;
433     }
434   }
435
436   // dump data of all entities to stdout
437   void DumpStdout() {
438     std::string data_str;
439     for (const auto& _channel : all_channels_) {
440       std::cout << "channel ID" << GetChannelID(_channel) << "_"
441                 << GetChannelName(_channel) << " data:" << std::endl;
442       // TODO(mohanli): TextFormat::PrintToString records time as seconds and
443       // nanos. Need a more human readable way.
444       ::google::protobuf::TextFormat::PrintToString(_channel.data(), &data_str);
445       printf("%s\n", data_str.c_str());
446     }
447     for (const auto& _subchannel : all_subchannels_) {
448       std::cout << "subchannel ID" << GetSubchannelID(_subchannel) << "_"
449                 << GetSubchannelName(_subchannel) << " data:" << std::endl;
450       ::google::protobuf::TextFormat::PrintToString(_subchannel.data(),
451                                                     &data_str);
452       printf("%s\n", data_str.c_str());
453     }
454     for (const auto& _server : all_servers_) {
455       std::cout << "server ID" << GetServerID(_server) << "_"
456                 << GetServerName(_server) << " data:" << std::endl;
457       ::google::protobuf::TextFormat::PrintToString(_server.data(), &data_str);
458       printf("%s\n", data_str.c_str());
459     }
460     for (const auto& _socket : all_sockets_) {
461       std::cout << "socket ID" << GetSocketID(_socket) << "_"
462                 << GetSocketName(_socket) << " data:" << std::endl;
463       ::google::protobuf::TextFormat::PrintToString(_socket.data(), &data_str);
464       printf("%s\n", data_str.c_str());
465     }
466   }
467
468   // Store a channel in Json
469   void StoreChannelInJson(const grpc::channelz::v1::Channel& channel) {
470     std::string id = grpc::to_string(GetChannelID(channel));
471     std::string type = "Channel";
472     std::string description;
473     ::google::protobuf::TextFormat::PrintToString(channel.data(), &description);
474     grpc_core::Json description_json = grpc_core::Json(description);
475     StoreEntityInJson(id, type, description_json);
476   }
477
478   // Store a subchannel in Json
479   void StoreSubchannelInJson(const grpc::channelz::v1::Subchannel& subchannel) {
480     std::string id = grpc::to_string(GetSubchannelID(subchannel));
481     std::string type = "Subchannel";
482     std::string description;
483     ::google::protobuf::TextFormat::PrintToString(subchannel.data(),
484                                                   &description);
485     grpc_core::Json description_json = grpc_core::Json(description);
486     StoreEntityInJson(id, type, description_json);
487   }
488
489   // Store a server in Json
490   void StoreServerInJson(const grpc::channelz::v1::Server& server) {
491     std::string id = grpc::to_string(GetServerID(server));
492     std::string type = "Server";
493     std::string description;
494     ::google::protobuf::TextFormat::PrintToString(server.data(), &description);
495     grpc_core::Json description_json = grpc_core::Json(description);
496     StoreEntityInJson(id, type, description_json);
497   }
498
499   // Store a socket in Json
500   void StoreSocketInJson(const grpc::channelz::v1::Socket& socket) {
501     std::string id = grpc::to_string(GetSocketID(socket));
502     std::string type = "Socket";
503     std::string description;
504     ::google::protobuf::TextFormat::PrintToString(socket.data(), &description);
505     grpc_core::Json description_json = grpc_core::Json(description);
506     StoreEntityInJson(id, type, description_json);
507   }
508
509   // Store an entity in Json
510   void StoreEntityInJson(std::string& id, std::string& type,
511                          const grpc_core::Json& description) {
512     std::string start, finish;
513     gpr_timespec ago = gpr_time_sub(
514         now_,
515         gpr_time_from_seconds(absl::GetFlag(FLAGS_sampling_interval_seconds),
516                               GPR_TIMESPAN));
517     std::stringstream ss;
518     const time_t time_now = now_.tv_sec;
519     ss << std::put_time(std::localtime(&time_now), "%F %T");
520     finish = ss.str();  // example: "2019-02-01 12:12:18"
521     ss.str("");
522     const time_t time_ago = ago.tv_sec;
523     ss << std::put_time(std::localtime(&time_ago), "%F %T");
524     start = ss.str();
525     grpc_core::Json obj =
526         grpc_core::Json::Object{{"Task", absl::StrFormat("%s_ID%s", type, id)},
527                                 {"Start", start},
528                                 {"Finish", finish},
529                                 {"ID", id},
530                                 {"Type", type},
531                                 {"Description", description}};
532     json_.mutable_array()->push_back(obj);
533   }
534
535   // Dump data in json
536   std::string DumpJson() { return json_.Dump(); }
537
538   // Check if one entity has been recorded
539   bool CheckID(int64_t id) {
540     if (id_set_.count(id) == 0) {
541       id_set_.insert(id);
542       return true;
543     } else {
544       return false;
545     }
546   }
547
548   // Record current time
549   void RecordNow() { now_ = gpr_now(GPR_CLOCK_REALTIME); }
550
551  private:
552   std::unique_ptr<grpc::channelz::v1::Channelz::Stub> channelz_stub_;
553   std::vector<grpc::channelz::v1::Channel> top_channels_;
554   std::vector<grpc::channelz::v1::Server> all_servers_;
555   std::vector<grpc::channelz::v1::Channel> all_channels_;
556   std::vector<grpc::channelz::v1::Subchannel> all_subchannels_;
557   std::vector<grpc::channelz::v1::Socket> all_sockets_;
558   std::unordered_set<int64_t> id_set_;
559   grpc_core::Json json_;
560   int64_t rpc_timeout_seconds_;
561   gpr_timespec now_;
562 };
563
564 int main(int argc, char** argv) {
565   grpc::testing::TestEnvironment env(argc, argv);
566   grpc::testing::InitTest(&argc, &argv, true);
567   std::ofstream output_file(absl::GetFlag(FLAGS_output_json));
568   for (int i = 0; i < absl::GetFlag(FLAGS_sampling_times); ++i) {
569     ChannelzSampler channelz_sampler;
570     channelz_sampler.Setup(absl::GetFlag(FLAGS_custom_credentials_type),
571                            absl::GetFlag(FLAGS_server_address));
572     std::cout << "Wait for sampling interval "
573               << absl::GetFlag(FLAGS_sampling_interval_seconds) << "s..."
574               << std::endl;
575     const gpr_timespec kDelay = gpr_time_add(
576         gpr_now(GPR_CLOCK_MONOTONIC),
577         gpr_time_from_seconds(absl::GetFlag(FLAGS_sampling_interval_seconds),
578                               GPR_TIMESPAN));
579     gpr_sleep_until(kDelay);
580     std::cout << "##### " << i << "th sampling #####" << std::endl;
581     channelz_sampler.RecordNow();
582     channelz_sampler.GetServersRPC();
583     channelz_sampler.GetSocketsOfServers();
584     channelz_sampler.GetTopChannelsRPC();
585     channelz_sampler.TraverseTopChannels();
586     channelz_sampler.DumpStdout();
587     if (!absl::GetFlag(FLAGS_output_json).empty()) {
588       output_file << channelz_sampler.DumpJson() << "\n" << std::flush;
589     }
590   }
591   output_file.close();
592   return 0;
593 }