{"id":13739933,"url":"https://github.com/grpc-ecosystem/grpcdebug","last_synced_at":"2025-04-12T16:36:56.655Z","repository":{"id":41093693,"uuid":"348887981","full_name":"grpc-ecosystem/grpcdebug","owner":"grpc-ecosystem","description":"grpcdebug is a command line interface focusing on simplifying the debugging process of gRPC applications.","archived":false,"fork":false,"pushed_at":"2025-03-18T20:59:31.000Z","size":103,"stargazers_count":160,"open_issues_count":4,"forks_count":21,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-03T20:09:24.224Z","etag":null,"topics":["cli","debug","go","golang","grpc"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grpc-ecosystem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-18T00:08:57.000Z","updated_at":"2025-04-02T23:42:16.000Z","dependencies_parsed_at":"2024-06-19T00:06:24.475Z","dependency_job_id":"2957b117-f697-4977-8eb8-0db076c51fad","html_url":"https://github.com/grpc-ecosystem/grpcdebug","commit_stats":{"total_commits":24,"total_committers":6,"mean_commits":4.0,"dds":0.25,"last_synced_commit":"88c9872db554e23879c480705bba7e14ede76efa"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grpc-ecosystem%2Fgrpcdebug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grpc-ecosystem%2Fgrpcdebug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grpc-ecosystem%2Fgrpcdebug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grpc-ecosystem%2Fgrpcdebug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grpc-ecosystem","download_url":"https://codeload.github.com/grpc-ecosystem/grpcdebug/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248597474,"owners_count":21130884,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","debug","go","golang","grpc"],"created_at":"2024-08-03T04:00:39.836Z","updated_at":"2025-04-12T16:36:56.632Z","avatar_url":"https://github.com/grpc-ecosystem.png","language":"Go","funding_links":[],"categories":["Tools","Go"],"sub_categories":["CLI"],"readme":"# grpcdebug\n[![Go Report\nCard](https://goreportcard.com/badge/github.com/grpc-ecosystem/grpcdebug)](https://goreportcard.com/report/github.com/grpc-ecosystem/grpcdebug)\n\ngrpcdebug is a command line interface focusing on simplifying the debugging\nprocess of gRPC applications. grpcdebug fetches the internal states of the gRPC\nlibrary from the application via gRPC protocol and provide a human-friendly UX\nto browse them. Currently, it supports Channelz/Health Checking/CSDS (aka. admin\nservices). In other words, it can fetch statistics about how many RPCs has being\nsent or failed on a given gRPC channel, it can inspect address resolution\nresults, it can dump the in-effective xDS configuration that directs the routing\nof RPCs.\n\nIf you are looking for a tool to send gRPC requests and interact with a gRPC\nserver, please checkout https://github.com/fullstorydev/grpcurl.\n\n```\ngrpcdebug is an gRPC service admin CLI\n\nUsage:\n  grpcdebug \u003ctarget address\u003e [flags] \u003ccommand\u003e\n\nAvailable Commands:\n  channelz    Display gRPC states in a human readable way.\n  health      Check health status of the target service (default \"\").\n  help        Help about any command\n  xds         Fetch xDS related information.\n\nFlags:\n      --credential_file string        Sets the path of the credential file; used in [tls] mode\n  -h, --help                          help for grpcdebug\n      --security string               Defines the type of credentials to use [tls, google-default, insecure] (default \"insecure\")\n      --server_name_override string   Overrides the peer server name if non empty; used in [tls] mode\n  -t, --timestamp                     Print timestamp as RFC3339 instead of human readable strings\n  -v, --verbose                       Print verbose information for debugging\n\nUse \"grpcdebug \u003ctarget address\u003e  [command] --help\" for more information about a command.\n```\n\n## Table of Contents\n- [grpcdebug](#grpcdebug)\n  - [Table of Contents](#table-of-contents)\n  - [Installation](#installation)\n    - [Use Compiled Binaries](#use-compiled-binaries)\n    - [Compile From Source](#compile-from-source)\n  - [Quick Start](#quick-start)\n    - [Connect \u0026 Security](#connect--security)\n      - [Insecure Connection](#insecure-connection)\n      - [TLS Connection - Flags](#tls-connection---flags)\n      - [Server Connection Config](#server-connection-config)\n    - [Health](#health)\n    - [Channelz](#channelz)\n      - [Usage 1: Raw Channelz Output](#usage-1-raw-channelz-output)\n      - [Usage 2: List Client Channels](#usage-2-list-client-channels)\n      - [Usage 3: List Servers](#usage-3-list-servers)\n      - [Usage 4: Inspect a Channel](#usage-4-inspect-a-channel)\n      - [Usage 5: Inspect a Subchannel](#usage-5-inspect-a-subchannel)\n      - [Usage 6: Inspect a Socket](#usage-6-inspect-a-socket)\n      - [Usage 7: Inspect a Server](#usage-7-inspect-a-server)\n      - [Usage 8: Pagination](#usage-8-pagination)\n    - [Debug xDS](#debug-xds)\n      - [Usage 1: xDS Resources Overview](#usage-1-xds-resources-overview)\n      - [Usage 2: Dump xDS Configs](#usage-2-dump-xds-configs)\n      - [Usage 3: Filter xDS Configs](#usage-3-filter-xds-configs)\n  - [Admin Services](#admin-services)\n    - [gRPC Java:](#grpc-java)\n    - [gRPC Go:](#grpc-go)\n    - [gRPC C++:](#grpc-c)\n\n## Installation\n\n### Use Compiled Binaries\n\nThe download links of the binaries can be found at\nhttps://github.com/grpc-ecosystem/grpcdebug/releases. You can find the\nprecompiled artifacts for `macOS`/`Linux`/`Windows`.\n\n### Compile From Source\n\nMinimum Golang Version 1.22. Official Golang install guide:\nhttps://golang.org/doc/install.\n\nYou can install the `grpcdebug` tool using command:\n\n```shell\ngo install -v github.com/grpc-ecosystem/grpcdebug@latest\n```\n\nYou can check your Golang version with:\n\n```shell\ngo version\n```\n\nDon't forget to add Golang binaries to your `PATH`:\n\n```shell\nexport PATH=$PATH:$(go env GOPATH)/bin\n```\n\n## Quick Start\n\nIf certain commands are confusing, please try to use `-h` to get more context.\nSuggestions and ideas are welcome, please post them to\nhttps://github.com/grpc-ecosystem/grpcdebug/issues!\n\nIf you haven't got your gRPC application instrumented, feel free to try out the\nmocking `testserver` which implemented admin services.\n\n```shell\ncd internal/testing/testserver\ngo run main.go\n# Serving Business Logic on :10001\n# Serving Insecure Admin Services on :50051\n# Serving Secure Admin Services on :50052\n# ...\n```\n\n### Connect \u0026 Security\n\n#### Insecure Connection\n\nTo connect to a gRPC endpoint without any credentials, we don't use any special\nflags. If the local network can connect to the given gRPC endpoint, it should\njust work. For example, if I have a gRPC application exposing admin services at\n`localhost:50051`:\n\n```shell\ngrpcdebug localhost:50051 channelz channels\n```\n\n#### TLS Connection - Flags\n\nOne way to establish a TLS connection with grpcdebug is by specifying the\ncredentials via command line flags. For example:\n\n```shell\ngrpcdebug localhost:50052 --security=tls --credential_file=./internal/testing/ca.pem --server_name_override=\"*.test.youtube.com\" channelz channels\n```\n\n#### Server Connection Config\n\nAlternatively, like OpenSSH clients, you can specify the security settings in a\n`grpcdebug_config.yaml` file. grpcdebug CLI will find matching connection config and\nthen use it to connect.\n\n```yaml\nservers:\n  \"pattern string\":\n    real_address: string\n    security: insecure/tls\n    credential_file: string\n    server_name_override: string\n```\n\nHere is an example config file\n[grpcdebug_config.yaml](internal/testing/grpcdebug_config.yaml).\n\nEach server config can have the following settings:\n\n* Pattern: the string right after `Server ` which dictates if this rule should\n  apply;\n* RealAddress: if present, override the given target address, which allows\n  giving nicknames/aliases to frequently used addresses;\n* Security: allows `insecure` or `tls`, expecting more in the future;\n* CredentialFile: path to the credential file;\n* ServerNameOverride: override the hostname, which is useful for local reproductions to\n  comply with the certificates' common name requirement.\n\ngrpcdebug searches the config file in the following order:\n\n1. Check if the environment variable `GRPCDEBUG_CONFIG` is set, if so, load from the\n   given path;\n2. Try to load the `grpcdebug_config.yaml` file in the current working directory;\n3. Try to load the `grpcdebug_config.yaml` file in the user config directory (Linux:\n   `$HOME/.config`, macOS: `$HOME/Library/Application Support`, Windows:\n   `%AppData%`, see\n   [`os.UserConfigDir()`](https://golang.org/pkg/os/#UserConfigDir)).\n\nFor example, we can connect to our mock test server's secure admin port via:\n\n```shell\nGRPCDEBUG_CONFIG=internal/testing/grpcdebug_config.yaml grpcdebug localhost:50052 channelz channels\n# Or\nGRPCDEBUG_CONFIG=internal/testing/grpcdebug_config.yaml grpcdebug prod channelz channels\n```\n\n### Health\n\ngrpcdebug can be used to fetch the health checking status of a peer gRPC\napplication (see\n[health.proto](https://github.com/grpc/grpc/blob/master/src/proto/grpc/health/v1/health.proto)).\ngRPC's health checking works at the service-level, meaning services registered on\nthe same gRPC server may have different health statuses. The health status of\nservice `\"\"` is used to represent the overall health status of the gRPC\napplication.\n\nTo simply fetch the overall health status:\n\n```shell\ngrpcdebug localhost:50051 health\n# \u003cOverall\u003e:  SERVING\n# or\n# \u003cOverall\u003e:  NOT_SERVING\n```\n\nOr fetch individual service's health status:\n\n```shell\ngrpcdebug localhost:50051 health helloworld.Greeter\n# \u003cOverall\u003e:            SERVING\n# helloworld.Greeter:   SERVING\n```\n\n### Channelz\n\n[Channelz](https://github.com/grpc/proposal/blob/master/A14-channelz.md) is a\nchannel tracing library that allows applications to remotely query gRPC internal\ndebug information. Also, Channelz has a web interface (see\n[gdebug](https://github.com/grpc/grpc-experiments/tree/master/gdebug)).\ngrpcdebug is able to fetch information and present it in a more readable way.\n\nGenerally, you wil start with either the `servers` or `channels` command and\nthen work down to the details.\n\n#### Usage 1: Raw Channelz Output\n\nFor all Channelz commands, you can add `--json` to get the raw Channelz output.\n\n```shell\ngrpcdebug localhost:50051 channelz servers --json\n#[\n#  {\n#    \"ref\": {\n#      \"server_id\": 2,\n#      \"name\": \"ServerImpl{logId=2, transportServer=NettyServer{logId=1, addresses=[0.0.0.0/0.0.0.0:50051]}}\"\n#    },\n#    \"data\": {\n#      \"calls_started\": 3,\n#      \"calls_succeeded\": 2,\n#      \"last_call_started_timestamp\": {\n#        \"seconds\": 1680220688,\n#        \"nanos\": 444000000\n#      }\n#    },\n#    \"listen_socket\": [\n#      {\n#        \"socket_id\": 3,\n#        \"name\": \"ListenSocket{logId=3, channel=[id: 0x05f9f16c, L:/0:0:0:0:0:0:0:0%0:50051]}\"\n#      }\n#    ]\n#  }\n#]\n\n```\n\n#### Usage 2: List Client Channels\n\n```shell\ngrpcdebug localhost:50051 channelz channels\n# Channel ID   Target            State     Calls(Started/Succeeded/Failed)   Created Time\n# 7            localhost:10001   READY     5136/4631/505                     8 minutes ago\n```\n\n#### Usage 3: List Servers\n\n```shell\ngrpcdebug localhost:50051 channelz servers\n# Server ID   Listen Addresses   Calls(Started/Succeeded/Failed)   Last Call Started\n# 1           [:::10001]         2852/2530/322                     now\n# 2           [:::50051]         29/28/0                           now\n# 3           [:::50052]         4/4/0                             26 seconds ago\n```\n\n#### Usage 4: Inspect a Channel\n\nYou can identify a channel via the Channel ID.\n\n```shell\ngrpcdebug localhost:50051 channelz channel 7\n# Channel ID:        7\n# Target:            localhost:10001\n# State:             READY\n# Calls Started:     3976\n# Calls Succeeded:   3520\n# Calls Failed:      456\n# Created Time:      6 minutes ago\n# ---\n# Subchannel ID   Target            State     Calls(Started/Succeeded/Failed)   CreatedTime\n# 8               localhost:10001   READY     3976/3520/456                     6 minutes ago\n# ---\n# Severity   Time            Child Ref                      Description\n# CT_INFO    6 minutes ago                                  Channel Created\n# CT_INFO    6 minutes ago                                  Resolver state updated: {Addresses:[{Addr:localhost:10001 ServerName: Attributes:\u003cnil\u003e Type:0 Metadata:\u003cnil\u003e}] ServiceConfig:\u003cnil\u003e Attributes:\u003cnil\u003e} (resolver returned new addresses)\n# CT_INFO    6 minutes ago                                  Channel switches to new LB policy \"pick_first\"\n# CT_INFO    6 minutes ago   subchannel(subchannel_id:8 )   Subchannel(id:8) created\n# CT_INFO    6 minutes ago                                  Channel Connectivity change to CONNECTING\n# CT_INFO    6 minutes ago                                  Channel Connectivity change to READY\n```\n\n#### Usage 5: Inspect a Subchannel\n\n```shell\ngrpcdebug localhost:50051 channelz subchannel 8\n# Subchannel ID:     8\n# Target:            localhost:10001\n# State:             READY\n# Calls Started:     4490\n# Calls Succeeded:   3966\n# Calls Failed:      524\n# Created Time:      7 minutes ago\n# ---\n# Socket ID   Local-\u003eRemote          Streams(Started/Succeeded/Failed)   Messages(Sent/Received)\n# 9           ::1:47436-\u003e::1:10001   4490/4490/0                         4490/3966\n```\n\n#### Usage 6: Inspect a Socket\n\n```shell\ngrpcdebug localhost:50051 channelz socket 9\n# Socket ID:                       9\n# Address:                         ::1:47436-\u003e::1:10001\n# Streams Started:                 4807\n# Streams Succeeded:               4807\n# Streams Failed:                  0\n# Messages Sent:                   4807\n# Messages Received:               4243\n# Keep Alives Sent:                0\n# Last Local Stream Created:       now\n# Last Remote Stream Created:      a long while ago\n# Last Message Sent Created:       now\n# Last Message Received Created:   now\n# Local Flow Control Window:       65535\n# Remote Flow Control Window:      65535\n# ---\n# Socket Options Name   Value\n# SO_LINGER             [type.googleapis.com/grpc.channelz.v1.SocketOptionLinger]:{duration:{}}\n# SO_RCVTIMEO           [type.googleapis.com/grpc.channelz.v1.SocketOptionTimeout]:{duration:{}}\n# SO_SNDTIMEO           [type.googleapis.com/grpc.channelz.v1.SocketOptionTimeout]:{duration:{}}\n# TCP_INFO              [type.googleapis.com/grpc.channelz.v1.SocketOptionTcpInfo]:{tcpi_state:1  tcpi_options:7  tcpi_rto:204000  tcpi_ato:40000  tcpi_snd_mss:32768  tcpi_rcv_mss:1093  tcpi_last_data_sent:16  tcpi_last_data_recv:16  tcpi_last_ack_recv:16  tcpi_pmtu:65536  tcpi_rcv_ssthresh:65476  tcpi_rtt:192  tcpi_rttvar:153  tcpi_snd_ssthresh:2147483647  tcpi_snd_cwnd:10  tcpi_advmss:65464  tcpi_reordering:3}\n# ---\n# Security Model:   TLS\n# Standard Name:    TLS_AES_128_GCM_SHA256\n```\n\n#### Usage 7: Inspect a Server\n\n```shell\ngrpcdebug localhost:50051 channelz server 1\n# Server Id:           1\n# Listen Addresses:    [:::10001]\n# Calls Started:       5250\n# Calls Succeeded:     4647\n# Calls Failed:        603\n# Last Call Started:   now\n# ---\n# Socket ID   Local-\u003eRemote          Streams(Started/Succeeded/Failed)   Messages(Sent/Received)\n# 10          ::1:10001-\u003e::1:47436   5250/5250/0                         4647/5250\n```\n\n#### Usage 8: Pagination\n\nIn production, there may be thousands of clients/servers/sockets. It would be very noisy to print all of them at once, so Channelz supports pagination through `start_id` and `max_results`\n\n```shell\ngrpcdebug localhost:50051 channelz servers --start_id=0 --max_results=1\n# Server ID   Listen Addresses   Calls(Started/Succeeded/Failed)   Last Call Started\n# 1           [:::10001]         2852/2530/322                     now\ngrpcdebug localhost:50051 channelz servers --start_id=2 --max_results=2\n# Server ID   Listen Addresses   Calls(Started/Succeeded/Failed)   Last Call Started\n# 2           [:::50051]         29/28/0                           now\n# 3           [:::50052]         4/4/0                             26 seconds ago\n```\n\nIt works similarly for printing channels via `channelz channels` and printing server sockets via `channelz server`.\n\n### Debug xDS\n\n[xDS](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/dynamic_configuration)\nis a data plane configuration API commonly used in service mesh projects. It's\ncreated by Envoy, used by Istio, Traffic Director, and gRPC.\n\n#### Usage 1: xDS Resources Overview\n\nThe xDS resources status might be `REQUESTED`/`DOES_NOT_EXIST`/`ACKED`/`NACKED` (see\n[config_dump.proto](https://github.com/envoyproxy/envoy/blob/b0ce15c96cebd89cf391869e49017325cd7faaa8/api/envoy/admin/v3/config_dump.proto#L22)).\nThis view is intended for a quick scan if a configuration is propagated from the\nservice mesh control plane.\n\n```shell\ngrpcdebug localhost:50051 xds status\n# Name                                                                   Status    Version               Type                                                                 LastUpdated\n# xds-test-server:1337                                                   ACKED     1617141154495058478   type.googleapis.com/envoy.config.listener.v3.Listener                2 days ago\n# URL_MAP/1040920224690_sergii-psm-test-url-map_0_xds-test-server:1337   ACKED     1617141154495058478   type.googleapis.com/envoy.config.route.v3.RouteConfiguration         2 days ago\n# cloud-internal-istio:cloud_mp_1040920224690_6530603179561593229        ACKED     1617141154495058478   type.googleapis.com/envoy.config.cluster.v3.Cluster                  2 days ago\n# cloud-internal-istio:cloud_mp_1040920224690_6530603179561593229        ACKED     1                     type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment   2 days ago\n```\n\n#### Usage 2: Dump xDS Configs\n\n```shell\ngrpcdebug localhost:50051 xds config\n# {\n#   \"config\":  [\n#     {\n#       \"node\":  {\n#         \"id\":  \"projects/1040920224690/networks/default/nodes/5cc9170c-d5b4-4061-b431-c1d43e6ac0ab\",\n#         \"cluster\":  \"cluster\",\n#         \"metadata\":  {\n#           \"INSTANCE_IP\":  \"192.168.120.31\",\n#           \"TRAFFICDIRECTOR_GCP_PROJECT_NUMBER\":  \"1040920224690\",\n#           \"TRAFFICDIRECTOR_NETWORK_NAME\":  \"default\"\n#         },\n# ...\n```\n\nFor an example config dump, see\n[csds_config_dump.json](internal/testing/testserver/csds_config_dump.json).\n\n#### Usage 3: Filter xDS Configs\n\nThe dumped xDS config can be quite verbose, if I only interested in certain xDS\ntype, grpcdebug can only print the selected section.\n\n```shell\ngrpcdebug localhost:50051 xds config --type=eds\n# {\n#   \"dynamicEndpointConfigs\":  [\n#     {\n#       \"versionInfo\":  \"1\",\n#       \"endpointConfig\":  {\n#         \"@type\":  \"type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment\",\n#         \"clusterName\":  \"cloud-internal-istio:cloud_mp_1040920224690_6530603179561593229\",\n#         \"endpoints\":  [\n#           {\n#             \"locality\":  {\n#               \"subZone\":  \"jf:us-central1-a_7062512536751318190_neg\"\n#             },\n#             \"lbEndpoints\":  [\n#               {\n#                 \"endpoint\":  {\n#                   \"address\":  {\n#                     \"socketAddress\":  {\n#                       \"address\":  \"192.168.120.26\",\n#                       \"portValue\":  8080\n#                     }\n#                   }\n#                 },\n#                 \"healthStatus\":  \"HEALTHY\"\n#               }\n#             ],\n#             \"loadBalancingWeight\":  100\n#           }\n#         ]\n#       },\n#       \"lastUpdated\":  \"2021-03-31T01:20:33.936Z\",\n#       \"clientStatus\":  \"ACKED\"\n#     }\n#   ]\n# }\n```\n\n## Admin Services\n\n### gRPC Java:\n\n```diff\n--- a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java\n+++ b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java\n@@ -18,6 +18,7 @@ package io.grpc.examples.helloworld;\n\n import io.grpc.Server;\n import io.grpc.ServerBuilder;\n+import io.grpc.services.AdminInterface;\n import io.grpc.stub.StreamObserver;\n import java.io.IOException;\n import java.util.concurrent.TimeUnit;\n@@ -36,6 +37,7 @@ public class HelloWorldServer {\n     int port = 50051;\n     server = ServerBuilder.forPort(port)\n         .addService(new GreeterImpl())\n+        .addServices(AdminInterface.getStandardServices())\n         .build()\n         .start();\n     logger.info(\"Server started, listening on \" + port);\n```\n\n\n### gRPC Go:\n\n```diff\n--- a/examples/helloworld/greeter_server/main.go\n+++ b/examples/helloworld/greeter_server/main.go\n@@ -27,6 +27,7 @@ import (\n        \"net\"\n\n        \"google.golang.org/grpc\"\n+       \"google.golang.org/grpc/admin\"\n        pb \"google.golang.org/grpc/examples/helloworld/helloworld\"\n )\n\n@@ -51,6 +52,11 @@ func main() {\n                log.Fatalf(\"failed to listen: %v\", err)\n        }\n        s := grpc.NewServer()\n+       cleanup, err := admin.Register(s)\n+       if err != nil {\n+               log.Fatalf(\"failed to register admin: %v\", err)\n+       }\n+       defer cleanup()\n        pb.RegisterGreeterServer(s, \u0026server{})\n        if err := s.Serve(lis); err != nil {\n                log.Fatalf(\"failed to serve: %v\", err)\n```\n\n\n### gRPC C++:\n\n```diff\n--- a/examples/cpp/helloworld/greeter_server.cc\n+++ b/examples/cpp/helloworld/greeter_server.cc\n@@ -20,6 +20,7 @@\n #include \u003cmemory\u003e\n #include \u003cstring\u003e\n\n+#include \u003cgrpcpp/ext/admin_services.h\u003e\n #include \u003cgrpcpp/ext/proto_server_reflection_plugin.h\u003e\n #include \u003cgrpcpp/grpcpp.h\u003e\n #include \u003cgrpcpp/health_check_service_interface.h\u003e\n@@ -60,6 +61,7 @@ void RunServer() {\n   // Register \"service\" as the instance through which we'll communicate with\n   // clients. In this case it corresponds to an *synchronous* service.\n   builder.RegisterService(\u0026service);\n+  grpc::AddAdminServices(\u0026builder);\n   // Finally assemble the server.\n   std::unique_ptr\u003cServer\u003e server(builder.BuildAndStart());\n   std::cout \u003c\u003c \"Server listening on \" \u003c\u003c server_address \u003c\u003c std::endl;\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrpc-ecosystem%2Fgrpcdebug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrpc-ecosystem%2Fgrpcdebug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrpc-ecosystem%2Fgrpcdebug/lists"}