github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/metrics/graphite.go (about) 1 package metrics 2 3 import ( 4 "bufio" 5 "fmt" 6 "log" 7 "net" 8 "strconv" 9 "strings" 10 "time" 11 ) 12 13 type GraphiteConfig struct { 14 Addr *net.TCPAddr 15 Registry Registry 16 FlushInterval time.Duration 17 DurationUnit time.Duration 18 Prefix string 19 Percentiles []float64 20 } 21 22 func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { 23 GraphiteWithConfig(GraphiteConfig{ 24 Addr: addr, 25 Registry: r, 26 FlushInterval: d, 27 DurationUnit: time.Nanosecond, 28 Prefix: prefix, 29 Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999}, 30 }) 31 } 32 33 func GraphiteWithConfig(c GraphiteConfig) { 34 35 for range time.Tick(c.FlushInterval) { 36 if err := graphite(&c); nil != err { 37 log.Println(err) 38 } 39 } 40 } 41 42 func GraphiteOnce(c GraphiteConfig) error { 43 44 return graphite(&c) 45 } 46 47 func graphite(c *GraphiteConfig) error { 48 now := time.Now().Unix() 49 du := float64(c.DurationUnit) 50 conn, err := net.DialTCP("tcp", nil, c.Addr) 51 if nil != err { 52 return err 53 } 54 defer conn.Close() 55 w := bufio.NewWriter(conn) 56 c.Registry.Each(func(name string, i interface{}) { 57 switch metric := i.(type) { 58 case Counter: 59 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now) 60 case Gauge: 61 fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) 62 case GaugeFloat64: 63 fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) 64 case Histogram: 65 h := metric.Snapshot() 66 ps := h.Percentiles(c.Percentiles) 67 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now) 68 fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now) 69 fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now) 70 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now) 71 fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now) 72 for psIdx, psKey := range c.Percentiles { 73 key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) 74 fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) 75 } 76 case Meter: 77 m := metric.Snapshot() 78 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now) 79 fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now) 80 fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now) 81 fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now) 82 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now) 83 case Timer: 84 t := metric.Snapshot() 85 ps := t.Percentiles(c.Percentiles) 86 fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now) 87 fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now) 88 fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now) 89 fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now) 90 fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now) 91 for psIdx, psKey := range c.Percentiles { 92 key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) 93 fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) 94 } 95 fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now) 96 fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now) 97 fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now) 98 fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now) 99 } 100 w.Flush() 101 }) 102 return nil 103 }