github.com/anycable/anycable-go@v1.5.1/metrics/statsd_writer_test.go (about) 1 package metrics 2 3 import ( 4 "log/slog" 5 "net" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestStatsdWriter(t *testing.T) { 13 m := NewMetrics(nil, 0, slog.Default()) 14 15 m.RegisterCounter("test_count", "") 16 m.RegisterGauge("test_gauge", "") 17 18 for i := 0; i < 10; i++ { 19 m.Counter("test_count").Inc() 20 } 21 22 m.Gauge("test_gauge").Set(123) 23 24 socket, received := startServer(t) 25 defer socket.Close() 26 27 t.Run("Write send UDP with metrics", func(t *testing.T) { 28 c := NewStatsdConfig() 29 c.Host = socket.LocalAddr().String() 30 w := NewStatsdWriter(c, nil, slog.Default()) 31 _ = w.Run(0) 32 defer w.Stop() 33 34 err := w.Write(m) 35 assert.NoError(t, err) 36 37 var buf []byte 38 39 select { 40 case buf = <-received: 41 case <-time.After(time.Second): 42 t.Error("timeout waiting for UDP payload") 43 return 44 } 45 46 payload := string(buf) 47 48 assert.Contains(t, payload, "anycable_go.test_count:10|c") 49 assert.Contains(t, payload, "anycable_go.test_gauge:123|g") 50 }) 51 52 t.Run("Write uses custom prefix", func(t *testing.T) { 53 c := NewStatsdConfig() 54 c.Host = socket.LocalAddr().String() 55 c.Prefix = "ws." 56 w := NewStatsdWriter(c, nil, slog.Default()) 57 _ = w.Run(0) 58 defer w.Stop() 59 60 err := w.Write(m) 61 assert.NoError(t, err) 62 63 var buf []byte 64 65 select { 66 case buf = <-received: 67 case <-time.After(time.Second): 68 t.Error("timeout waiting for UDP payload") 69 return 70 } 71 72 payload := string(buf) 73 74 assert.Contains(t, payload, "ws.test_count:10|c") 75 assert.Contains(t, payload, "ws.test_gauge:123|g") 76 }) 77 78 t.Run("Adds tags in DataDog format", func(t *testing.T) { 79 c := NewStatsdConfig() 80 c.TagFormat = "datadog" 81 c.Host = socket.LocalAddr().String() 82 w := NewStatsdWriter(c, map[string]string{"env": "dev"}, slog.Default()) 83 _ = w.Run(0) 84 defer w.Stop() 85 86 err := w.Write(m) 87 assert.NoError(t, err) 88 89 var buf []byte 90 91 select { 92 case buf = <-received: 93 case <-time.After(time.Second): 94 t.Error("timeout waiting for UDP payload") 95 return 96 } 97 98 payload := string(buf) 99 100 assert.Contains(t, payload, "anycable_go.test_count:10|c|#env:dev") 101 assert.Contains(t, payload, "anycable_go.test_gauge:123|g|#env:dev") 102 }) 103 104 t.Run("Adds multiple tags in DataDog format", func(t *testing.T) { 105 c := NewStatsdConfig() 106 c.TagFormat = "datadog" 107 c.Host = socket.LocalAddr().String() 108 w := NewStatsdWriter(c, map[string]string{"env": "dev", "rev": "1.1"}, slog.Default()) 109 _ = w.Run(0) 110 defer w.Stop() 111 112 err := w.Write(m) 113 assert.NoError(t, err) 114 115 var buf []byte 116 117 select { 118 case buf = <-received: 119 case <-time.After(time.Second): 120 t.Error("timeout waiting for UDP payload") 121 return 122 } 123 124 payload := string(buf) 125 126 assert.Contains(t, payload, "anycable_go.test_count:10|c|#") 127 assert.Contains(t, payload, "anycable_go.test_gauge:123|g|#") 128 assert.Contains(t, payload, "env:dev") 129 assert.Contains(t, payload, "rev:1.1") 130 }) 131 132 t.Run("Adds tags in InfluxDB format", func(t *testing.T) { 133 c := NewStatsdConfig() 134 c.TagFormat = "influxdb" 135 c.Host = socket.LocalAddr().String() 136 w := NewStatsdWriter(c, map[string]string{"env": "dev"}, slog.Default()) 137 _ = w.Run(0) 138 defer w.Stop() 139 140 err := w.Write(m) 141 assert.NoError(t, err) 142 143 var buf []byte 144 145 select { 146 case buf = <-received: 147 case <-time.After(time.Second): 148 t.Error("timeout waiting for UDP payload") 149 return 150 } 151 152 payload := string(buf) 153 154 assert.Contains(t, payload, "anycable_go.test_count,env=dev:10|c") 155 assert.Contains(t, payload, "anycable_go.test_gauge,env=dev:123|g") 156 }) 157 158 t.Run("Adds tags in Graphite format", func(t *testing.T) { 159 c := NewStatsdConfig() 160 c.TagFormat = "graphite" 161 c.Host = socket.LocalAddr().String() 162 w := NewStatsdWriter(c, map[string]string{"env": "dev"}, slog.Default()) 163 _ = w.Run(0) 164 defer w.Stop() 165 166 err := w.Write(m) 167 assert.NoError(t, err) 168 169 var buf []byte 170 171 select { 172 case buf = <-received: 173 case <-time.After(time.Second): 174 t.Error("timeout waiting for UDP payload") 175 return 176 } 177 178 payload := string(buf) 179 180 assert.Contains(t, payload, "anycable_go.test_count;env=dev:10|c") 181 assert.Contains(t, payload, "anycable_go.test_gauge;env=dev:123|g") 182 }) 183 } 184 185 func startServer(t *testing.T) (*net.UDPConn, chan []byte) { 186 inSocket, err := net.ListenUDP("udp4", &net.UDPAddr{ 187 IP: net.IPv4(127, 0, 0, 1), 188 }) 189 if err != nil { 190 t.Error(err) 191 } 192 193 received := make(chan []byte, 1024) 194 195 go func() { 196 for { 197 buf := make([]byte, 1500) 198 199 n, err := inSocket.Read(buf) 200 if err != nil { 201 return 202 } 203 204 received <- buf[0:n] 205 } 206 207 }() 208 209 return inSocket, received 210 }