Files
gocommon/metric/prometheus.go
2025-08-12 17:40:03 +09:00

109 lines
2.4 KiB
Go

package metric
import (
"maps"
"math"
"sync/atomic"
"github.com/prometheus/client_golang/prometheus"
"repositories.action2quare.com/ayo/gocommon/logger"
)
const (
METRIC_HEAD_INLINE = byte(14)
METRIC_TAIL_INLINE = byte(15)
)
type MetricType int
const (
MetricCounter = MetricType(1)
MetricGuage = MetricType(2)
metric_key_size = 8
)
func convertValueType(in MetricType) prometheus.ValueType {
switch in {
case MetricCounter:
return prometheus.CounterValue
case MetricGuage:
return prometheus.GaugeValue
}
return prometheus.UntypedValue
}
type prometheusMetricDesc struct {
*prometheus.Desc
valueType prometheus.ValueType
valptr *uint64
key string
}
type PrometheusCollector struct {
namespace string
metrics map[string]*prometheusMetricDesc
registry *prometheus.Registry
}
func (pc *PrometheusCollector) Describe(ch chan<- *prometheus.Desc) {
for _, v := range pc.metrics {
logger.Println("collector describe :", v.Desc.String())
ch <- v.Desc
}
}
func (pc *PrometheusCollector) Collect(ch chan<- prometheus.Metric) {
for _, v := range pc.metrics {
value := atomic.LoadUint64(v.valptr)
cm, err := prometheus.NewConstMetric(v.Desc, v.valueType, math.Float64frombits(value))
if err == nil {
ch <- cm
}
}
}
func (pc *PrometheusCollector) RegisterMetric(md *MetricDescription) *PrometheusCollector {
nm := &prometheusMetricDesc{
Desc: prometheus.NewDesc(prometheus.BuildFQName("ou", "", md.Name), md.Help, nil, md.ConstLabels),
valueType: convertValueType(md.Type),
valptr: new(uint64),
key: md.Key,
}
next := NewPrometheusCollector(pc.namespace, pc.registry)
maps.Copy(next.metrics, pc.metrics)
next.metrics[nm.key] = nm
pc.registry.Unregister(pc)
pc.registry.Register(next)
return next
}
func (pc *PrometheusCollector) UpdateMetric(key string, val float64) {
if m := pc.metrics[key]; m != nil {
atomic.StoreUint64(m.valptr, math.Float64bits(val))
}
}
func (pc *PrometheusCollector) UnregisterMetric(key string) *PrometheusCollector {
next := NewPrometheusCollector(pc.namespace, pc.registry)
maps.Copy(next.metrics, pc.metrics)
delete(next.metrics, key)
pc.registry.Unregister(pc)
pc.registry.Register(next)
return next
}
func NewPrometheusCollector(namespace string, registry *prometheus.Registry) *PrometheusCollector {
return &PrometheusCollector{
namespace: namespace,
metrics: make(map[string]*prometheusMetricDesc),
registry: registry,
}
}