Il existe deux façons d'interfacer avec le système de surveillance, l'une est Pull et l'autre est Push.
Prenons Prometheus comme exemple. L'application expose l'interface HTTP et permet à Prometheus de capturer périodiquement des indicateurs via l'interface. Dans Push, l'application transmet activement les indicateurs à PushGateway et Prometheus accède à PushGateway pour capturer les données.
Il existe un package appelé expvar dans la bibliothèque standard Go. Son nom est une combinaison de exp et var, ce qui signifie exporter des variables.
expvar fournit une interface standardisée pour les variables publiques et expose ces variables au format Json via HTTP, ce qui est très approprié pour se connecter au système de surveillance à l'aide de Pull.
expvar est une bibliothèque standard, ce qui signifie que nous n'avons pas besoin de dépendances supplémentaires, et elle fournit également des indicateurs prêts à l'emploi. Apprenons à utiliser cette bibliothèque.
Lorsque la bibliothèque expvar est référencée (<code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">import "expvar"</span>
),以下 init 函数将被自动调用。
func init() { http.HandleFunc("/debug/vars", expvarHandler) Publish("cmdline", Func(cmdline)) Publish("memstats", Func(memstats)) }
该函数为我们注册了 /debug/vars 路径的 HTTP 服务,访问该路径将得到 Json 格式的指标。
因此,我们还需要调用 ListenAndServe 绑定端口,并开始服务 HTTP 请求。
http.ListenAndServe(":8080", nil)
完整代码如下
package main import ( _ "expvar" "net/http" ) func main() { http.ListenAndServe(":8080", nil) }
将程序运行起来后,通过 curl 请求,得到以下结果
$ curl localhost:8080/debug/vars { "cmdline": ["/var/folders/xk/gn46n46d503dsztbc6_9qb2h0000gn/T/go-build1657217338/b001/exe/main"], "memstats": {"Alloc":278880,"TotalAlloc":278880,"Sys":8735760,"Lookups":0,"Mallocs":1169,"Frees":87,"HeapAlloc":278880,"HeapSys":3866624,"HeapIdle":2949120,"HeapInuse":917504,"HeapReleased":2899968,"HeapObjects":1082,"StackInuse":327680,"StackSys":327680,"MSpanInuse":28696,"MSpanSys":32640,"MCacheInuse":9600,"MCacheSys":15600,"BuckHashSys":3875,"GCSys":3826448,"OtherSys":662893,"NextGC":4194304,"LastGC":0,"PauseTotalNs":0,"PauseNs":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"PauseEnd":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"NumGC":0,"NumForcedGC":0,"GCCPUFraction":0,"EnableGC":true,"DebugGC":false,"BySize":[{"Size":0,"Mallocs":0,"Frees":0},{"Size":8,"Mallocs":41,"Frees":0},{"Size":16,"Mallocs":496,"Frees":0},{"Size":24,"Mallocs":63,"Frees":0},{"Size":32,"Mallocs":28,"Frees":0},{"Size":48,"Mallocs":134,"Frees":0},{"Size":64,"Mallocs":50,"Frees":0},{"Size":80,"Mallocs":17,"Frees":0},{"Size":96,"Mallocs":17,"Frees":0},{"Size":112,"Mallocs":6,"Frees":0},{"Size":128,"Mallocs":9,"Frees":0},{"Size":144,"Mallocs":9,"Frees":0},{"Size":160,"Mallocs":18,"Frees":0},{"Size":176,"Mallocs":6,"Frees":0},{"Size":192,"Mallocs":0,"Frees":0},{"Size":208,"Mallocs":37,"Frees":0},{"Size":224,"Mallocs":6,"Frees":0},{"Size":240,"Mallocs":0,"Frees":0},{"Size":256,"Mallocs":12,"Frees":0},{"Size":288,"Mallocs":7,"Frees":0},{"Size":320,"Mallocs":2,"Frees":0},{"Size":352,"Mallocs":13,"Frees":0},{"Size":384,"Mallocs":1,"Frees":0},{"Size":416,"Mallocs":30,"Frees":0},{"Size":448,"Mallocs":1,"Frees":0},{"Size":480,"Mallocs":2,"Frees":0},{"Size":512,"Mallocs":0,"Frees":0},{"Size":576,"Mallocs":5,"Frees":0},{"Size":640,"Mallocs":5,"Frees":0},{"Size":704,"Mallocs":3,"Frees":0},{"Size":768,"Mallocs":0,"Frees":0},{"Size":896,"Mallocs":6,"Frees":0},{"Size":1024,"Mallocs":8,"Frees":0},{"Size":1152,"Mallocs":10,"Frees":0},{"Size":1280,"Mallocs":3,"Frees":0},{"Size":1408,"Mallocs":1,"Frees":0},{"Size":1536,"Mallocs":0,"Frees":0},{"Size":1792,"Mallocs":7,"Frees":0},{"Size":2048,"Mallocs":2,"Frees":0},{"Size":2304,"Mallocs":3,"Frees":0},{"Size":2688,"Mallocs":2,"Frees":0},{"Size":3072,"Mallocs":0,"Frees":0},{"Size":3200,"Mallocs":0,"Frees":0},{"Size":3456,"Mallocs":0,"Frees":0},{"Size":4096,"Mallocs":8,"Frees":0},{"Size":4864,"Mallocs":1,"Frees":0},{"Size":5376,"Mallocs":1,"Frees":0},{"Size":6144,"Mallocs":2,"Frees":0},{"Size":6528,"Mallocs":0,"Frees":0},{"Size":6784,"Mallocs":0,"Frees":0},{"Size":6912,"Mallocs":0,"Frees":0},{"Size":8192,"Mallocs":2,"Frees":0},{"Size":9472,"Mallocs":8,"Frees":0},{"Size":9728,"Mallocs":0,"Frees":0},{"Size":10240,"Mallocs":0,"Frees":0},{"Size":10880,"Mallocs":0,"Frees":0},{"Size":12288,"Mallocs":0,"Frees":0},{"Size":13568,"Mallocs":0,"Frees":0},{"Size":14336,"Mallocs":0,"Frees":0},{"Size":16384,"Mallocs":0,"Frees":0},{"Size":18432,"Mallocs":0,"Frees":0}]} }
可以看到,expvar 默认已提供了两项指标,分别是程序执行命令(os.Args)和运行时内存分配(runtime.Memstats)信息。
expvar 中最重要的是 Publish 函数和 Var 接口。
func Publish(name string, v Var) {}
Publish 函数签名中需要两个参数,name 是我们指定的指标名。例如在上文 expvar 的 init 函数下 <span style="font-size: 15px;">Publish("cmdline", Func(cmdline))</span>
代码行,其中<span style="font-size: 15px;">cmdline</span>
就是指标名,而<span style="font-size: 15px;">Func(cmdline)</span>
import "expvar"), la fonction init suivante sera appelée automatiquement.
// Var is an abstract type for all exported variables. type Var interface { // String returns a valid JSON value for the variable. // Types with String methods that do not return valid JSON // (such as time.Time) must not be used as a Var. String() string }
type Int struct { i int64 } type Float struct { f uint64 } type Map struct { m sync.Map // map[string]Var keysMu sync.RWMutex keys []string // sorted } type String struct { s atomic.Value // string } type Func func() any
intVar = expvar.NewInt(“metricName”) floatVar = expvar.NewFloat(“metricName”) mapVar = expvar.NewMap(“metricName”) stringVar = expvar.NewString(“metricName”)
func NewInt(name string) *Int { v := new(Int) Publish(name, v) return v }
type MyStruct struct { Field1 string Field2 int Field3 float64 }
🎜Publish("cmdline", Func(cmdline))🎜
🎜ligne de code, où🎜🎜cmdline🎜
🎜 est le nom de l'indicateur, et 🎜🎜Func(cmdline)🎜
🎜 est expvar.Func qui implémente le Variable de type d'interface Var. 🎜🎜🎜🎜Interface Var, qui définit uniquement une méthode String. Il convient de noter que cette méthode doit renvoyer une chaîne Json valide. 🎜🎜// Var is an abstract type for all exported variables. type Var interface { // String returns a valid JSON value for the variable. // Types with String methods that do not return valid JSON // (such as time.Time) must not be used as a Var. String() string }
为了方便使用,expvar 库中提供了五种导出变量类型,它们均实现了 Var 接口。
type Int struct { i int64 } type Float struct { f uint64 } type Map struct { m sync.Map // map[string]Var keysMu sync.RWMutex keys []string // sorted } type String struct { s atomic.Value // string } type Func func() any
我们分别通过调用 expvar.NewXXX 函数即可完成前四种类型的变量创建与指标注册。
intVar = expvar.NewInt(“metricName”) floatVar = expvar.NewFloat(“metricName”) mapVar = expvar.NewMap(“metricName”) stringVar = expvar.NewString(“metricName”)
例如 expvar.NewInt 函数,它会内部调用 Publish 方法完成指标名与 expvar.Int 类型变量的绑定。
func NewInt(name string) *Int { v := new(Int) Publish(name, v) return v }
而 expvar.Func 类型,其实是为了让我们可以自定义导出类型。
例如,假如我们想要暴露以下定义的结构体
type MyStruct struct { Field1 string Field2 int Field3 float64 }
首先需要创建一个数据生成函数。它用于在每次调用 HTTP 服务路径时,通过该函数导出这里面的数据。
func MyStructData() interface{} { return MyStruct{ Field1: "Gopher", Field2: 22, Field3: 19.99, } }
最后,通过 Publish 函数注册指标名即可。
expvar.Publish("metricName", expvar.Func(MyStructData))
下面,我们给出一个覆盖五种导出变量类型的完整示例。
package main import ( "expvar" "github.com/shirou/gopsutil/v3/host" "github.com/shirou/gopsutil/v3/load" "github.com/shirou/gopsutil/v3/mem" "net/http" "time" ) type Load struct { Load1 float64 Load5 float64 Load15 float64 } func AllLoadAvg() interface{} { return Load{ Load1: LoadAvg(1), Load5: LoadAvg(5), Load15: LoadAvg(15), } } func LoadAvg(loadNumber int) float64 { avg, _ := load.Avg() switch loadNumber { case 5: return avg.Load5 case 15: return avg.Load15 default: return avg.Load1 } } func main() { var ( aliveOfSeconds = expvar.NewInt("aliveOfSeconds") hostID = expvar.NewString("hostID") lastLoad = expvar.NewFloat("lastLoad") virtualMemory = expvar.NewMap("virtualMemory") ) expvar.Publish("allLoadAvg", expvar.Func(AllLoadAvg)) h, _ := host.HostID() hostID.Set(h) go http.ListenAndServe(":8080", nil) for { aliveOfSeconds.Add(1) vm, _ := mem.VirtualMemory() lastLoad.Set(LoadAvg(1)) virtualMemory.Add("active", int64(vm.Active)) virtualMemory.Add("buffer", int64(vm.Buffers)) time.Sleep(1 * time.Second) } }
在上述示例中,我们通过 gopsutil 库(介绍可见还在自己写 Go 系统监控函数吗一文)获取了一些系统信息,并展示了如何通过 expvar 中的各种变量类型将这些信息进行导出。
curl 访问 localhost:8080/debug/vars 结果如下
$ curl localhost:8080/debug/vars { "aliveOfSeconds": 1, "allLoadAvg": {"Load1":1.69580078125,"Load5":1.97412109375,"Load15":1.90283203125}, "cmdline": ["/var/folders/xk/gn46n46d503dsztbc6_9qb2h0000gn/T/go-build3566019824/b001/exe/main"], "hostID": "7a1a74f2-30fc-5bc1-b439-6b7aef22e58d", "lastLoad": 1.69580078125, "memstats": {"Alloc":256208,"TotalAlloc":256208,"Sys":8735760,"Lookups":0,"Mallocs":1089,"Frees":48,"HeapAlloc":256208,"HeapSys":3866624,"HeapIdle":2891776,"HeapInuse":974848,"HeapReleased":2859008,"HeapObjects":1041,"StackInuse":327680,"StackSys":327680,"MSpanInuse":19992,"MSpanSys":32640,"MCacheInuse":9600,"MCacheSys":15600,"BuckHashSys":3905,"GCSys":3851120,"OtherSys":638191,"NextGC":4194304,"LastGC":0,"PauseTotalNs":0,"PauseNs":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"PauseEnd":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"NumGC":0,"NumForcedGC":0,"GCCPUFraction":0,"EnableGC":true,"DebugGC":false,"BySize":[{"Size":0,"Mallocs":0,"Frees":0},{"Size":8,"Mallocs":35,"Frees":0},{"Size":16,"Mallocs":415,"Frees":0},{"Size":24,"Mallocs":71,"Frees":0},{"Size":32,"Mallocs":37,"Frees":0},{"Size":48,"Mallocs":141,"Frees":0},{"Size":64,"Mallocs":52,"Frees":0},{"Size":80,"Mallocs":20,"Frees":0},{"Size":96,"Mallocs":23,"Frees":0},{"Size":112,"Mallocs":14,"Frees":0},{"Size":128,"Mallocs":7,"Frees":0},{"Size":144,"Mallocs":7,"Frees":0},{"Size":160,"Mallocs":18,"Frees":0},{"Size":176,"Mallocs":6,"Frees":0},{"Size":192,"Mallocs":1,"Frees":0},{"Size":208,"Mallocs":42,"Frees":0},{"Size":224,"Mallocs":3,"Frees":0},{"Size":240,"Mallocs":0,"Frees":0},{"Size":256,"Mallocs":9,"Frees":0},{"Size":288,"Mallocs":8,"Frees":0},{"Size":320,"Mallocs":5,"Frees":0},{"Size":352,"Mallocs":13,"Frees":0},{"Size":384,"Mallocs":3,"Frees":0},{"Size":416,"Mallocs":33,"Frees":0},{"Size":448,"Mallocs":0,"Frees":0},{"Size":480,"Mallocs":2,"Frees":0},{"Size":512,"Mallocs":1,"Frees":0},{"Size":576,"Mallocs":4,"Frees":0},{"Size":640,"Mallocs":8,"Frees":0},{"Size":704,"Mallocs":3,"Frees":0},{"Size":768,"Mallocs":1,"Frees":0},{"Size":896,"Mallocs":6,"Frees":0},{"Size":1024,"Mallocs":8,"Frees":0},{"Size":1152,"Mallocs":9,"Frees":0},{"Size":1280,"Mallocs":3,"Frees":0},{"Size":1408,"Mallocs":1,"Frees":0},{"Size":1536,"Mallocs":1,"Frees":0},{"Size":1792,"Mallocs":9,"Frees":0},{"Size":2048,"Mallocs":1,"Frees":0},{"Size":2304,"Mallocs":2,"Frees":0},{"Size":2688,"Mallocs":2,"Frees":0},{"Size":3072,"Mallocs":0,"Frees":0},{"Size":3200,"Mallocs":1,"Frees":0},{"Size":3456,"Mallocs":0,"Frees":0},{"Size":4096,"Mallocs":5,"Frees":0},{"Size":4864,"Mallocs":0,"Frees":0},{"Size":5376,"Mallocs":1,"Frees":0},{"Size":6144,"Mallocs":1,"Frees":0},{"Size":6528,"Mallocs":0,"Frees":0},{"Size":6784,"Mallocs":0,"Frees":0},{"Size":6912,"Mallocs":0,"Frees":0},{"Size":8192,"Mallocs":1,"Frees":0},{"Size":9472,"Mallocs":8,"Frees":0},{"Size":9728,"Mallocs":0,"Frees":0},{"Size":10240,"Mallocs":0,"Frees":0},{"Size":10880,"Mallocs":0,"Frees":0},{"Size":12288,"Mallocs":0,"Frees":0},{"Size":13568,"Mallocs":0,"Frees":0},{"Size":14336,"Mallocs":0,"Frees":0},{"Size":16384,"Mallocs":0,"Frees":0},{"Size":18432,"Mallocs":0,"Frees":0}]}, "virtualMemory": {"active": 1957449728, "buffer": 0} }
标准库 expvar 为需要导出的公共变量提供了一个标准化的接口,使用比较简单。
expvar 包内部定义的几种基础类型都相应给出了并发安全的操作方法,我们不需要去重复实现一遍,能够开箱即用。
Cependant, selon les statistiques des projets publics sur https://go.dev/, le nombre d'importations de cette bibliothèque est inférieur à 10 000.
Par rapport au nombre d'importations dans d'autres bibliothèques standards, la présence d'expvar est trop faible.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!