点击上方 云原生CTO,选择 设为星标

               优质文章,每日送达


「【只做懂你de云原生干货知识共享】」

使用 Prometheus 和 Grafana 监控你的 Golang 服务

我最近对如何通过监控从应用程序中获取洞察力非常感兴趣。我开始搜索监控工具后,很快就找到了Prometheus和Grafana,前者将从您的应用程序收集指标,后者将显示收集的指标。

「https://prometheus.io/」「https://grafana.com/」

如何重现本教程并运行代码

为了便于重现本教程,我们将使用Docker、Docker-Compose和VS Code 远程容器。我不会详细介绍如何安装这些工具,但只需按照文档操作即可。

「https://docs.docker.com/get-docker/」「https://docs.docker.com/compose/install/」「https://code.visualstudio.com/docs/remote/containers」

您可以在此处找到完整的源代码。

「https://github.com/alcbotta/go-prometheus-grafana」

OPEN上VSCode的源代码,然后点击container重新打开。初始化完成后,您应该在 go-prometheus-grafana 服务名称下运行三个容器。您现在可以通过 VSCode 的 GUI 或在终端上运行以下命令来启动应用程序:

go run main.go

user_status 自定义指标和正在生成的数据

启动应用程序(特别是main.go文件)后,它将创建一个名为「http_request_get_user_status_count」的自定义计数器指标,并将其注册到 prometheus 客户端。服务器和生产者都将被初始化。生产者将向服务器发送包含随机用户名的消息。然后服务器为该请求生成一个随机状态,然后将响应添加到 prometheus 计数器。我们在路径“ metrics ”下为 Prometheus 注册了一个额外的端点。代码如下:

package main

import (
 "bytes"
 "encoding/json"
 "log"
 "math/rand"
 "net/http"
 "time"

 "github.com/prometheus/client_golang/prometheus"
 "github.com/prometheus/client_golang/prometheus/promhttp"
)

// we create a new custom metric of type counter
var userStatus = prometheus.NewCounterVec(
 prometheus.CounterOpts{
  Name: "http_request_get_user_status_count", // metric name
  Help: "Count of status returned by user.",
 },
 []string{"user", "status"}, // labels
)

func init() {
 // we need to register the counter so prometheus can collect this metric
 prometheus.MustRegister(userStatus)
}

type MyRequest struct {
 User string
}

// the server will retrieve the user from the body, and randomly generate a status to return
func server(w http.ResponseWriter, r *http.Request) {
 var status string
 var user string
 defer func() {
  userStatus.WithLabelValues(user, status).Inc()
 }()
 var mr MyRequest
 json.NewDecoder(r.Body).Decode(&mr)

 if rand.Float32() > 0.8 {
  status = "4xx"
 } else {
  status = "2xx"
 }

 user = mr.User
 log.Println(user, status)
 w.Write([]byte(status))
}

// the producer will randomly select a user from a pool of users and send it to the server
func producer() {
 userPool := []string{"bob", "alice", "jack"}
 for {
  postBody, _ := json.Marshal(MyRequest{
   User: userPool[rand.Intn(len(userPool))],
  })
  requestBody := bytes.NewBuffer(postBody)
  http.Post("http://localhost:8080", "application/json", requestBody)
  time.Sleep(time.Second * 2)
 }
}

func main() {
 // the producer runs on its own goroutine
 go producer()

 http.Handle("/metrics", promhttp.Handler())
 http.HandleFunc("/", server)

 http.ListenAndServe(":8080", nil)
}

Prometheus

在初始化期间,prometheus 服务被配置为每5 秒在“ metrics ”路径上以服务器名称为目标抓取数据(因为所有服务都在同一个网络下运行,每个服务都可以通过使用另一个服务的名称):

global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    metrics_path: '/metrics'
    static_configs:
      - targets: ['server:8080']

Prometheus 应该在http://localhost:9090 上运行。在搜索表达式中,如果您键入「http_request_get_user_status_count」,您应该会看到到目前为止生成的数据。就像是:

Grafana

现在,为了在 Prometheus 中可视化数据,我们将使用 Grafana。Grafana 应该在http://localhost:3000 上运行。默认凭据为:admin/admin。

我们需要做的第一件事就是添加prometheus作为数据源。要做到这一点,在左侧面板上,点击齿轮图标,然后在DATA来源,最后添加数据源。选择 Prometheus 并在 URL 上输入:prometheus:9090,如下图所示:

向下滚动,然后单击“保存并测试”,您应该会看到一条消息:“数据源正在工作”。

现在,在左侧面板上,单击“+”图标,然后单击导入。在新页面上,复制并粘贴以下 json(或从源代码上传文件grafana/panel.json),然后单击加载。

{
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": "-- Grafana --",
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",
        "type": "dashboard"
      }
    ]
  },
  "editable": true,
  "gnetId": null,
  "graphTooltip": 0,
  "id": 1,
  "links": [],
  "panels": [
    {
      "datasource": null,
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "thresholds"
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          }
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 0
      },
      "id": 6,
      "options": {
        "displayMode": "gradient",
        "orientation": "horizontal",
        "reduceOptions": {
          "calcs": [
            "lastNotNull"
          ],
          "fields": "",
          "values": false
        },
        "showUnfilled": true,
        "text": {}
      },
      "pluginVersion": "8.0.6",
      "targets": [
        {
          "exemplar": true,
          "expr": "http_request_get_user_status_count",
          "interval": "",
          "legendFormat": "{{status}}  {{user}}",
          "refId": "A"
        }
      ],
      "timeFrom": null,
      "timeShift": null,
      "title": "Panel Title",
      "type": "bargauge"
    }
  ],
  "refresh": "",
  "schemaVersion": 30,
  "style": "dark",
  "tags": [],
  "templating": {
    "list": []
  },
  "time": {
    "from": "now-6h",
    "to": "now"
  },
  "timepicker": {},
  "timezone": "",
  "title": "user_status",
  "uid": "g5kaN3W7k",
  "version": 2
}

您应该会在屏幕上看到类似于以下内容的内容:

应该是全部。当然,这是一个极其简单的例子,我用来理解所有部分如何相互连接。同样,您可以在此处找到完整代码:

「https://github.com/alcbotta/go-prometheus-grafana」

参考:

https://medium.com/@alcbotta/monitoring-you-golang-server-with-prometheus-and-grafana-97e64bb1d0e9