mirror of
https://github.com/project-zot/zot.git
synced 2024-12-23 22:27:35 -05:00
ada21ed842
Files were added to be built whether an extension is on or off. New build tags were added for each extension, while minimal and extended disappeared. added custom binary naming depending on extensions used and changed references from binary to binary-extended added automated blackbox tests for sync, search, scrub, metrics added contributor guidelines Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro>
181 lines
6 KiB
Go
181 lines
6 KiB
Go
//go:build !metrics
|
|
// +build !metrics
|
|
|
|
// nolint: varnamelen
|
|
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"net/http"
|
|
"regexp"
|
|
"strconv"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
|
"zotregistry.io/zot/pkg/log"
|
|
)
|
|
|
|
type Collector struct {
|
|
Client *monitoring.MetricsClient
|
|
MetricsDesc map[string]*prometheus.Desc // all known metrics descriptions
|
|
invalidChars *regexp.Regexp
|
|
}
|
|
|
|
// Implements prometheus.Collector interface.
|
|
func (zc Collector) Describe(ch chan<- *prometheus.Desc) {
|
|
for _, metricDescription := range zc.MetricsDesc {
|
|
ch <- metricDescription
|
|
}
|
|
}
|
|
|
|
// Implements prometheus.Collector interface.
|
|
func (zc Collector) Collect(ch chan<- prometheus.Metric) {
|
|
metrics, err := zc.Client.GetMetrics()
|
|
if err != nil {
|
|
fmt.Printf("error getting metrics: %v\n", err)
|
|
ch <- prometheus.MustNewConstMetric(zc.MetricsDesc["zot_up"], prometheus.GaugeValue, 0)
|
|
|
|
return
|
|
}
|
|
ch <- prometheus.MustNewConstMetric(zc.MetricsDesc["zot_up"], prometheus.GaugeValue, 1)
|
|
|
|
for _, g := range metrics.Gauges {
|
|
name := zc.invalidChars.ReplaceAllLiteralString(g.Name, "_")
|
|
ch <- prometheus.MustNewConstMetric(
|
|
zc.MetricsDesc[name], prometheus.GaugeValue, g.Value, g.LabelValues...)
|
|
}
|
|
|
|
for _, c := range metrics.Counters {
|
|
name := zc.invalidChars.ReplaceAllLiteralString(c.Name, "_")
|
|
name += "_total"
|
|
ch <- prometheus.MustNewConstMetric(
|
|
zc.MetricsDesc[name], prometheus.CounterValue, float64(c.Count), c.LabelValues...)
|
|
}
|
|
|
|
for _, summary := range metrics.Summaries {
|
|
mname := zc.invalidChars.ReplaceAllLiteralString(summary.Name, "_")
|
|
name := mname + "_count"
|
|
ch <- prometheus.MustNewConstMetric(
|
|
zc.MetricsDesc[name], prometheus.CounterValue, float64(summary.Count), summary.LabelValues...)
|
|
|
|
name = mname + "_sum"
|
|
ch <- prometheus.MustNewConstMetric(
|
|
zc.MetricsDesc[name], prometheus.CounterValue, summary.Sum, summary.LabelValues...)
|
|
}
|
|
|
|
for _, h := range metrics.Histograms {
|
|
mname := zc.invalidChars.ReplaceAllLiteralString(h.Name, "_")
|
|
name := mname + "_count"
|
|
ch <- prometheus.MustNewConstMetric(
|
|
zc.MetricsDesc[name], prometheus.CounterValue, float64(h.Count), h.LabelValues...)
|
|
|
|
name = mname + "_sum"
|
|
ch <- prometheus.MustNewConstMetric(
|
|
zc.MetricsDesc[name], prometheus.CounterValue, h.Sum, h.LabelValues...)
|
|
|
|
if h.Buckets != nil {
|
|
for _, fvalue := range monitoring.GetBuckets(h.Name) {
|
|
var svalue string
|
|
if fvalue == math.MaxFloat64 {
|
|
svalue = "+Inf"
|
|
} else {
|
|
svalue = strconv.FormatFloat(fvalue, 'f', -1, 64)
|
|
}
|
|
|
|
name = mname + "_bucket"
|
|
ch <- prometheus.MustNewConstMetric(
|
|
zc.MetricsDesc[name], prometheus.CounterValue, float64(h.Buckets[svalue]), append(h.LabelValues, svalue)...)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func panicOnDuplicateMetricName(m map[string]*prometheus.Desc, name string, log log.Logger) {
|
|
if _, present := m[name]; present {
|
|
log.Fatal().Msg("Duplicate keys: metric " + name + " already present")
|
|
}
|
|
}
|
|
|
|
func GetCollector(c *Controller) *Collector {
|
|
// compute all metrics description map
|
|
MetricsDesc := map[string]*prometheus.Desc{
|
|
"zot_up": prometheus.NewDesc(
|
|
"zot_up",
|
|
"Connection to zot server was successfully established.",
|
|
nil, nil,
|
|
),
|
|
}
|
|
invalidChars := regexp.MustCompile("[^a-zA-Z0-9:_]")
|
|
|
|
for metricName, metricLabelNames := range monitoring.GetCounters() {
|
|
name := invalidChars.ReplaceAllLiteralString(metricName, "_")
|
|
name += "_total"
|
|
panicOnDuplicateMetricName(MetricsDesc, name, c.Log)
|
|
MetricsDesc[name] = prometheus.NewDesc(name, "Metric "+name, metricLabelNames, nil)
|
|
}
|
|
|
|
for metricName, metricLabelNames := range monitoring.GetGauges() {
|
|
name := invalidChars.ReplaceAllLiteralString(metricName, "_")
|
|
panicOnDuplicateMetricName(MetricsDesc, name, c.Log)
|
|
MetricsDesc[name] = prometheus.NewDesc(name, "Metric "+name, metricLabelNames, nil)
|
|
}
|
|
|
|
for metricName, metricLabelNames := range monitoring.GetSummaries() {
|
|
mname := invalidChars.ReplaceAllLiteralString(metricName, "_")
|
|
|
|
name := mname + "_count"
|
|
panicOnDuplicateMetricName(MetricsDesc, name, c.Log)
|
|
MetricsDesc[name] = prometheus.NewDesc(name, "Metric "+name, metricLabelNames, nil)
|
|
|
|
name = mname + "_sum"
|
|
panicOnDuplicateMetricName(MetricsDesc, name, c.Log)
|
|
MetricsDesc[name] = prometheus.NewDesc(name, "Metric "+name, metricLabelNames, nil)
|
|
}
|
|
|
|
for metricName, metricLabelNames := range monitoring.GetHistograms() {
|
|
mname := invalidChars.ReplaceAllLiteralString(metricName, "_")
|
|
|
|
name := mname + "_count"
|
|
panicOnDuplicateMetricName(MetricsDesc, name, c.Log)
|
|
MetricsDesc[name] = prometheus.NewDesc(name, "Metric "+name, metricLabelNames, nil)
|
|
|
|
name = mname + "_sum"
|
|
panicOnDuplicateMetricName(MetricsDesc, name, c.Log)
|
|
MetricsDesc[name] = prometheus.NewDesc(name, "Metric "+name, metricLabelNames, nil)
|
|
|
|
name = mname + "_bucket"
|
|
panicOnDuplicateMetricName(MetricsDesc, name, c.Log)
|
|
// Append a new label to hitogram bucket - le - 'lower or equal'
|
|
MetricsDesc[name] = prometheus.NewDesc(name, "Metric "+name, append(metricLabelNames, "le"), nil)
|
|
}
|
|
|
|
// parameters to connect to the zot server
|
|
serverAddr := fmt.Sprintf("%s://%s:%s", c.Config.Server.Protocol,
|
|
c.Config.Server.Host, c.Config.Server.Port)
|
|
cfg := &monitoring.MetricsConfig{Address: serverAddr}
|
|
|
|
return &Collector{
|
|
Client: monitoring.NewMetricsClient(cfg, c.Log),
|
|
MetricsDesc: MetricsDesc,
|
|
invalidChars: invalidChars,
|
|
}
|
|
}
|
|
|
|
func runExporter(c *Controller) {
|
|
err := prometheus.Register(GetCollector(c))
|
|
if err != nil {
|
|
c.Log.Error().Err(err).Msg("Expected error in testing")
|
|
}
|
|
|
|
http.Handle(c.Config.Exporter.Metrics.Path, promhttp.Handler())
|
|
exporterAddr := fmt.Sprintf(":%s", c.Config.Exporter.Port)
|
|
c.Log.Info().Msgf("Exporter is listening on %s & exposes metrics on %s path",
|
|
exporterAddr, c.Config.Exporter.Metrics.Path)
|
|
|
|
serverAddr := fmt.Sprintf("%s://%s:%s", c.Config.Server.Protocol,
|
|
c.Config.Server.Host, c.Config.Server.Port)
|
|
c.Log.Info().Msgf("Scraping metrics from %s", serverAddr)
|
|
c.Log.Fatal().Err(http.ListenAndServe(exporterAddr, nil)).Msg("Exporter stopped")
|
|
}
|