| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- package prometheus
- import (
- "context"
- "encoding/json"
- "fmt"
- "strings"
- v1 "k8s.io/api/core/v1"
- "k8s.io/client-go/kubernetes"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- )
- // returns the prometheus service name
- func GetPrometheusService(clientset kubernetes.Interface) (*v1.Service, bool, error) {
- services, err := clientset.CoreV1().Services("").List(context.TODO(), metav1.ListOptions{
- LabelSelector: "app=prometheus,component=server,heritage=Helm",
- })
- if err != nil {
- return nil, false, err
- }
- if len(services.Items) == 0 {
- return nil, false, nil
- }
- return &services.Items[0], true, nil
- }
- type QueryOpts struct {
- Metric string `schema:"metric"`
- ShouldSum bool `schema:"shouldsum"`
- PodList []string `schema:"pods"`
- Namespace string `schema:"namespace"`
- StartRange uint `schema:"startrange"`
- EndRange uint `schema:"endrange"`
- Resolution string `schema:"resolution"`
- }
- func QueryPrometheus(
- clientset kubernetes.Interface,
- service *v1.Service,
- opts *QueryOpts,
- ) ([]byte, error) {
- if len(service.Spec.Ports) == 0 {
- return nil, fmt.Errorf("prometheus service has no exposed ports to query")
- }
- podSelector := fmt.Sprintf(`namespace="%s",pod=~"%s",container!="POD",container!=""`, opts.Namespace, strings.Join(opts.PodList, "|"))
- query := ""
- if opts.Metric == "cpu" {
- query = fmt.Sprintf("rate(container_cpu_usage_seconds_total{%s}[5m])", podSelector)
- } else if opts.Metric == "memory" {
- query = fmt.Sprintf("container_memory_usage_bytes{%s}", podSelector)
- } else if opts.Metric == "network" {
- netPodSelector := fmt.Sprintf(`namespace="%s",pod=~"%s",container="POD"`, opts.Namespace, strings.Join(opts.PodList, "|"))
- query = fmt.Sprintf("rate(container_network_receive_bytes_total{%s}[5m])", netPodSelector)
- }
- if opts.ShouldSum {
- query = fmt.Sprintf("sum(%s)", query)
- }
- queryParams := map[string]string{
- "query": query,
- "start": fmt.Sprintf("%d", opts.StartRange),
- "end": fmt.Sprintf("%d", opts.EndRange),
- "step": opts.Resolution,
- }
- resp := clientset.CoreV1().Services(service.Namespace).ProxyGet(
- "http",
- service.Name,
- fmt.Sprintf("%d", service.Spec.Ports[0].Port),
- "/api/v1/query_range",
- queryParams,
- )
- rawQuery, err := resp.DoRaw(context.TODO())
- if err != nil {
- return nil, err
- }
- return parseQuery(rawQuery, opts.Metric)
- }
- type promRawQuery struct {
- Data struct {
- Result []struct {
- Metric struct {
- Pod string `json:"pod,omitempty"`
- } `json:"metric,omitempty"`
- Values [][]interface{} `json:"values"`
- } `json:"result"`
- } `json:"data"`
- }
- type promParsedSingletonQueryResult struct {
- Date interface{} `json:"date,omitempty"`
- CPU interface{} `json:"cpu,omitempty"`
- Memory interface{} `json:"memory,omitempty"`
- Bytes interface{} `json:"bytes,omitempty"`
- }
- type promParsedSingletonQuery struct {
- Pod string `json:"pod,omitempty"`
- Results []promParsedSingletonQueryResult `json:"results"`
- }
- func parseQuery(rawQuery []byte, metric string) ([]byte, error) {
- rawQueryObj := &promRawQuery{}
- json.Unmarshal(rawQuery, rawQueryObj)
- res := make([]*promParsedSingletonQuery, 0)
- for _, result := range rawQueryObj.Data.Result {
- singleton := &promParsedSingletonQuery{
- Pod: result.Metric.Pod,
- }
- singletonResults := make([]promParsedSingletonQueryResult, 0)
- for _, values := range result.Values {
- singletonResult := &promParsedSingletonQueryResult{
- Date: values[0],
- }
- if metric == "cpu" {
- singletonResult.CPU = values[1]
- } else if metric == "memory" {
- singletonResult.Memory = values[1]
- } else if metric == "network" {
- singletonResult.Bytes = values[1]
- }
- singletonResults = append(singletonResults, *singletonResult)
- }
- singleton.Results = singletonResults
- res = append(res, singleton)
- }
- return json.Marshal(res)
- }
|