Cleans up metrics pkg to not require locks, and split out resources into
different files Signed-off-by: JoshVanL <vleeuwenjoshua@gmail.com>
This commit is contained in:
parent
db24ca052b
commit
63c5e5f5c6
@ -2,7 +2,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["metrics.go"],
|
||||
srcs = [
|
||||
"acme.go",
|
||||
"certificates.go",
|
||||
"metrics.go",
|
||||
],
|
||||
importpath = "github.com/jetstack/cert-manager/pkg/metrics",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
@ -33,7 +37,7 @@ filegroup(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["metrics_test.go"],
|
||||
srcs = ["certificates_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/certmanager/v1alpha2:go_default_library",
|
||||
|
||||
38
pkg/metrics/acme.go
Normal file
38
pkg/metrics/acme.go
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright 2020 The Jetstack cert-manager contributors.
|
||||
|
||||
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_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 (
|
||||
"time"
|
||||
)
|
||||
|
||||
// ObserveACMERequestDuration increases bucket counters for that ACME client duration.
|
||||
func (m *Metrics) ObserveACMERequestDuration(duration time.Duration, labels ...string) {
|
||||
m.acmeClientRequestDurationSeconds.WithLabelValues(labels...).Observe(duration.Seconds())
|
||||
}
|
||||
|
||||
// IncrementACMERequestCount increases the acme client request counter.
|
||||
func (m *Metrics) IncrementACMERequestCount(labels ...string) {
|
||||
m.acmeClientRequestCount.WithLabelValues(labels...).Inc()
|
||||
}
|
||||
106
pkg/metrics/certificates.go
Normal file
106
pkg/metrics/certificates.go
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2020 The Jetstack cert-manager contributors.
|
||||
|
||||
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_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 (
|
||||
"context"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
logf "github.com/jetstack/cert-manager/pkg/logs"
|
||||
)
|
||||
|
||||
// UpdateCertificate will update that Certificate metric with expiry and Ready
|
||||
// condition.
|
||||
func (m *Metrics) UpdateCertificate(ctx context.Context, crt *cmapi.Certificate) {
|
||||
key, err := cache.MetaNamespaceKeyFunc(crt)
|
||||
if err != nil {
|
||||
log := logf.WithRelatedResource(m.log, crt)
|
||||
log.Error(err, "failed to get key from certificate object")
|
||||
return
|
||||
}
|
||||
|
||||
m.updateCertificateStatus(key, crt)
|
||||
m.updateCertificateExpiry(ctx, key, crt)
|
||||
}
|
||||
|
||||
// updateCertificateExpiry updates the expiry time of a certificate
|
||||
func (m *Metrics) updateCertificateExpiry(ctx context.Context, key string, crt *cmapi.Certificate) {
|
||||
expiryTime := 0.0
|
||||
|
||||
if crt.Status.NotAfter != nil {
|
||||
expiryTime = float64(crt.Status.NotAfter.Unix())
|
||||
}
|
||||
|
||||
m.certificateExpiryTimeSeconds.With(prometheus.Labels{
|
||||
"name": crt.Name,
|
||||
"namespace": crt.Namespace}).Set(expiryTime)
|
||||
}
|
||||
|
||||
// updateCertificateStatus will update the metric for that Certificate
|
||||
func (m *Metrics) updateCertificateStatus(key string, crt *cmapi.Certificate) {
|
||||
for _, c := range crt.Status.Conditions {
|
||||
if c.Type == cmapi.CertificateConditionReady {
|
||||
m.updateCertificateReadyStatus(crt, c.Status)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If no status condition set yet, set to Unknown
|
||||
m.updateCertificateReadyStatus(crt, cmmeta.ConditionUnknown)
|
||||
}
|
||||
|
||||
func (m *Metrics) updateCertificateReadyStatus(crt *cmapi.Certificate, current cmmeta.ConditionStatus) {
|
||||
for _, condition := range readyConditionStatuses {
|
||||
value := 0.0
|
||||
|
||||
if current == condition {
|
||||
value = 1.0
|
||||
}
|
||||
|
||||
m.certificateReadyStatus.With(prometheus.Labels{
|
||||
"name": crt.Name,
|
||||
"namespace": crt.Namespace,
|
||||
"condition": string(condition),
|
||||
}).Set(value)
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveCertificate will delete the Certificate metrics from continuing to be
|
||||
// exposed.
|
||||
func (m *Metrics) RemoveCertificate(key string) {
|
||||
namespace, name, err := cache.SplitMetaNamespaceKey(key)
|
||||
if err != nil {
|
||||
m.log.Error(err, "failed to get namespace and name from key")
|
||||
return
|
||||
}
|
||||
|
||||
m.certificateExpiryTimeSeconds.DeleteLabelValues(name, namespace)
|
||||
for _, condition := range readyConditionStatuses {
|
||||
m.certificateReadyStatus.DeleteLabelValues(name, namespace, string(condition))
|
||||
}
|
||||
}
|
||||
@ -26,18 +26,14 @@ package metrics
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
logf "github.com/jetstack/cert-manager/pkg/logs"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -56,15 +52,11 @@ type Metrics struct {
|
||||
registry *prometheus.Registry
|
||||
server *http.Server
|
||||
|
||||
mux sync.Mutex
|
||||
|
||||
certificateExpiryTimeSeconds *prometheus.GaugeVec
|
||||
certificateReadyStatus *prometheus.GaugeVec
|
||||
acmeClientRequestDurationSeconds *prometheus.SummaryVec
|
||||
acmeClientRequestCount *prometheus.CounterVec
|
||||
controllerSyncCallCount *prometheus.CounterVec
|
||||
|
||||
registeredCertificates map[string]struct{}
|
||||
}
|
||||
|
||||
var readyConditionStatuses = [...]cmmeta.ConditionStatus{cmmeta.ConditionTrue, cmmeta.ConditionFalse, cmmeta.ConditionUnknown}
|
||||
@ -138,8 +130,6 @@ func New(log logr.Logger, listenAddress string) *Metrics {
|
||||
Handler: router,
|
||||
},
|
||||
|
||||
registeredCertificates: make(map[string]struct{}),
|
||||
|
||||
certificateExpiryTimeSeconds: certificateExpiryTimeSeconds,
|
||||
certificateReadyStatus: certificateReadyStatus,
|
||||
acmeClientRequestCount: acmeClientRequestCount,
|
||||
@ -175,112 +165,11 @@ func (m *Metrics) Start(stopCh <-chan struct{}) {
|
||||
m.shutdown()
|
||||
}
|
||||
|
||||
// ObserveACMERequestDuration increases bucket counters for that ACME client duration.
|
||||
func (m *Metrics) ObserveACMERequestDuration(duration time.Duration, labels ...string) {
|
||||
m.acmeClientRequestDurationSeconds.WithLabelValues(labels...).Observe(duration.Seconds())
|
||||
}
|
||||
|
||||
// IncrementACMERequestCount increases the acme client request counter.
|
||||
func (m *Metrics) IncrementACMERequestCount(labels ...string) {
|
||||
m.acmeClientRequestCount.WithLabelValues(labels...).Inc()
|
||||
}
|
||||
|
||||
// IncrementSyncCallCount will increase the sync counter for that controller.
|
||||
func (m *Metrics) IncrementSyncCallCount(controllerName string) {
|
||||
m.controllerSyncCallCount.WithLabelValues(controllerName).Inc()
|
||||
}
|
||||
|
||||
// UpdateCertificate will update that Certificate metric with expiry and Ready
|
||||
// condition.
|
||||
func (m *Metrics) UpdateCertificate(ctx context.Context, crt *cmapi.Certificate) {
|
||||
key, err := cache.MetaNamespaceKeyFunc(crt)
|
||||
if err != nil {
|
||||
log := logf.WithRelatedResource(m.log, crt)
|
||||
log.Error(err, "failed to get key from certificate object")
|
||||
return
|
||||
}
|
||||
|
||||
m.updateCertificateStatus(key, crt)
|
||||
m.updateCertificateExpiry(ctx, key, crt)
|
||||
}
|
||||
|
||||
// updateCertificateExpiry updates the expiry time of a certificate
|
||||
func (m *Metrics) updateCertificateExpiry(ctx context.Context, key string, crt *cmapi.Certificate) {
|
||||
expiryTime := 0.0
|
||||
|
||||
if crt.Status.NotAfter != nil {
|
||||
expiryTime = float64(crt.Status.NotAfter.Unix())
|
||||
}
|
||||
|
||||
m.certificateExpiryTimeSeconds.With(prometheus.Labels{
|
||||
"name": crt.Name,
|
||||
"namespace": crt.Namespace}).Set(expiryTime)
|
||||
|
||||
m.mux.Lock()
|
||||
m.registeredCertificates[key] = struct{}{}
|
||||
m.mux.Unlock()
|
||||
}
|
||||
|
||||
// updateCertificateStatus will update the metric for that Certificate
|
||||
func (m *Metrics) updateCertificateStatus(key string, crt *cmapi.Certificate) {
|
||||
defer func() {
|
||||
m.mux.Lock()
|
||||
m.registeredCertificates[key] = struct{}{}
|
||||
m.mux.Unlock()
|
||||
}()
|
||||
|
||||
for _, c := range crt.Status.Conditions {
|
||||
if c.Type == cmapi.CertificateConditionReady {
|
||||
m.updateCertificateReadyStatus(crt, c.Status)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If no status condition set yet, set to Unknown
|
||||
m.updateCertificateReadyStatus(crt, cmmeta.ConditionUnknown)
|
||||
}
|
||||
|
||||
func (m *Metrics) updateCertificateReadyStatus(crt *cmapi.Certificate, current cmmeta.ConditionStatus) {
|
||||
for _, condition := range readyConditionStatuses {
|
||||
value := 0.0
|
||||
|
||||
if current == condition {
|
||||
value = 1.0
|
||||
}
|
||||
|
||||
m.certificateReadyStatus.With(prometheus.Labels{
|
||||
"name": crt.Name,
|
||||
"namespace": crt.Namespace,
|
||||
"condition": string(condition),
|
||||
}).Set(value)
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveCertificate will delete the Certificate metrics from continuing to be
|
||||
// exposed.
|
||||
func (m *Metrics) RemoveCertificate(key string) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
namespace, name, err := cache.SplitMetaNamespaceKey(key)
|
||||
if err != nil {
|
||||
m.log.Error(err, "failed to get namespace and name from key")
|
||||
return
|
||||
}
|
||||
|
||||
// If the certificate is not registered, exit early
|
||||
if _, ok := m.registeredCertificates[key]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
m.certificateExpiryTimeSeconds.DeleteLabelValues(name, namespace)
|
||||
for _, condition := range readyConditionStatuses {
|
||||
m.certificateReadyStatus.DeleteLabelValues(name, namespace, string(condition))
|
||||
}
|
||||
|
||||
delete(m.registeredCertificates, key)
|
||||
}
|
||||
|
||||
func (m *Metrics) shutdown() {
|
||||
m.log.Info("stopping Prometheus metrics server...")
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user