cert-manager/pkg/metrics/metrics.go
Ashley Davis 3a055cc2f5
rename all uses of github.com/jetstack/cert-manager
This was done by running the following command twice:

 ```bash
 grep -Ri "github.com/jetstack/cert-manager" . | \
 cut -d":" -f1 | \
 sort | \
 uniq | \
 xargs sed -i
 "s/github.com\/jetstack\/cert-manager/github.com\/cert-manager\/cert-manager/"
 ```

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-02-02 09:08:31 +00:00

209 lines
7.5 KiB
Go

/*
Copyright 2020 The cert-manager Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package metrics contains global structures related to metrics collection
// cert-manager exposes the following metrics:
// certificate_expiration_timestamp_seconds{name, namespace}
// certificate_renewal_timestamp_seconds{name, namespace}
// certificate_ready_status{name, namespace, condition}
// acme_client_request_count{"scheme", "host", "path", "method", "status"}
// acme_client_request_duration_seconds{"scheme", "host", "path", "method", "status"}
// controller_sync_call_count{"controller"}
package metrics
import (
"net"
"net/http"
"time"
"github.com/go-logr/logr"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"k8s.io/utils/clock"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
)
const (
// Namespace is the namespace for cert-manager metric names
namespace = "certmanager"
prometheusMetricsServerReadTimeout = 8 * time.Second
prometheusMetricsServerWriteTimeout = 8 * time.Second
prometheusMetricsServerMaxHeaderBytes = 1 << 20 // 1 MiB
)
// Metrics is designed to be a shared object for updating the metrics exposed
// by cert-manager
type Metrics struct {
log logr.Logger
registry *prometheus.Registry
clockTimeSeconds prometheus.CounterFunc
clockTimeSecondsGauge prometheus.GaugeFunc
certificateExpiryTimeSeconds *prometheus.GaugeVec
certificateRenewalTimeSeconds *prometheus.GaugeVec
certificateReadyStatus *prometheus.GaugeVec
acmeClientRequestDurationSeconds *prometheus.SummaryVec
acmeClientRequestCount *prometheus.CounterVec
controllerSyncCallCount *prometheus.CounterVec
}
var readyConditionStatuses = [...]cmmeta.ConditionStatus{cmmeta.ConditionTrue, cmmeta.ConditionFalse, cmmeta.ConditionUnknown}
// New creates a Metrics struct and populates it with prometheus metric types.
func New(log logr.Logger, c clock.Clock) *Metrics {
var (
// Deprecated in favour of clock_time_seconds_gauge.
clockTimeSeconds = prometheus.NewCounterFunc(
prometheus.CounterOpts{
Namespace: namespace,
Name: "clock_time_seconds",
Help: "DEPRECATED: use clock_time_seconds_gauge instead. The clock time given in seconds (from 1970/01/01 UTC).",
},
func() float64 {
return float64(c.Now().Unix())
},
)
// The clockTimeSeconds metric was first added, however this was
// erroneously made a "counter" metric type. Time can in fact go backwards,
// see:
// - https://github.com/cert-manager/cert-manager/issues/4560
// - https://www.robustperception.io/are-increasing-timestamps-counters-or-gauges
// In order to not break users relying on the `clock_time_seconds` metric,
// a new `clock_time_seconds_gauge` metric of type gauge is added which
// implements the same thing.
clockTimeSecondsGauge = prometheus.NewGaugeFunc(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "clock_time_seconds_gauge",
Help: "The clock time given in seconds (from 1970/01/01 UTC).",
},
func() float64 {
return float64(c.Now().Unix())
},
)
certificateExpiryTimeSeconds = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "certificate_expiration_timestamp_seconds",
Help: "The date after which the certificate expires. Expressed as a Unix Epoch Time.",
},
[]string{"name", "namespace"},
)
certificateRenewalTimeSeconds = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "certificate_renewal_timestamp_seconds",
Help: "The number of seconds before expiration time the certificate should renew.",
},
[]string{"name", "namespace"},
)
certificateReadyStatus = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "certificate_ready_status",
Help: "The ready status of the certificate.",
},
[]string{"name", "namespace", "condition"},
)
// acmeClientRequestCount is a Prometheus summary to collect the number of
// requests made to each endpoint with the ACME client.
acmeClientRequestCount = prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
Name: "acme_client_request_count",
Help: "The number of requests made by the ACME client.",
Subsystem: "http",
},
[]string{"scheme", "host", "path", "method", "status"},
)
// acmeClientRequestDurationSeconds is a Prometheus summary to collect request
// times for the ACME client.
acmeClientRequestDurationSeconds = prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Namespace: namespace,
Name: "acme_client_request_duration_seconds",
Help: "The HTTP request latencies in seconds for the ACME client.",
Subsystem: "http",
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
},
[]string{"scheme", "host", "path", "method", "status"},
)
controllerSyncCallCount = prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
Name: "controller_sync_call_count",
Help: "The number of sync() calls made by a controller.",
},
[]string{"controller"},
)
)
// Create server and register Prometheus metrics handler
m := &Metrics{
log: log.WithName("metrics"),
registry: prometheus.NewRegistry(),
clockTimeSeconds: clockTimeSeconds,
clockTimeSecondsGauge: clockTimeSecondsGauge,
certificateExpiryTimeSeconds: certificateExpiryTimeSeconds,
certificateRenewalTimeSeconds: certificateRenewalTimeSeconds,
certificateReadyStatus: certificateReadyStatus,
acmeClientRequestCount: acmeClientRequestCount,
acmeClientRequestDurationSeconds: acmeClientRequestDurationSeconds,
controllerSyncCallCount: controllerSyncCallCount,
}
return m
}
// NewServer registers Prometheus metrics and returns a new Prometheus metrics HTTP server.
func (m *Metrics) NewServer(ln net.Listener) *http.Server {
m.registry.MustRegister(m.clockTimeSeconds)
m.registry.MustRegister(m.clockTimeSecondsGauge)
m.registry.MustRegister(m.certificateExpiryTimeSeconds)
m.registry.MustRegister(m.certificateRenewalTimeSeconds)
m.registry.MustRegister(m.certificateReadyStatus)
m.registry.MustRegister(m.acmeClientRequestDurationSeconds)
m.registry.MustRegister(m.acmeClientRequestCount)
m.registry.MustRegister(m.controllerSyncCallCount)
mux := http.NewServeMux()
mux.Handle("/metrics", promhttp.HandlerFor(m.registry, promhttp.HandlerOpts{}))
server := &http.Server{
Addr: ln.Addr().String(),
ReadTimeout: prometheusMetricsServerReadTimeout,
WriteTimeout: prometheusMetricsServerWriteTimeout,
MaxHeaderBytes: prometheusMetricsServerMaxHeaderBytes,
Handler: mux,
}
return server
}
// IncrementSyncCallCount will increase the sync counter for that controller.
func (m *Metrics) IncrementSyncCallCount(controllerName string) {
m.controllerSyncCallCount.WithLabelValues(controllerName).Inc()
}