github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/remotewrite/client_test.go (about) 1 package remotewrite_test 2 3 import ( 4 "context" 5 "io/ioutil" 6 "net/http" 7 "net/http/httptest" 8 "sync" 9 10 . "github.com/onsi/ginkgo/v2" 11 . "github.com/onsi/gomega" 12 "github.com/prometheus/client_golang/prometheus" 13 "github.com/sirupsen/logrus" 14 15 "github.com/pyroscope-io/pyroscope/pkg/config" 16 "github.com/pyroscope-io/pyroscope/pkg/convert/profile" 17 "github.com/pyroscope-io/pyroscope/pkg/ingestion" 18 "github.com/pyroscope-io/pyroscope/pkg/remotewrite" 19 "github.com/pyroscope-io/pyroscope/pkg/storage/metadata" 20 "github.com/pyroscope-io/pyroscope/pkg/storage/segment" 21 "github.com/pyroscope-io/pyroscope/pkg/util/attime" 22 ) 23 24 // TODO(eh-am): clean up these bunch of putInput 25 26 var _ = Describe("TrafficShadower", func() { 27 var logger *logrus.Logger 28 29 BeforeEach(func() { 30 logger = logrus.New() 31 logger.SetOutput(ioutil.Discard) 32 }) 33 34 Context("happy path", func() { 35 var remoteHandler http.HandlerFunc 36 var wg sync.WaitGroup 37 var cfg config.RemoteWriteTarget 38 var in ingestion.IngestInput 39 40 BeforeEach(func() { 41 remoteHandler = func(w http.ResponseWriter, r *http.Request) {} 42 43 cfg.Address = "" 44 cfg.AuthToken = "" 45 cfg.Tags = make(map[string]string) 46 }) 47 48 run := func() { 49 remoteServer := httptest.NewServer(http.HandlerFunc( 50 func(w http.ResponseWriter, r *http.Request) { 51 remoteHandler(w, r) 52 wg.Done() 53 }), 54 ) 55 56 cfg.Address = remoteServer.URL 57 client := remotewrite.NewClient(logger, prometheus.NewRegistry(), "targetName", cfg) 58 59 wg.Add(1) 60 client.Ingest(context.TODO(), &in) 61 wg.Wait() 62 } 63 64 It("sends request to remote", func() { 65 in = ingestion.IngestInput{ 66 Metadata: ingestion.Metadata{ 67 Key: segment.NewKey(map[string]string{ 68 "__name__": "myapp", 69 }), 70 71 StartTime: attime.Parse("1654110240"), 72 EndTime: attime.Parse("1654110250"), 73 SampleRate: 100, 74 SpyName: "gospy", 75 Units: metadata.SamplesUnits, 76 AggregationType: metadata.SumAggregationType, 77 }, 78 79 Profile: new(profile.RawProfile), 80 Format: ingestion.FormatGroups, 81 } 82 83 remoteHandler = func(w http.ResponseWriter, r *http.Request) { 84 defer GinkgoRecover() 85 86 Expect(r.URL.Query().Get("name")).To(Equal("myapp{}")) 87 Expect(r.URL.Query().Get("from")).To(Equal("1654110240")) 88 Expect(r.URL.Query().Get("until")).To(Equal("1654110250")) 89 Expect(r.URL.Query().Get("sampleRate")).To(Equal("100")) 90 Expect(r.URL.Query().Get("spyName")).To(Equal("gospy")) 91 Expect(r.URL.Query().Get("units")).To(Equal("samples")) 92 Expect(r.URL.Query().Get("aggregationType")).To(Equal("sum")) 93 Expect(r.URL.Query().Get("format")).To(Equal(string(ingestion.FormatGroups))) 94 } 95 96 run() 97 }) 98 99 When("auth is configured", func() { 100 BeforeEach(func() { 101 cfg.AuthToken = "myauthtoken" 102 }) 103 104 It("sets the Authorization header", func() { 105 in = ingestion.IngestInput{ 106 Metadata: ingestion.Metadata{ 107 Key: segment.NewKey(map[string]string{ 108 "__name__": "myapp", 109 "my": "tag", 110 }), 111 112 StartTime: attime.Parse("1654110240"), 113 EndTime: attime.Parse("1654110250"), 114 SampleRate: 100, 115 SpyName: "gospy", 116 Units: metadata.SamplesUnits, 117 AggregationType: metadata.SumAggregationType, 118 }, 119 120 Profile: new(profile.RawProfile), 121 } 122 123 remoteHandler = func(w http.ResponseWriter, r *http.Request) { 124 defer GinkgoRecover() 125 126 Expect(r.Header.Get("Authorization")).To(Equal("Bearer myauthtoken")) 127 } 128 129 run() 130 }) 131 }) 132 133 When("tags are configured", func() { 134 BeforeEach(func() { 135 cfg.Tags = make(map[string]string) 136 137 cfg.Tags["minha"] = "tag" 138 cfg.Tags["nuestra"] = "etiqueta" 139 }) 140 141 It("enhances the app name with tags", func() { 142 in = ingestion.IngestInput{ 143 Metadata: ingestion.Metadata{ 144 Key: segment.NewKey(map[string]string{ 145 "__name__": "myapp", 146 "my": "tag", 147 }), 148 149 StartTime: attime.Parse("1654110240"), 150 EndTime: attime.Parse("1654110250"), 151 SampleRate: 100, 152 SpyName: "gospy", 153 Units: metadata.SamplesUnits, 154 AggregationType: metadata.SumAggregationType, 155 }, 156 157 Profile: new(profile.RawProfile), 158 } 159 160 remoteHandler = func(w http.ResponseWriter, r *http.Request) { 161 defer GinkgoRecover() 162 163 key, err := segment.ParseKey(r.URL.Query().Get("name")) 164 Expect(err).NotTo(HaveOccurred()) 165 166 Expect(key).To(Equal( 167 segment.NewKey(map[string]string{ 168 "__name__": "myapp", 169 "my": "tag", 170 "minha": "tag", 171 "nuestra": "etiqueta", 172 }), 173 )) 174 } 175 176 run() 177 }) 178 }) 179 }) 180 181 Context("sad path", func() { 182 When("it can't convert PutInput into a http.Request", func() { 183 It("fails with ErrConvertPutInputToRequest", func() { 184 client := remotewrite.NewClient(logger, prometheus.NewRegistry(), "targetName", 185 config.RemoteWriteTarget{ 186 Address: "%%", 187 }) 188 in := ingestion.IngestInput{ 189 Metadata: ingestion.Metadata{ 190 Key: segment.NewKey(map[string]string{ 191 "__name__": "myapp", 192 }), 193 }, 194 Profile: new(profile.RawProfile), 195 } 196 197 err := client.Ingest(context.TODO(), &in) 198 Expect(err).To(MatchError(remotewrite.ErrConvertPutInputToRequest)) 199 }) 200 }) 201 202 When("it can't send to remote", func() { 203 It("fails with ErrMakingRequest", func() { 204 client := remotewrite.NewClient(logger, prometheus.NewRegistry(), "targetName", 205 config.RemoteWriteTarget{ 206 Address: "//inexistent-url", 207 }) 208 in := ingestion.IngestInput{ 209 Metadata: ingestion.Metadata{ 210 Key: segment.NewKey(map[string]string{ 211 "__name__": "myapp", 212 "my": "tag", 213 }), 214 215 StartTime: attime.Parse("1654110240"), 216 EndTime: attime.Parse("1654110250"), 217 SampleRate: 100, 218 SpyName: "gospy", 219 Units: metadata.SamplesUnits, 220 AggregationType: metadata.SumAggregationType, 221 }, 222 223 Profile: new(profile.RawProfile), 224 } 225 226 err := client.Ingest(context.TODO(), &in) 227 Expect(err).To(MatchError(remotewrite.ErrMakingRequest)) 228 }) 229 }) 230 231 When("response is not within the 2xx range", func() { 232 It("fails with ErrNotOkResponse", func() { 233 remoteServer := httptest.NewServer(http.HandlerFunc( 234 func(w http.ResponseWriter, r *http.Request) { 235 w.WriteHeader(500) 236 }), 237 ) 238 239 client := remotewrite.NewClient(logger, prometheus.NewRegistry(), "targetName", 240 config.RemoteWriteTarget{ 241 Address: remoteServer.URL, 242 }) 243 in := ingestion.IngestInput{ 244 Metadata: ingestion.Metadata{ 245 Key: segment.NewKey(map[string]string{ 246 "__name__": "myapp", 247 "my": "tag", 248 }), 249 250 StartTime: attime.Parse("1654110240"), 251 EndTime: attime.Parse("1654110250"), 252 SampleRate: 100, 253 SpyName: "gospy", 254 Units: metadata.SamplesUnits, 255 AggregationType: metadata.SumAggregationType, 256 }, 257 258 Profile: new(profile.RawProfile), 259 } 260 261 err := client.Ingest(context.TODO(), &in) 262 Expect(err).To(MatchError(remotewrite.ErrNotOkResponse)) 263 }) 264 }) 265 }) 266 })