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  }