1package statsd
2
3import (
4	"errors"
5	"fmt"
6	"net"
7	"os"
8	"time"
9)
10
11const (
12	autoHostEnvName = "DD_AGENT_HOST"
13	autoPortEnvName = "DD_DOGSTATSD_PORT"
14	defaultUDPPort  = "8125"
15)
16
17// udpWriter is an internal class wrapping around management of UDP connection
18type udpWriter struct {
19	conn net.Conn
20}
21
22// New returns a pointer to a new udpWriter given an addr in the format "hostname:port".
23func newUDPWriter(addr string) (*udpWriter, error) {
24	if addr == "" {
25		addr = addressFromEnvironment()
26	}
27	if addr == "" {
28		return nil, errors.New("No address passed and autodetection from environment failed")
29	}
30
31	udpAddr, err := net.ResolveUDPAddr("udp", addr)
32	if err != nil {
33		return nil, err
34	}
35	conn, err := net.DialUDP("udp", nil, udpAddr)
36	if err != nil {
37		return nil, err
38	}
39	writer := &udpWriter{conn: conn}
40	return writer, nil
41}
42
43// SetWriteTimeout is not needed for UDP, returns error
44func (w *udpWriter) SetWriteTimeout(d time.Duration) error {
45	return errors.New("SetWriteTimeout: not supported for UDP connections")
46}
47
48// Write data to the UDP connection with no error handling
49func (w *udpWriter) Write(data []byte) (int, error) {
50	return w.conn.Write(data)
51}
52
53func (w *udpWriter) Close() error {
54	return w.conn.Close()
55}
56
57func (w *udpWriter) remoteAddr() net.Addr {
58	return w.conn.RemoteAddr()
59}
60
61func addressFromEnvironment() string {
62	autoHost := os.Getenv(autoHostEnvName)
63	if autoHost == "" {
64		return ""
65	}
66
67	autoPort := os.Getenv(autoPortEnvName)
68	if autoPort == "" {
69		autoPort = defaultUDPPort
70	}
71
72	return fmt.Sprintf("%s:%s", autoHost, autoPort)
73}
74