Obtaining the application’s operational metrics gives us a better understanding of its actual status. By connecting these metrics to monitoring systems such as prometheus, zabbix, etc., the application can be continuously checked and any abnormalities can be alerted and handled in a timely manner.
Pull and Push
There are two ways to interface with monitoring systems, one is Pull and the other is Push.
In the case of Prometheus, for example, the application exposes an HTTP interface for Prometheus to periodically grab metrics through, which is called Pull, while Push is when the application actively pushes metrics to PushGateway.
The Go standard library has a package called expvar, whose name is a combination of exp and var, meaning exported variable.
expvar provides a standardized interface to public variables and exposes them in Json format via HTTP, making it ideal for interfacing with monitoring systems using Pull.
Using the expvar library
expvar is a standard library, meaning we don’t want additional dependencies, and it also provides some out-of-the-box metrics. Let’s learn how to use the library.
When the expvar library is imported (import "expvar"
), the following init functions will be called automatically.
This function registers us with an HTTP service for the /debug/vars path, accessing which will give us the metrics in Json format.
Therefore, we also need to call ListenAndServe to bind the port and start serving HTTP requests.
|
|
The complete code is as follows.
After running the program up and requesting it via curl, the following results are obtained.
|
|
As you can see, expvar already provides two indicators by default, namely program execution commands (os.Args
) and runtime memory allocation (runtime.Memstats
) information.
Highlights of the expvar library
The most important things in expvar are the Publish
function and the Var
interface.
|
|
The Publish function takes two arguments in its signature, name is the name of the indicator we specify. For example, in the Publish("cmdline", Func(cmdline))
code line under the init function of expvar above, where cmdline
is the indicator name and Func(cmdline)
is an expvar.Func variable that implements the Var interface.
Var interface, which defines only a String method. Note that the method must return a valid Json string.
For ease of use, five exported variable types are provided in the expvar library, all of which implement the Var interface.
We can create the first four types of variables and register the indicators by calling the expvar.NewXXX function respectively.
For example, the expvar.NewInt function calls the Publish method internally to bind the indicator name to a variable of type expvar.Int.
And the expvar.Func type is actually designed to allow us to customize the export type.
For example, let’s say we want to expose the following defined structure.
First you need to create a data generation function. It is used to export the data in this function each time the HTTP service path is called.
Finally, just register the indicator name with the Publish function.
|
|
Complete Example
Below, we give a complete example covering the five exported variable types.
|
|
In the above example, we get some system information through the gopsutil library and show how to export this information through the various variable types in expvar.
Using curl to request localhost:8080/debug/vars
, the result is as follows.
|
|
Summary
The standard library expvar provides a standardized interface to the public variables that need to be exported and is relatively simple to use.
Several base types defined inside the expvar package are given concurrency-safe methods of operation. We don’t need to implement them all over again, they are ready to use out of the box.
However, the number of imports of this library is less than 10,000 for the public projects counted on https://go.dev/.