1package csm
2
3import (
4	"fmt"
5	"strings"
6	"sync"
7)
8
9var (
10	lock sync.Mutex
11)
12
13const (
14	// DefaultPort is used when no port is specified.
15	DefaultPort = "31000"
16
17	// DefaultHost is the host that will be used when none is specified.
18	DefaultHost = "127.0.0.1"
19)
20
21// AddressWithDefaults returns a CSM address built from the host and port
22// values. If the host or port is not set, default values will be used
23// instead. If host is "localhost" it will be replaced with "127.0.0.1".
24func AddressWithDefaults(host, port string) string {
25	if len(host) == 0 || strings.EqualFold(host, "localhost") {
26		host = DefaultHost
27	}
28
29	if len(port) == 0 {
30		port = DefaultPort
31	}
32
33	// Only IP6 host can contain a colon
34	if strings.Contains(host, ":") {
35		return "[" + host + "]:" + port
36	}
37
38	return host + ":" + port
39}
40
41// Start will start a long running go routine to capture
42// client side metrics. Calling start multiple time will only
43// start the metric listener once and will panic if a different
44// client ID or port is passed in.
45//
46//		r, err := csm.Start("clientID", "127.0.0.1:31000")
47//		if err != nil {
48//			panic(fmt.Errorf("expected no error, but received %v", err))
49//		}
50//		sess := session.NewSession()
51//		r.InjectHandlers(sess.Handlers)
52//
53//		svc := s3.New(sess)
54//		out, err := svc.GetObject(&s3.GetObjectInput{
55//			Bucket: aws.String("bucket"),
56//			Key: aws.String("key"),
57//		})
58func Start(clientID string, url string) (*Reporter, error) {
59	lock.Lock()
60	defer lock.Unlock()
61
62	if sender == nil {
63		sender = newReporter(clientID, url)
64	} else {
65		if sender.clientID != clientID {
66			panic(fmt.Errorf("inconsistent client IDs. %q was expected, but received %q", sender.clientID, clientID))
67		}
68
69		if sender.url != url {
70			panic(fmt.Errorf("inconsistent URLs. %q was expected, but received %q", sender.url, url))
71		}
72	}
73
74	if err := connect(url); err != nil {
75		sender = nil
76		return nil, err
77	}
78
79	return sender, nil
80}
81
82// Get will return a reporter if one exists, if one does not exist, nil will
83// be returned.
84func Get() *Reporter {
85	lock.Lock()
86	defer lock.Unlock()
87
88	return sender
89}
90