Files
gocommon/metric/common.go

145 lines
3.2 KiB
Go
Raw Normal View History

2023-11-16 19:56:47 +09:00
package metric
import (
"crypto/md5"
"encoding/binary"
"encoding/hex"
"encoding/json"
2023-11-20 13:49:29 +09:00
"fmt"
2023-11-16 19:56:47 +09:00
"math"
"os"
2023-11-20 16:39:39 +09:00
"path"
2023-11-20 17:06:53 +09:00
"strings"
2023-11-20 14:12:44 +09:00
"sync/atomic"
2023-11-20 13:49:29 +09:00
"repositories.action2quare.com/ayo/gocommon/logger"
2023-11-16 19:56:47 +09:00
)
2023-11-28 22:29:52 +09:00
const metric_value_line_size = 19
2023-11-16 19:56:47 +09:00
type MetricDescription struct {
Key string
Type MetricType
Name string `json:",omitempty"`
Help string `json:",omitempty"`
ConstLabels map[string]string `json:",omitempty"`
}
2023-11-28 22:29:52 +09:00
type Exporter interface {
RegisterMetric(*MetricDescription)
UpdateMetric(string, float64)
2023-11-16 19:56:47 +09:00
}
2023-11-20 14:12:44 +09:00
type MetricWriter interface {
Add(int64)
Set(int64)
}
type metric_empty struct{}
2023-11-28 22:29:52 +09:00
func (mw *metric_empty) Set(int64) {}
func (mw *metric_empty) Add(int64) {}
2023-11-20 14:12:44 +09:00
2023-11-22 23:41:49 +09:00
var MetricWriterNil = MetricWriter(&metric_empty{})
2023-11-20 14:12:44 +09:00
type metric_int64 struct {
2023-11-28 22:29:52 +09:00
valptr *int64
buff [metric_value_line_size]byte
2023-11-20 14:12:44 +09:00
}
2023-11-28 22:29:52 +09:00
func (mw *metric_int64) printOut() {
binary.LittleEndian.PutUint64(mw.buff[9:], math.Float64bits(float64(atomic.LoadInt64(mw.valptr))))
os.Stdout.Write(mw.buff[:])
2023-11-20 14:12:44 +09:00
}
func (mw *metric_int64) Set(newval int64) {
atomic.StoreInt64(mw.valptr, newval)
2023-11-28 22:29:52 +09:00
mw.printOut()
2023-11-20 14:12:44 +09:00
}
func (mw *metric_int64) Add(inc int64) {
atomic.AddInt64(mw.valptr, inc)
2023-11-28 22:29:52 +09:00
mw.printOut()
2023-11-20 14:12:44 +09:00
}
2023-11-16 19:56:47 +09:00
2023-11-28 22:29:52 +09:00
func NewMetric(mt MetricType, name string, help string, constLabels map[string]string) (writer MetricWriter) {
if !metricEnabled {
return MetricWriterNil
2023-11-16 19:56:47 +09:00
}
2023-11-28 22:29:52 +09:00
hash := md5.New()
hash.Write([]byte(name))
for k, v := range constLabels {
hash.Write([]byte(k))
hash.Write([]byte(v))
}
2023-11-16 19:56:47 +09:00
2023-11-28 22:29:52 +09:00
key := hex.EncodeToString(hash.Sum(nil))[:metric_key_size]
temp, _ := json.Marshal(MetricDescription{
Key: key,
Type: mt,
Name: name,
Help: help,
ConstLabels: constLabels,
})
impl := &metric_int64{
valptr: new(int64),
}
impl.buff[0] = METRIC_HEAD_INLINE
impl.buff[17] = METRIC_TAIL_INLINE
impl.buff[18] = '\n'
copy(impl.buff[1:], []byte(key))
output := append([]byte{METRIC_HEAD_INLINE}, temp...)
output = append(output, METRIC_TAIL_INLINE, '\n')
os.Stdout.Write(output)
// writer
return impl
}
func ReadMetricValue(line []byte) (string, float64) {
if len(line) < 16 {
return "", 0
2023-11-20 13:49:29 +09:00
}
2023-11-16 19:56:47 +09:00
2023-11-28 22:29:52 +09:00
key := string(line[0:8])
valbits := binary.LittleEndian.Uint64(line[8:])
val := math.Float64frombits(valbits)
return key, val
}
var metricEnabled = false
func init() {
2023-11-20 16:39:39 +09:00
if path.Base(os.Args[0]) == "houston" {
logger.Println("metrics are going to be generated for myself(houston)")
2023-11-28 22:29:52 +09:00
metricEnabled = true
2023-11-20 16:39:39 +09:00
return
}
2023-11-20 13:49:29 +09:00
ppid := os.Getppid()
if parent, _ := os.FindProcess(ppid); parent != nil {
filename := fmt.Sprintf(`/proc/%d/stat`, os.Getppid())
if fn, err := os.ReadFile(filename); err == nil {
2023-11-20 17:06:53 +09:00
stats := strings.SplitN(string(fn), " ", 3)
parentname := strings.Trim(stats[1], "()")
if path.Base(parentname) == "houston" {
2023-11-20 16:39:39 +09:00
logger.Println("metrics are going to be generated for houston")
2023-11-28 22:29:52 +09:00
metricEnabled = true
2023-11-20 13:49:29 +09:00
} else {
2023-11-20 16:42:46 +09:00
logger.Println("metrics are NOT going to be generated. parent is not houston :", filename, string(fn))
2023-11-20 13:49:29 +09:00
}
} else {
2023-11-20 16:39:39 +09:00
logger.Println("metrics are NOT going to be generated. ppid proc is missing :", filename)
2023-11-16 19:56:47 +09:00
}
2023-11-20 13:49:29 +09:00
} else {
2023-11-20 16:39:39 +09:00
logger.Println("metrics are NOT going to be generated. parent process is missing. ppid :", ppid)
2023-11-16 19:56:47 +09:00
}
2023-11-20 13:49:29 +09:00
}