func (m *PrometheusMetrics) init() {
	m.metrics.K8gbRuntimeInfo = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: K8gbRuntimeInfo,
			Help: "K8gb runtime info.",
		},
		[]string{"namespace", "k8gb_version", "go_version", "arch", "os", "git_sha"},
	)
	m.metrics.K8gbEndpointStatusNum = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: K8gbEndpointStatusNum,
			Help: "Number of targets in DNS endpoint.",
		},
		[]string{"namespace", "name", "dns_name"},
	)
	m.metrics.K8gbGslbHealthyRecords = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: K8gbGslbHealthyRecords,
			Help: "Number of healthy records observed by K8GB.",
		},
		[]string{"namespace", "name"},
	)
	m.metrics.K8gbGslbServiceStatusNum = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: K8gbGslbServiceStatusNum,
			Help: "Number of managed hosts observed by K8GB.",
		},
		[]string{"namespace", "name", "status"},
	)
	m.metrics.K8gbGslbErrorsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: K8gbGslbErrorsTotal,
			Help: "Number of errors",
		},
		[]string{"namespace", "name"},
	)
	m.metrics.K8gbGslbReconciliationLoopsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: K8gbGslbReconciliationLoopsTotal,
			Help: "Number of successful reconciliation loops.",
		},
		[]string{"namespace", "name"},
	)
	m.metrics.K8gbGslbStatusCountForFailover = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: K8gbGslbStatusCountForFailover,
			Help: "Gslb status count for Failover strategy.",
		},
		[]string{"namespace", "name", "status"},
	)
	m.metrics.K8gbGslbStatusCountForRoundrobin = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: K8gbGslbStatusCountForRoundrobin,
			Help: "Gslb status count for RoundRobin strategy.",
		},
		[]string{"namespace", "name", "status"},
	)
	m.metrics.K8gbGslbStatusCountForGeoip = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: K8gbGslbStatusCountForGeoIP,
			Help: "Gslb status count for GeoIP strategy.",
		},
		[]string{"namespace", "name", "status"},
	)
	m.metrics.K8gbInfobloxZoneUpdatesTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: K8gbInfobloxZoneUpdatesTotal,
			Help: "Number of K8GB Infoblox zone updates.",
		},
		[]string{"namespace", "name"},
	)
	m.metrics.K8gbInfobloxZoneUpdateErrorsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: K8gbInfobloxZoneUpdateErrorsTotal,
			Help: "Number of K8GB Infoblox zone update errors.",
		},
		[]string{"namespace", "name"},
	)
	m.metrics.K8gbInfobloxHeartbeatsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: K8gbInfobloxHeartbeatsTotal,
			Help: "Number of K8GB Infoblox heartbeat TXT record updates.",
		},
		[]string{"namespace", "name"},
	)
	m.metrics.K8gbInfobloxHeartbeatErrorsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: K8gbInfobloxHeartbeatErrorsTotal,
			Help: "Number of K8GB Infoblox TXT record errors.",
		},
		[]string{"namespace", "name"},
	)
}
init instantiates particular metrics
package metrics
import (
	"fmt"
	"reflect"
	"regexp"
	"runtime"
	"strings"
	"sync"
	externaldns "sigs.k8s.io/external-dns/endpoint"
	k8gbv1beta1 "github.com/k8gb-io/k8gb/api/v1beta1"
	"github.com/k8gb-io/k8gb/controllers/depresolver"
	"github.com/k8gb-io/k8gb/controllers/internal/utils"
	"github.com/prometheus/client_golang/prometheus"
	crm "sigs.k8s.io/controller-runtime/pkg/metrics"
)
const (
	primary   = "primary"
	secondary = "secondary"
)
const (
	K8gbGslbErrorsTotal               = "k8gb_gslb_errors_total"
	K8gbGslbHealthyRecords            = "k8gb_gslb_healthy_records"
	K8gbGslbReconciliationLoopsTotal  = "k8gb_gslb_reconciliation_loops_total"
	K8gbGslbServiceStatusNum          = "k8gb_gslb_service_status_num"
	K8gbGslbStatusCountForFailover    = "k8gb_gslb_status_count_for_failover"
	K8gbGslbStatusCountForRoundrobin  = "k8gb_gslb_status_count_for_roundrobin"
	K8gbGslbStatusCountForGeoIP       = "k8gb_gslb_status_count_for_geoip"
	K8gbInfobloxHeartbeatsTotal       = "k8gb_infoblox_heartbeats_total"
	K8gbInfobloxHeartbeatErrorsTotal  = "k8gb_infoblox_heartbeat_errors_total"
	K8gbInfobloxZoneUpdatesTotal      = "k8gb_infoblox_zone_updates_total"
	K8gbInfobloxZoneUpdateErrorsTotal = "k8gb_infoblox_zone_update_errors_total"
	K8gbEndpointStatusNum             = "k8gb_endpoint_status_num"
	K8gbRuntimeInfo                   = "k8gb_runtime_info"
)
type collectors struct {
	K8gbGslbHealthyRecords            *prometheus.GaugeVec
	K8gbGslbServiceStatusNum          *prometheus.GaugeVec
	K8gbGslbStatusCountForFailover    *prometheus.GaugeVec
	K8gbGslbStatusCountForRoundrobin  *prometheus.GaugeVec
	K8gbGslbStatusCountForGeoip       *prometheus.GaugeVec
	K8gbGslbErrorsTotal               *prometheus.CounterVec
	K8gbGslbReconciliationLoopsTotal  *prometheus.CounterVec
	K8gbInfobloxZoneUpdatesTotal      *prometheus.CounterVec
	K8gbInfobloxZoneUpdateErrorsTotal *prometheus.CounterVec
	K8gbInfobloxHeartbeatsTotal       *prometheus.CounterVec
	K8gbInfobloxHeartbeatErrorsTotal  *prometheus.CounterVec
	K8gbEndpointStatusNum             *prometheus.GaugeVec
	K8gbRuntimeInfo                   *prometheus.GaugeVec
}
type PrometheusMetrics struct {
	once    sync.Once
	config  depresolver.Config
	metrics collectors
}
var regex = regexp.MustCompile("[A-Z]")
func newPrometheusMetrics(config depresolver.Config) (metrics *PrometheusMetrics) {
	metrics = new(PrometheusMetrics)
	metrics.config = config
	metrics.init()
	return
}
func (m *PrometheusMetrics) UpdateIngressHostsPerStatusMetric(gslb *k8gbv1beta1.Gslb, serviceHealth map[string]k8gbv1beta1.HealthStatus) {
	var healthyHostsCount, unhealthyHostsCount, notFoundHostsCount int
	for _, hs := range serviceHealth {
		switch hs {
		case k8gbv1beta1.Healthy:
			healthyHostsCount++
		case k8gbv1beta1.Unhealthy:
			unhealthyHostsCount++
		default:
			notFoundHostsCount++
		}
	}
	m.metrics.K8gbGslbServiceStatusNum.
		With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name, "status": k8gbv1beta1.Healthy.String()}).Set(float64(healthyHostsCount))
	m.metrics.K8gbGslbServiceStatusNum.
		With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name, "status": k8gbv1beta1.Unhealthy.String()}).Set(float64(unhealthyHostsCount))
	m.metrics.K8gbGslbServiceStatusNum.
		With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name, "status": k8gbv1beta1.NotFound.String()}).Set(float64(notFoundHostsCount))
}
func (m *PrometheusMetrics) UpdateHealthyRecordsMetric(gslb *k8gbv1beta1.Gslb, healthyRecords map[string][]string) {
	var hrsCount int
	for _, hrs := range healthyRecords {
		hrsCount += len(hrs)
	}
	m.metrics.K8gbGslbHealthyRecords.With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name}).Set(float64(hrsCount))
}
func (m *PrometheusMetrics) UpdateEndpointStatus(ep *externaldns.DNSEndpoint) {
	for _, e := range ep.Spec.Endpoints {
		m.metrics.K8gbEndpointStatusNum.With(prometheus.Labels{"namespace": ep.Namespace, "name": ep.Name, "dns_name": e.DNSName}).
			Set(float64(e.Targets.Len()))
	}
}
func (m *PrometheusMetrics) UpdateFailoverStatus(gslb *k8gbv1beta1.Gslb, isPrimary bool, healthy k8gbv1beta1.HealthStatus, targets []string) {
	t := secondary
	if isPrimary {
		t = primary
	}
	m.updateRuntimeStatus(gslb, m.metrics.K8gbGslbStatusCountForFailover, healthy, targets, "_"+t)
}
func (m *PrometheusMetrics) UpdateRoundrobinStatus(gslb *k8gbv1beta1.Gslb, healthy k8gbv1beta1.HealthStatus, targets []string) {
	m.updateRuntimeStatus(gslb, m.metrics.K8gbGslbStatusCountForRoundrobin, healthy, targets, "")
}
func (m *PrometheusMetrics) UpdateGeoIPStatus(gslb *k8gbv1beta1.Gslb, healthy k8gbv1beta1.HealthStatus, targets []string) {
	m.updateRuntimeStatus(gslb, m.metrics.K8gbGslbStatusCountForGeoip, healthy, targets, "")
}
func (m *PrometheusMetrics) IncrementError(gslb *k8gbv1beta1.Gslb) {
	m.metrics.K8gbGslbErrorsTotal.With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name}).Inc()
}
func (m *PrometheusMetrics) IncrementReconciliation(gslb *k8gbv1beta1.Gslb) {
	m.metrics.K8gbGslbReconciliationLoopsTotal.With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name}).Inc()
}
func (m *PrometheusMetrics) InfobloxIncrementZoneUpdate(gslb *k8gbv1beta1.Gslb) {
	m.metrics.K8gbInfobloxZoneUpdatesTotal.With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name}).Inc()
}
func (m *PrometheusMetrics) InfobloxIncrementZoneUpdateError(gslb *k8gbv1beta1.Gslb) {
	m.metrics.K8gbInfobloxZoneUpdateErrorsTotal.With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name}).Inc()
}
func (m *PrometheusMetrics) InfobloxIncrementHeartbeat(gslb *k8gbv1beta1.Gslb) {
	m.metrics.K8gbInfobloxHeartbeatsTotal.With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name}).Inc()
}
func (m *PrometheusMetrics) InfobloxIncrementHeartbeatError(gslb *k8gbv1beta1.Gslb) {
	m.metrics.K8gbInfobloxHeartbeatErrorsTotal.With(prometheus.Labels{"namespace": gslb.Namespace, "name": gslb.Name}).Inc()
}
func (m *PrometheusMetrics) SetRuntimeInfo(version, commit string) {
	firstN := func(value string, n int) string {
		if len(value) < n {
			return value
		}
		return value[:n]
	}
	m.metrics.K8gbRuntimeInfo.With(
		prometheus.Labels{"namespace": m.config.K8gbNamespace, "go_version": runtime.Version(), "arch": runtime.GOARCH,
			"os": runtime.GOOS, "k8gb_version": version, "git_sha": firstN(commit, 7)}).Set(1)
}
func (m *PrometheusMetrics) Register() (err error) {
	m.once.Do(func() {
		for _, r := range m.registry() {
			if err = crm.Registry.Register(r); err != nil {
				return
			}
		}
	})
	if err != nil {
		return fmt.Errorf("can't register prometheus metrics: %s", err)
	}
	return
}
func (m *PrometheusMetrics) Unregister() {
	for _, r := range m.registry() {
		crm.Registry.Unregister(r)
	}
}