bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/tsdbrelay/integrationTest/main.go (about) 1 /* 2 We are going to simulate a full multi-datacenter cluster: 3 DC1: 4 - tsdbrelay: :5555 5 - opentsdb: :5556 6 - bosun: :5557 7 DC2: 8 - tsdbrelay :6555 9 - opentsdb :6556 10 - bosun: :6557 11 */ 12 package main 13 14 import ( 15 "bytes" 16 "compress/gzip" 17 "encoding/json" 18 "fmt" 19 "io" 20 "log" 21 "net/http" 22 "os" 23 "os/exec" 24 "os/signal" 25 "time" 26 27 "bosun.org/metadata" 28 "bosun.org/models" 29 "bosun.org/opentsdb" 30 ) 31 32 var ( 33 relay1, relay2 *os.Process 34 gotMeta1, gotMeta2 bool 35 ) 36 37 func init() { 38 cmd := exec.Command("tsdbrelay", "-l=:5555", "-b=localhost:5557", "-r=localhost:6555", "-t=localhost:5556", "-denormalize=os.cpu__host") 39 cmd.Stdout = os.Stdout 40 cmd.Stderr = os.Stderr 41 err := cmd.Start() 42 if err != nil { 43 fatal(err) 44 } 45 relay1 = cmd.Process 46 cmd = exec.Command("tsdbrelay", "-l=:6555", "-b=localhost:6557", "-r=localhost:5555", "-t=localhost:6556", "-denormalize=os.cpu__host") 47 cmd.Stdout = os.Stdout 48 cmd.Stderr = os.Stderr 49 err = cmd.Start() 50 if err != nil { 51 fatal(err) 52 } 53 relay2 = cmd.Process 54 dc1BosunMux := http.NewServeMux() 55 dc1BosunMux.HandleFunc("/api/index", handleBosun(dc1BosunReceived)) 56 dc1BosunMux.HandleFunc("/api/metadata/put", handleMeta(&gotMeta1)) 57 go func() { 58 fatal("DC1-Bosun", http.ListenAndServe(":5557", dc1BosunMux)) 59 }() 60 61 dc2BosunMux := http.NewServeMux() 62 dc2BosunMux.HandleFunc("/api/index", handleBosun(dc2BosunReceived)) 63 dc2BosunMux.HandleFunc("/api/metadata/put", handleMeta(&gotMeta2)) 64 go func() { 65 fatal("DC2-Bosun", http.ListenAndServe(":6557", dc2BosunMux)) 66 }() 67 68 dc1TsdbMux := http.NewServeMux() 69 dc1TsdbMux.HandleFunc("/api/put", handleTsdb(dc1TsdbReceived)) 70 71 go func() { 72 fatal("DC1-TSDB", http.ListenAndServe(":5556", dc1TsdbMux)) 73 }() 74 75 dc2TsdbMux := http.NewServeMux() 76 dc2TsdbMux.HandleFunc("/api/put", handleTsdb(dc2TsdbReceived)) 77 go func() { 78 fatal("DC3-TSDB", http.ListenAndServe(":6556", dc2TsdbMux)) 79 }() 80 81 ch := make(chan os.Signal) 82 signal.Notify(ch, os.Kill, os.Interrupt) 83 go func() { 84 <-ch 85 fatal("INTERRUPT RECIEVED") 86 }() 87 time.Sleep(2 * time.Second) 88 } 89 90 const ( 91 localRelayUrl = "http://localhost:5555/api/put" 92 remoteRelayUrl = "http://localhost:6555/api/put" 93 ) 94 95 var ( 96 dc1BosunReceived = map[models.AlertKey]int{} 97 dc2BosunReceived = map[models.AlertKey]int{} 98 dc1TsdbReceived = map[models.AlertKey]int{} 99 dc2TsdbReceived = map[models.AlertKey]int{} 100 ) 101 102 func main() { 103 // 1. Single data point to local relay 104 dp1 := &opentsdb.DataPoint{Metric: "abc", Tags: opentsdb.TagSet{"host": "h1"}} 105 buf := encodeMdp([]*opentsdb.DataPoint{dp1}) 106 resp, err := http.Post(localRelayUrl, "application/json", buf) 107 if err != nil { 108 fatal(err) 109 } 110 if resp.StatusCode != 204 { 111 fatal("response code not relayed") 112 } 113 time.Sleep(1 * time.Second) 114 check("Bosun DC1", "abc{host=h1}", 1, dc1BosunReceived) 115 check("Bosun DC2", "abc{host=h1}", 1, dc2BosunReceived) 116 check("Tsdb DC1", "abc{host=h1}", 1, dc1TsdbReceived) 117 check("Tsdb DC2", "abc{host=h1}", 1, dc2TsdbReceived) 118 log.Println("test 1 ok") 119 // 2. Single data point to remote relay. Should be denormalized. 120 dp2 := &opentsdb.DataPoint{Metric: "os.cpu", Tags: opentsdb.TagSet{"host": "h1"}} 121 buf = encodeMdp([]*opentsdb.DataPoint{dp2}) 122 resp, err = http.Post(remoteRelayUrl, "application/json", buf) 123 if err != nil { 124 fatal(err) 125 } 126 if resp.StatusCode != 204 { 127 fatal("response code not relayed") 128 } 129 time.Sleep(1 * time.Second) 130 check("Bosun DC1", "os.cpu{host=h1}", 1, dc1BosunReceived) 131 check("Bosun DC2", "os.cpu{host=h1}", 1, dc2BosunReceived) 132 check("Tsdb DC1", "os.cpu{host=h1}", 1, dc1TsdbReceived) 133 check("Tsdb DC2", "os.cpu{host=h1}", 1, dc2TsdbReceived) 134 check("Bosun DC1", "__h1.os.cpu{host=h1}", 1, dc1BosunReceived) 135 check("Bosun DC2", "__h1.os.cpu{host=h1}", 1, dc2BosunReceived) 136 check("Tsdb DC1", "__h1.os.cpu{host=h1}", 1, dc1TsdbReceived) 137 check("Tsdb DC2", "__h1.os.cpu{host=h1}", 1, dc2TsdbReceived) 138 log.Println("test 2 ok") 139 140 metas := []metadata.Metasend{ 141 {Metric: "foo", Name: "desc", Value: 42}, 142 } 143 b, _ := json.Marshal(metas) 144 http.Post("http://localhost:5555/api/metadata/put", "application/json", bytes.NewReader(b)) 145 time.Sleep(1 * time.Second) 146 if !gotMeta1 || !gotMeta2 { 147 fatal("Didn't get metadata in both datacenters. ", gotMeta1, gotMeta2) 148 } 149 killAll() 150 } 151 func check(node string, ak models.AlertKey, expected int, data map[models.AlertKey]int) { 152 if data[ak] != expected { 153 msg := fmt.Sprintf("Expected %s to see %s %d times, but saw %d.", node, ak, expected, data[ak]) 154 fatal(msg) 155 } 156 } 157 158 func handleBosun(data map[models.AlertKey]int) http.HandlerFunc { 159 return func(w http.ResponseWriter, r *http.Request) { 160 readDps(r.Body, data) 161 w.WriteHeader(500) 162 } 163 } 164 165 func handleMeta(result *bool) http.HandlerFunc { 166 return func(w http.ResponseWriter, r *http.Request) { 167 *result = true 168 } 169 } 170 171 func handleTsdb(data map[models.AlertKey]int) http.HandlerFunc { 172 return func(w http.ResponseWriter, r *http.Request) { 173 readDps(r.Body, data) 174 w.WriteHeader(204) 175 } 176 } 177 178 func killAll() { 179 if relay1 != nil { 180 log.Println("Killing relay 1:", relay1.Kill()) 181 } 182 if relay2 != nil { 183 log.Println("Killing relay 2:", relay2.Kill()) 184 } 185 } 186 func readDps(r io.Reader, data map[models.AlertKey]int) { 187 gr, err := gzip.NewReader(r) 188 if err != nil { 189 fatal(err) 190 } 191 jr := json.NewDecoder(gr) 192 mdp := []*opentsdb.DataPoint{} 193 err = jr.Decode(&mdp) 194 if err != nil { 195 fatal(err) 196 } 197 for _, dp := range mdp { 198 ak := models.NewAlertKey(dp.Metric, dp.Tags) 199 n, ok := data[ak] 200 if ok { 201 data[ak] = n + 1 202 } else { 203 data[ak] = 1 204 } 205 } 206 } 207 208 func encodeMdp(mdp []*opentsdb.DataPoint) io.Reader { 209 buf := &bytes.Buffer{} 210 gw := gzip.NewWriter(buf) 211 jw := json.NewEncoder(gw) 212 jw.Encode(mdp) 213 gw.Close() 214 return buf 215 } 216 217 func fatal(i ...interface{}) { 218 log.Println(i...) 219 killAll() 220 log.Fatal("") 221 }