At FullStory, we use gRPC for all server-to-server communications. In a past post we detailed the story of gRPCurl, a useful command-line tool for interacting with gRPC servers. But we knew we could level this up even further.
While command-line tools like gRPCurl are extremely useful, a graphical user interface can often reduce friction and be more intuitive than a command-line interface. So that was clearly the next step, hence we built gRPCui (pronounced /dʒi ɑr pi kui/, like “jee are pee cooey”).
What is gRPCui?
So, “what is gRPCui?” you may ask. Much like its predecessor, gRPCurl, it is two things simultaneously:
- It is a command-line tool (written in Go). When you invoke
grpcuiand point it at a gRPC server, it will dial that gRPC server and then start up its own web server. On navigating a browser to that just-started web server, you will find a web UI that allows you to explore the gRPC server’s RPC interfaces, build requests via a web form, and then send requests and invoke RPCs.
- It is also a Go library. With the Go packages that comprise gRPCui, you can easily embed a web UI into any Go gRPC server.
gRPCurl includes a Go package that provides the ability to easily perform dynamic dispatch of RPCs. The gRPCui Go code uses that library to send RPCs; so gRPCui is actually powered by gRPCurl.
The idea for gRPCui comes from similar tools that some of us worked with in past lives at Square and Google. At Square, some of us had a hand in building a bespoke protocol-buffer-based RPC system named Sake RPC. Java and Go Sake RPC servers embedded a web UI for Sake, very similar to what gRPCui provides. And at Google, a protocol-buffer-based RPC system named Stubby was ubiquitous. Stubby was a closed source precursor to gRPC. Running “stubby web” would start a web server, which provided a web UI that was part of the inspiration for gRPCui.
Outside of protocol-buffer-based RPC systems, gRPCui can be compared to tools like Postman, which provides a web UI for exploring and interacting with REST APIs. Postman consumes OpenAPI (formerly known as Swagger) spec files, which describe the API, not unlike how protocol buffer source files describe a gRPC API.
In the next two sections we’ll review a couple of core use cases for gRPCui and provide more details on what it is and how to use it. In the final two sections, we’ll look at some neat ways to put it to use: high-leverage things you can do when a tool like gRPCui exists.
Like gRPCurl, gRPCui lets you explore a running server’s RPC interfaces. With gRPCurl, you can issue several commands to list the exposed interfaces and then describe the various elements of the request and response message schemas. And gRPCui provides the same capability, but in a web-based GUI that allows you to explore the RPC endpoints via drop-down lists and HTML forms.
Also like gRPCurl, the gRPCui tool works best when servers support Server Reflection. This makes exploring the server’s RPC endpoints effortless. Let's take a look at
api.grpc.me, an example gRPC server hosted by FullStory that provides a simple gRPC interface for listennotes.com:
This will also open a browser tab pointed at that URL:
All of the RPC services exposed by the server are shown in the Service name drop-down. On selecting a service, we can see all of the RPC methods for that service in the Method name drop-down. When you select a method, the Request Data form below it reconfigures itself based on the request attributes of the selected method.
The web form indicates the fully-qualified name of the request message, followed by form inputs for each request attribute. Each input shows the name and type of the field, a checkbox indicating whether that attribute is included in the request message, and finally a form input into which the request value can be entered.
The first thing to note here is that you need to check the box to the right of the field name in order to add that field to the request. After the box is checked, you can then use the form input to set the value for that request field.
In addition to entering data via the form inputs, you can select the Raw Request (JSON) tab and paste in a JSON request. (Or you can copy the JSON request that you just constructed with the form inputs.)
Pressing the Invoke button sends the request to the server for processing. When the RPC completes, you’ll be shown a formatted view of the response data:
Exploring the RPC schema and initiating RPC operations couldn’t be simpler!
Caveats for streaming RPCs: for client-streaming methods, gRPCui requires you to define the entire stream of inputs upfront, all at once. Invoking server-streaming methods will wait to download all response messages before showing the results page.
In addition to a stand-alone command-line program, gRPCui is also a Go library. With this Go library, you can easily embed the gRPCui into any gRPC server that is written in Go!
Let’s say your server’s primary port is 8080. You can then add an HTTP server on port 8081 (that is adequately firewalled/protected, to prevent unauthorized access) that exposes the gRPCui, for accessing all of the server’s RPC endpoints. If the gRPC server supports server reflection, this can be done with a very small amount of code using the
HandlerViaReflection function in the
github.com/fullstorydev/grpcui/standalone Go package:
(A larger, more complete example can be found in this gist.)
Since your gRPC server may support sensitive internal operations, it is important that the HTTP server that exposes the gRPCui has adequate access controls and restrictions in place. This could be handled with HTTP middleware in the Go container itself or by putting the server behind an authenticating proxy that can enforce access control policies and prevent unauthorized access to the gRPCui.
Automatic Admin UIs
gRPCui can accelerate your development by providing basic UIs for admin operations in your RPC backend servers.
When adding tools for system operators (like an on-call engineer or customer support staff), each task typically has some needed input parameters and some outputs to indicate the result of the task. Whether you are providing tools that let you tweak customer configuration settings or view low-level storage details in your data model, the basic operation is often easily described as an RPC: just model the needed input parameters as a request and the output results as a response.
Once the interface is defined, you can then create the implementation in your server. If you use gRPC throughout your stack, you may already be defining these operations using protocol buffers and gRPC interfaces.
It’s often the next step that can be the hurdle: exposing this functionality to humans, such as in the form of command-line tools or internal web applications. That’s where gRPCui comes in: depending on who is executing the task and how often, the UI provided by gRPCui is often good enough. This provides a simple mechanism to expose tools and functions to your system operators: just implement the function as an RPC method! There’s no need to spend time integrating the function into a web application or creating a bespoke user interface. Just point operators at an embedded gRPCui for the service, and let them initiate the tasks through it.
Similar to implementing admin operations as RPC interfaces, you can also create RPC interfaces for manually-initiated jobs and ad-hoc processes.
The premise is very similar to creating automatic admin UIs. If you need to run a job, such as a migration, a backfill, or some other analysis, in your production environment, you can deploy it as a gRPC method and invoke it using gRPCui.
This allows the logic for these jobs to go through your standard code review and deployment process. Once deployed, you can protect the endpoint using standard production access controls, such as firewalls or secure proxies in front of the port on which gRPCui is served. This also allows you to get to the logs and metrics for the job, since they are made available via the same mechanisms as standard application metrics -- they are just part of a normal application.
The reason this can be an advantageous way to ship ad-hoc processes is that it reduces the need for operators to run arbitrary code in your production environment. So you don’t need to grant people permission to create arbitrary Kubernetes jobs, or to copy and execute arbitrary programs on VMs. You also don’t need to go through provisioning overhead or launch checklists for each ad-hoc process. You can instead rely on existing access control and peer review procedures.
So you can leverage gRPCui to accelerate these kinds of chores without sacrificing quality or security.
We’ve discussed several ways that gRPCui can be useful if you use gRPC. There are probably more ways that we haven’t even thought about!
If you want to give it a try, you can download v1.0.0 from GitHub, pull the image from Docker Hub and run it in a container, or install it using Homebrew (
brew install grpcui) if you’re on a Mac OS device.