Path: blob/main/components/registry-facade/pkg/registry/metrics.go
2499 views
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package registry56import (7"net/http"8"strings"9"time"1011"github.com/prometheus/client_golang/prometheus"12)1314// NewMeasuringRegistryRoundTripper produces a round tripper that exposes registry access metrics15func NewMeasuringRegistryRoundTripper(delegate http.RoundTripper, reg prometheus.Registerer) (http.RoundTripper, error) {16metrics, err := newMetrics(reg, false)17if err != nil {18return nil, err19}20return &measuringRegistryRoundTripper{21delegate: delegate,22metrics: metrics,23}, nil24}2526type measuringRegistryRoundTripper struct {27delegate http.RoundTripper28metrics *metrics29}3031func (m *measuringRegistryRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {32t0 := time.Now()33resp, err := m.delegate.RoundTrip(req)34dt := time.Since(t0)3536if strings.Contains(req.URL.Path, "/manifests/") {37m.metrics.ManifestHist.Observe(dt.Seconds())38if err != nil {39m.metrics.ReqFailedCounter.WithLabelValues("manifest").Inc()40}41} else if strings.Contains(req.URL.Path, "/blobs/") {42m.metrics.BlobCounter.Inc()43if err != nil {44m.metrics.ReqFailedCounter.WithLabelValues("blob").Inc()45}46}4748return resp, err49}5051// Metrics combine custom metrics exported by registry facade52type metrics struct {53ManifestHist prometheus.Histogram54ReqFailedCounter *prometheus.CounterVec55BlobCounter prometheus.Counter56BlobDownloadSizeCounter *prometheus.CounterVec57BlobDownloadCounter *prometheus.CounterVec58BlobDownloadSpeedHist *prometheus.HistogramVec59}6061func newMetrics(reg prometheus.Registerer, upstream bool) (*metrics, error) {62manifestHist := prometheus.NewHistogram(prometheus.HistogramOpts{63Name: "manifest_req_seconds",64Help: "time of manifest requests made to the downstream registry",65Buckets: []float64{0.1, 0.5, 1, 2, 5, 10, 60, 300, 600, 1800},66})67err := reg.Register(manifestHist)68if err != nil {69return nil, err70}7172reqFailedCounter := prometheus.NewCounterVec(73prometheus.CounterOpts{74Name: "req_failed_total",75Help: "number of requests that failed",76}, []string{"type"},77)78err = reg.Register(reqFailedCounter)79if err != nil {80return nil, err81}8283blobCounter := prometheus.NewCounter(prometheus.CounterOpts{84Name: "blob_req_total",85Help: "number of blob requests made to the downstream registry",86})87err = reg.Register(blobCounter)88if err != nil {89return nil, err90}9192blobDownloadCounter := prometheus.NewCounterVec(prometheus.CounterOpts{93Name: "blob_req_dl_total",94Help: "number of blob download requests",95}, []string{"blobSource", "ok"})96err = reg.Register(blobDownloadCounter)97if err != nil {98return nil, err99}100101blobDownloadSizeCounter := prometheus.NewCounterVec(prometheus.CounterOpts{102Name: "blob_req_bytes_total",103Help: "amount of blob bytes downloaded",104}, []string{"blobSource"})105err = reg.Register(blobDownloadSizeCounter)106if err != nil {107return nil, err108}109110blobDownloadSpeedHist := prometheus.NewHistogramVec(prometheus.HistogramOpts{111Name: "blob_req_bytes_second",112Help: "blob download speed in bytes per second",113Buckets: prometheus.ExponentialBuckets(1024*1024, 2, 15),114}, []string{"blobSource"})115if upstream {116err = reg.Register(blobDownloadSpeedHist)117if err != nil {118return nil, err119}120}121122return &metrics{123ManifestHist: manifestHist,124ReqFailedCounter: reqFailedCounter,125BlobCounter: blobCounter,126BlobDownloadSpeedHist: blobDownloadSpeedHist,127BlobDownloadSizeCounter: blobDownloadSizeCounter,128BlobDownloadCounter: blobDownloadCounter,129}, nil130}131132133