From 72a62b678f83dac0698b1202fd852568a01dbf5e Mon Sep 17 00:00:00 2001 From: mountain Date: Thu, 16 Nov 2023 19:56:47 +0900 Subject: [PATCH] =?UTF-8?q?metric=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metric/metric.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 metric/metric.go diff --git a/metric/metric.go b/metric/metric.go new file mode 100644 index 0000000..1893a3e --- /dev/null +++ b/metric/metric.go @@ -0,0 +1,108 @@ +package metric + +import ( + "crypto/md5" + "encoding/binary" + "encoding/hex" + "encoding/json" + "math" + "os" + "sync" +) + +const ( + METRIC_HEAD_INLINE = byte(1) + METRIC_TAIL_INLINE = byte(2) +) + +type MetricType int + +const ( + MetricCounter = MetricType(1) + MetricGuage = MetricType(2) + metric_key_size = 8 +) + +type MetricDescription struct { + Key string + Type MetricType + Name string `json:",omitempty"` + Help string `json:",omitempty"` + ConstLabels map[string]string `json:",omitempty"` +} + +type writeRequest struct { + key string + val float64 +} + +type metricCollection struct { + writerChan chan *writeRequest +} + +var mc = metricCollection{ + writerChan: make(chan *writeRequest, 100), +} + +type MetricWriter func(float64) + +func (mc *metricCollection) metricWriter() { + // head + metric_key_size + 8byte + tail + cr = 19 + var buff [20]byte + buff[0] = METRIC_HEAD_INLINE + buff[17] = METRIC_TAIL_INLINE + buff[18] = '\n' + + for req := range mc.writerChan { + copy(buff[1:], []byte(req.key)) + binary.BigEndian.PutUint64(buff[9:], math.Float64bits(req.val)) + os.Stdout.Write(buff[:]) + } +} + +var metricWriterFlag sync.Once + +func NewMetric(mt MetricType, name string, help string, constLabel ...string) (writer MetricWriter) { + metricWriterFlag.Do(func() { + go mc.metricWriter() + }) + + hash := md5.New() + hash.Write([]byte(name)) + + var constLabels map[string]string + if len(constLabel) > 0 { + constLabels = make(map[string]string) + for i := 0; i < len(constLabel); i = i + 2 { + constLabels[constLabel[i]] = "" + hash.Write([]byte(constLabel[i])) + } + + for i := 1; i < len(constLabel); i = i + 2 { + constLabels[constLabel[i-1]] = constLabel[i] + hash.Write([]byte(constLabel[i])) + } + } + + key := hex.EncodeToString(hash.Sum(nil))[:metric_key_size] + temp, _ := json.Marshal(MetricDescription{ + Key: key, + Type: mt, + Name: name, + Help: help, + ConstLabels: constLabels, + }) + + writer = func(val float64) { + mc.writerChan <- &writeRequest{ + key: key, + val: val, + } + } + + output := append([]byte{METRIC_HEAD_INLINE}, temp...) + output = append(output, METRIC_TAIL_INLINE, '\n') + os.Stdout.Write(output) + + return +}