Files
houston/client/custom_exporter.go
2023-11-16 19:47:30 +09:00

84 lines
2.0 KiB
Go

package client
import (
"math"
_ "net/http/pprof"
"sync/atomic"
"unsafe"
"github.com/prometheus/client_golang/prometheus"
"repositories.action2quare.com/ayo/gocommon/metric"
)
type metricDesc struct {
*prometheus.Desc
val *uint64
valueType prometheus.ValueType
}
type exporterForPrometheus struct {
metricPtr unsafe.Pointer // []metricDesc
}
func newExporterForPrometheus() *exporterForPrometheus {
return &exporterForPrometheus{
metricPtr: unsafe.Pointer(new([]metricDesc)),
}
}
type metricValueAccessor struct {
ptr *uint64
}
func (va metricValueAccessor) set(val float64) {
atomic.StoreUint64(va.ptr, math.Float64bits(val))
}
func convertValueType(in metric.MetricType) prometheus.ValueType {
switch in {
case metric.MetricCounter:
return prometheus.CounterValue
case metric.MetricGuage:
return prometheus.GaugeValue
}
return prometheus.UntypedValue
}
func (e *exporterForPrometheus) registMetric(namespace string, desc metric.MetricDescription) metricValueAccessor {
ptr := atomic.LoadPointer(&e.metricPtr)
container := *(*[]metricDesc)(ptr)
newcont := make([]metricDesc, len(container)+1)
copy(newcont, container)
newval := new(uint64)
newcont[len(container)] = metricDesc{
Desc: prometheus.NewDesc(prometheus.BuildFQName(namespace, "", desc.Name), desc.Help, nil, desc.ConstLabels),
val: newval,
valueType: convertValueType(desc.Type),
}
atomic.StorePointer(&e.metricPtr, unsafe.Pointer(&newcont))
return metricValueAccessor{
ptr: newval,
}
}
func (e *exporterForPrometheus) Describe(ch chan<- *prometheus.Desc) {
ptr := atomic.LoadPointer(&e.metricPtr)
container := *(*[]metricDesc)(ptr)
for _, v := range container {
ch <- v.Desc
}
}
func (e *exporterForPrometheus) Collect(ch chan<- prometheus.Metric) {
ptr := atomic.LoadPointer(&e.metricPtr)
container := *(*[]metricDesc)(ptr)
for _, v := range container {
ch <- prometheus.MustNewConstMetric(v.Desc, v.valueType, math.Float64frombits(atomic.LoadUint64(v.val)))
}
}