描述
最近需要写一个告警的功能,本来是打算自己实现 metric 和 alert,但是由于我们本来就已经有 grafana 和 prometheus 了,就想要借助成熟体系来实现,这样可以节省很多工作,但是找了一些库,都没有合适的姿势入场,最近主管推给我一个软件 Cursor,来试一下。
使用
- 先来看下主界面
 
- command + k
 
- 来试一下
 
- 效果
 
- 很好,但是好像没有鉴权 [ command + a & command + k ]
 
- ok,文件太长就不截图了
package main
// Import necessary packages
import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"time"
	"github.com/prometheus/client_golang/api"
	v1 "github.com/prometheus/client_golang/api/prometheus/v1"
	"github.com/prometheus/common/model"
)
// BasicAuthRoundTripper is a RoundTripper that adds basic authentication credentials to requests
type BasicAuthRoundTripper struct {
	Username     string
	Password     string
	RoundTripper http.RoundTripper
}
func (rt *BasicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	req.SetBasicAuth(rt.Username, rt.Password)
	return rt.RoundTripper.RoundTrip(req)
}
// Define a struct to hold the query results
type QueryResult struct {
	Metric model.Metric      `json:"metric"`
	Value  model.SampleValue `json:"value"`
}
// Define a function to query Prometheus with a given username, password
func QueryPrometheus(username string, password string, query string) ([]QueryResult, error) {
	// Create a new HTTP client with the given username and password
	client, err := api.NewClient(api.Config{
		Address: "http://localhost:9090",
		RoundTripper: &BasicAuthRoundTripper{
			Username: username,
			Password: password,
			RoundTripper: &http.Transport{
				Proxy:           http.ProxyFromEnvironment,
				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
				// Set the username and password for basic authentication
				// Note: this is not secure and should not be used in production
				// Instead, use a secure authentication method such as OAuth2
				// or a reverse proxy with authentication
				DialContext: (&net.Dialer{
					Timeout:   30 * time.Second,
					KeepAlive: 30 * time.Second,
				}).DialContext,
				ForceAttemptHTTP2:     true,
				MaxIdleConns:          100,
				IdleConnTimeout:       90 * time.Second,
				TLSHandshakeTimeout:   10 * time.Second,
				ExpectContinueTimeout: 1 * time.Second,
				ProxyConnectHeader:    http.Header{},
			},
		},
	})
	if err != nil {
		return nil, err
	}
	// Create a new Prometheus API client
	prometheusClient := v1.NewAPI(client)
	// Query Prometheus with the built query string
	result, warnings, err := prometheusClient.Query(context.Background(), query, time.Now())
	if err != nil {
		return nil, err
	}
	if len(warnings) > 0 {
		fmt.Println("Warnings:", warnings)
	}
	// Parse the query result into a slice of QueryResult structs
	var queryResults []QueryResult
	for _, res := range result.(model.Vector) {
		queryResults = append(queryResults, QueryResult{
			Metric: res.Metric,
			Value:  res.Value,
		})
	}
	return queryResults, nil
}
- 感觉还是不够,如果能按照 label 查询就更好了。
 
- 结果如下
package main
// Import necessary packages
import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"time"
	"github.com/prometheus/client_golang/api"
	v1 "github.com/prometheus/client_golang/api/prometheus/v1"
	"github.com/prometheus/common/model"
)
// BasicAuthRoundTripper is a RoundTripper that adds basic authentication credentials to requests
type BasicAuthRoundTripper struct {
	Username     string
	Password     string
	RoundTripper http.RoundTripper
}
func (rt *BasicAuthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	req.SetBasicAuth(rt.Username, rt.Password)
	return rt.RoundTripper.RoundTrip(req)
}
// Define a struct to hold the query results
type QueryResult struct {
	Metric model.Metric      `json:"metric"`
	Value  model.SampleValue `json:"value"`
}
// Define a function to query Prometheus with a given username, password, and label
func QueryPrometheus(username string, password string, my_metric string, key string, value string) ([]QueryResult, error) {
	// Create a new HTTP client with the given username and password
	client, err := api.NewClient(api.Config{
		Address: "http://localhost:9090",
		RoundTripper: &BasicAuthRoundTripper{
			Username: username,
			Password: password,
			RoundTripper: &http.Transport{
				Proxy:           http.ProxyFromEnvironment,
				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
				// Set the username and password for basic authentication
				// Note: this is not secure and should not be used in production
				// Instead, use a secure authentication method such as OAuth2
				// or a reverse proxy with authentication
				DialContext: (&net.Dialer{
					Timeout:   30 * time.Second,
					KeepAlive: 30 * time.Second,
				}).DialContext,
				ForceAttemptHTTP2:     true,
				MaxIdleConns:          100,
				IdleConnTimeout:       90 * time.Second,
				TLSHandshakeTimeout:   10 * time.Second,
				ExpectContinueTimeout: 1 * time.Second,
				ProxyConnectHeader:    http.Header{},
			},
		},
	})
	if err != nil {
		return nil, err
	}
	// Create a new Prometheus API client
	prometheusClient := v1.NewAPI(client)
	// Build the query string with the given label
	query := fmt.Sprintf(`%s{%s="%s"}`, my_metric, key, value)
	// Query Prometheus with the built query string
	result, warnings, err := prometheusClient.Query(context.Background(), query, time.Now())
	if err != nil {
		return nil, err
	}
	if len(warnings) > 0 {
		fmt.Println("Warnings:", warnings)
	}
	// Parse the query result into a slice of QueryResult structs
	var queryResults []QueryResult
	for _, res := range result.(model.Vector) {
		queryResults = append(queryResults, QueryResult{
			Metric: res.Metric,
			Value:  res.Value,
		})
	}
	return queryResults, nil
}
很好,感觉自己要失业了。
文中有一些代码被我改过,因为最开始生成的代码已经找不到了。
总结
其实 AI 现在已经被训练的非常强大了,无论是 chatGPT 还是其衍生产物,俨然已经成为大势所趋,在未来越快接受并能融入生活进行使用的人,就越能走在时代的前沿,不过回归 Cursor 本身而言,并不是所有生成的代码都可以拿来使用,有一些包可能已经更新了,一些结构已经不存在了,这个时候只需要让他换一个包,或者换一种方式实现就可以了,工具本身灵活度不够,只要人足够灵活,那么使用起来自然就可以千人千面,另外,这个版本每天有使用次数限制,超出使用次数是要收费的,pro 要 $20 一个月,还是挺贵的。
