zotregistry.io/zot@v1.4.4-0.20231124084042-02a8ed785457/pkg/extensions/monitoring/extension.go (about)

     1  //go:build metrics
     2  // +build metrics
     3  
     4  package monitoring
     5  
     6  import (
     7  	"path"
     8  	"time"
     9  
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/prometheus/client_golang/prometheus/promauto"
    12  
    13  	"zotregistry.io/zot/errors"
    14  	"zotregistry.io/zot/pkg/log"
    15  )
    16  
    17  const metricsNamespace = "zot"
    18  
    19  var (
    20  	httpConnRequests = promauto.NewCounterVec( //nolint: gochecknoglobals
    21  		prometheus.CounterOpts{
    22  			Namespace: metricsNamespace,
    23  			Name:      "http_requests_total",
    24  			Help:      "Total number of http request in zot",
    25  		},
    26  		[]string{"method", "code"},
    27  	)
    28  	httpRepoLatency = promauto.NewSummaryVec( //nolint: gochecknoglobals
    29  		prometheus.SummaryOpts{
    30  			Namespace: metricsNamespace,
    31  			Name:      "http_repo_latency_seconds",
    32  			Help:      "Latency of serving HTTP requests",
    33  		},
    34  		[]string{"repo"},
    35  	)
    36  	httpMethodLatency = promauto.NewHistogramVec( //nolint: gochecknoglobals
    37  		prometheus.HistogramOpts{
    38  			Namespace: metricsNamespace,
    39  			Name:      "http_method_latency_seconds",
    40  			Help:      "Latency of serving HTTP requests",
    41  			Buckets:   GetDefaultBuckets(),
    42  		},
    43  		[]string{"method"},
    44  	)
    45  	repoStorageBytes = promauto.NewGaugeVec( //nolint: gochecknoglobals
    46  		prometheus.GaugeOpts{
    47  			Namespace: metricsNamespace,
    48  			Name:      "repo_storage_bytes",
    49  			Help:      "Storage used per zot repo",
    50  		},
    51  		[]string{"repo"},
    52  	)
    53  	uploadCounter = promauto.NewCounterVec( //nolint: gochecknoglobals
    54  		prometheus.CounterOpts{
    55  			Namespace: metricsNamespace,
    56  			Name:      "repo_uploads_total",
    57  			Help:      "Total number times an image was uploaded",
    58  		},
    59  		[]string{"repo"},
    60  	)
    61  	downloadCounter = promauto.NewCounterVec( //nolint: gochecknoglobals
    62  		prometheus.CounterOpts{
    63  			Namespace: metricsNamespace,
    64  			Name:      "repo_downloads_total",
    65  			Help:      "Total number times an image was downloaded",
    66  		},
    67  		[]string{"repo"},
    68  	)
    69  	serverInfo = promauto.NewGaugeVec( //nolint: gochecknoglobals
    70  		prometheus.GaugeOpts{
    71  			Namespace: metricsNamespace,
    72  			Name:      "info",
    73  			Help:      "Server general information",
    74  		},
    75  		[]string{"commit", "binaryType", "goVersion", "version"},
    76  	)
    77  	storageLockLatency = promauto.NewHistogramVec( //nolint: gochecknoglobals
    78  		prometheus.HistogramOpts{
    79  			Namespace: metricsNamespace,
    80  			Name:      "storage_lock_latency_seconds",
    81  			Help:      "Latency of serving HTTP requests",
    82  			Buckets:   GetStorageLatencyBuckets(),
    83  		},
    84  		[]string{"storageName", "lockType"},
    85  	)
    86  )
    87  
    88  type metricServer struct {
    89  	enabled bool
    90  	log     log.Logger
    91  }
    92  
    93  func GetDefaultBuckets() []float64 {
    94  	return []float64{.05, .5, 1, 5, 30, 60, 600}
    95  }
    96  
    97  func GetStorageLatencyBuckets() []float64 {
    98  	return []float64{.001, .01, 0.1, 1, 5, 10, 15, 30, 60}
    99  }
   100  
   101  func NewMetricsServer(enabled bool, log log.Logger) MetricServer {
   102  	return &metricServer{
   103  		enabled: enabled,
   104  		log:     log,
   105  	}
   106  }
   107  
   108  // implementing the MetricServer interface.
   109  func (ms *metricServer) SendMetric(mfunc interface{}) {
   110  	if ms.enabled {
   111  		mfn, ok := mfunc.(func())
   112  		if !ok {
   113  			ms.log.Error().Err(errors.ErrInvalidMetric).Msg("type conversion")
   114  
   115  			return
   116  		}
   117  
   118  		mfn()
   119  	}
   120  }
   121  
   122  func (ms *metricServer) ForceSendMetric(mfunc interface{}) {
   123  	mfn, ok := mfunc.(func())
   124  	if !ok {
   125  		ms.log.Error().Err(errors.ErrInvalidMetric).Msg("type conversion")
   126  
   127  		return
   128  	}
   129  
   130  	mfn()
   131  }
   132  
   133  func (ms *metricServer) ReceiveMetrics() interface{} {
   134  	return nil
   135  }
   136  
   137  func (ms *metricServer) IsEnabled() bool {
   138  	return ms.enabled
   139  }
   140  
   141  func IncHTTPConnRequests(ms MetricServer, lvalues ...string) {
   142  	ms.SendMetric(func() {
   143  		httpConnRequests.WithLabelValues(lvalues...).Inc()
   144  	})
   145  }
   146  
   147  func ObserveHTTPRepoLatency(ms MetricServer, path string, latency time.Duration) {
   148  	ms.SendMetric(func() {
   149  		match := re.FindStringSubmatch(path)
   150  
   151  		if len(match) > 1 {
   152  			httpRepoLatency.WithLabelValues(match[1]).Observe(latency.Seconds())
   153  		} else {
   154  			httpRepoLatency.WithLabelValues("N/A").Observe(latency.Seconds())
   155  		}
   156  	})
   157  }
   158  
   159  func ObserveHTTPMethodLatency(ms MetricServer, method string, latency time.Duration) {
   160  	ms.SendMetric(func() {
   161  		httpMethodLatency.WithLabelValues(method).Observe(latency.Seconds())
   162  	})
   163  }
   164  
   165  func IncDownloadCounter(ms MetricServer, repo string) {
   166  	ms.SendMetric(func() {
   167  		downloadCounter.WithLabelValues(repo).Inc()
   168  	})
   169  }
   170  
   171  func SetStorageUsage(ms MetricServer, rootDir, repo string) {
   172  	ms.SendMetric(func() {
   173  		dir := path.Join(rootDir, repo)
   174  		repoSize, err := GetDirSize(dir)
   175  
   176  		if err == nil {
   177  			repoStorageBytes.WithLabelValues(repo).Set(float64(repoSize))
   178  		}
   179  	})
   180  }
   181  
   182  func IncUploadCounter(ms MetricServer, repo string) {
   183  	ms.SendMetric(func() {
   184  		uploadCounter.WithLabelValues(repo).Inc()
   185  	})
   186  }
   187  
   188  func SetServerInfo(ms MetricServer, lvalues ...string) {
   189  	ms.ForceSendMetric(func() {
   190  		serverInfo.WithLabelValues(lvalues...).Set(0)
   191  	})
   192  }
   193  
   194  func ObserveStorageLockLatency(ms MetricServer, latency time.Duration, storageName, lockType string) {
   195  	ms.SendMetric(func() {
   196  		storageLockLatency.WithLabelValues(storageName, lockType).Observe(latency.Seconds())
   197  	})
   198  }