github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/boskos/metrics/metrics.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"net/http"
    23  	"time"
    24  
    25  	"github.com/prometheus/client_golang/prometheus"
    26  	"github.com/prometheus/client_golang/prometheus/promhttp"
    27  	"github.com/sirupsen/logrus"
    28  	"k8s.io/test-infra/boskos/client"
    29  )
    30  
    31  type prometheusMetrics struct {
    32  	GceStats map[string]prometheus.Gauge
    33  	GkeStats map[string]prometheus.Gauge
    34  }
    35  
    36  var (
    37  	promMetrics = prometheusMetrics{
    38  		GceStats: map[string]prometheus.Gauge{
    39  			"free": prometheus.NewGauge(prometheus.GaugeOpts{
    40  				Name: "boskos_gce_project_free",
    41  				Help: "Number of free gce-project",
    42  			}),
    43  			"busy": prometheus.NewGauge(prometheus.GaugeOpts{
    44  				Name: "boskos_gce_project_busy",
    45  				Help: "Number of busy gce-project",
    46  			}),
    47  			"dirty": prometheus.NewGauge(prometheus.GaugeOpts{
    48  				Name: "boskos_gce_project_dirty",
    49  				Help: "Number of dirty gce-project",
    50  			}),
    51  			"cleaning": prometheus.NewGauge(prometheus.GaugeOpts{
    52  				Name: "boskos_gce_project_cleaning",
    53  				Help: "Number of cleaning gce-project",
    54  			}),
    55  		},
    56  		GkeStats: map[string]prometheus.Gauge{
    57  			"free": prometheus.NewGauge(prometheus.GaugeOpts{
    58  				Name: "boskos_gke_project_free",
    59  				Help: "Number of free gke-project",
    60  			}),
    61  			"busy": prometheus.NewGauge(prometheus.GaugeOpts{
    62  				Name: "boskos_gke_project_busy",
    63  				Help: "Number of busy gke-project",
    64  			}),
    65  			"dirty": prometheus.NewGauge(prometheus.GaugeOpts{
    66  				Name: "boskos_gke_project_dirty",
    67  				Help: "Number of dirty gke-project",
    68  			}),
    69  			"cleaning": prometheus.NewGauge(prometheus.GaugeOpts{
    70  				Name: "boskos_gke_project_cleaning",
    71  				Help: "Number of cleaning gke-project",
    72  			}),
    73  		},
    74  	}
    75  )
    76  
    77  func init() {
    78  	for _, gce := range promMetrics.GceStats {
    79  		prometheus.MustRegister(gce)
    80  	}
    81  
    82  	for _, gke := range promMetrics.GkeStats {
    83  		prometheus.MustRegister(gke)
    84  	}
    85  }
    86  
    87  func main() {
    88  	logrus.SetFormatter(&logrus.JSONFormatter{})
    89  	boskos := client.NewClient("Metrics", "http://boskos")
    90  	logrus.Infof("Initialzied boskos client!")
    91  
    92  	http.Handle("/prometheus", promhttp.Handler())
    93  	http.Handle("/", handleMetric(boskos))
    94  
    95  	go func() {
    96  		logTick := time.NewTicker(time.Minute).C
    97  		for {
    98  			select {
    99  			case <-logTick:
   100  				if err := update(boskos); err != nil {
   101  					logrus.WithError(err).Warning("[Boskos Metrics]Update failed!")
   102  				}
   103  			}
   104  		}
   105  	}()
   106  
   107  	logrus.Info("Start Service")
   108  	logrus.WithError(http.ListenAndServe(":8080", nil)).Fatal("ListenAndServe returned.")
   109  }
   110  
   111  func update(boskos *client.Client) error {
   112  	gce, err := boskos.Metric("gce-project")
   113  	if err != nil {
   114  		return fmt.Errorf("fail to get metric for gce-project : %v", err)
   115  	}
   116  
   117  	promMetrics.GceStats["free"].Set(float64(gce.Current["free"]))
   118  	promMetrics.GceStats["busy"].Set(float64(gce.Current["busy"]))
   119  	promMetrics.GceStats["dirty"].Set(float64(gce.Current["dirty"]))
   120  	promMetrics.GceStats["cleaning"].Set(float64(gce.Current["cleaning"]))
   121  
   122  	gke, err := boskos.Metric("gke-project")
   123  	if err != nil {
   124  		return fmt.Errorf("fail to get metric for gke-project : %v", err)
   125  	}
   126  
   127  	promMetrics.GkeStats["free"].Set(float64(gke.Current["free"]))
   128  	promMetrics.GkeStats["busy"].Set(float64(gke.Current["busy"]))
   129  	promMetrics.GkeStats["dirty"].Set(float64(gke.Current["dirty"]))
   130  	promMetrics.GkeStats["cleaning"].Set(float64(gke.Current["cleaning"]))
   131  
   132  	return nil
   133  }
   134  
   135  //  handleMetric: Handler for /
   136  //  Method: GET
   137  func handleMetric(boskos *client.Client) http.HandlerFunc {
   138  	return func(res http.ResponseWriter, req *http.Request) {
   139  		log := logrus.WithField("handler", "handleMetric")
   140  		log.Infof("From %v", req.RemoteAddr)
   141  
   142  		if req.Method != "GET" {
   143  			log.Warning("[BadRequest]method %v, expect GET", req.Method)
   144  			http.Error(res, "only accepts GET request", http.StatusMethodNotAllowed)
   145  			return
   146  		}
   147  
   148  		rtype := req.URL.Query().Get("type")
   149  		if rtype == "" {
   150  			msg := "type must be set in the request."
   151  			log.Warning(msg)
   152  			http.Error(res, msg, http.StatusBadRequest)
   153  			return
   154  		}
   155  
   156  		log.Infof("Request for metric %v", rtype)
   157  
   158  		metric, err := boskos.Metric(rtype)
   159  		if err != nil {
   160  			log.WithError(err).Errorf("Fail to get metic for %v", rtype)
   161  			http.Error(res, err.Error(), http.StatusNotFound)
   162  			return
   163  		}
   164  
   165  		metricJSON, err := json.Marshal(metric)
   166  		if err != nil {
   167  			log.WithError(err).Errorf("json.Marshal failed: %v", metricJSON)
   168  			http.Error(res, err.Error(), http.StatusInternalServerError)
   169  			return
   170  		}
   171  		log.Infof("Metric query for %v: %v", rtype, string(metricJSON))
   172  		fmt.Fprint(res, string(metricJSON))
   173  	}
   174  }