Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/integrations/v2/app_agent_receiver/handler_test.go
5333 views
1
package app_agent_receiver
2
3
import (
4
"bytes"
5
"context"
6
"errors"
7
"net/http"
8
"net/http/httptest"
9
"testing"
10
11
"github.com/go-kit/log"
12
"github.com/stretchr/testify/require"
13
14
"github.com/prometheus/client_golang/prometheus"
15
)
16
17
const PAYLOAD = `
18
{
19
"traces": {
20
"resourceSpans": []
21
},
22
"logs": [],
23
"exceptions": [],
24
"measurements": [],
25
"meta": {}
26
}
27
`
28
29
type TestExporter struct {
30
name string
31
broken bool
32
payloads []Payload
33
}
34
35
func (te *TestExporter) Name() string {
36
return te.name
37
}
38
39
func (te *TestExporter) Export(ctx context.Context, payload Payload) error {
40
if te.broken {
41
return errors.New("this exporter is broken")
42
}
43
te.payloads = append(te.payloads, payload)
44
return nil
45
}
46
47
func TestMultipleExportersAllSucceed(t *testing.T) {
48
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
49
50
reg := prometheus.NewRegistry()
51
52
require.NoError(t, err)
53
54
exporter1 := TestExporter{
55
name: "exporter1",
56
broken: false,
57
payloads: []Payload{},
58
}
59
exporter2 := TestExporter{
60
name: "exporter2",
61
broken: false,
62
payloads: []Payload{},
63
}
64
65
conf := &Config{}
66
67
fr := NewAppAgentReceiverHandler(conf, []appAgentReceiverExporter{&exporter1, &exporter2}, reg)
68
handler := fr.HTTPHandler(log.NewNopLogger())
69
70
rr := httptest.NewRecorder()
71
72
handler.ServeHTTP(rr, req)
73
74
require.Equal(t, http.StatusAccepted, rr.Result().StatusCode)
75
76
require.Len(t, exporter1.payloads, 1)
77
require.Len(t, exporter2.payloads, 1)
78
}
79
80
func TestMultipleExportersOneFails(t *testing.T) {
81
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
82
83
require.NoError(t, err)
84
85
reg := prometheus.NewRegistry()
86
87
exporter1 := TestExporter{
88
name: "exporter1",
89
broken: true,
90
payloads: []Payload{},
91
}
92
exporter2 := TestExporter{
93
name: "exporter2",
94
broken: false,
95
payloads: []Payload{},
96
}
97
98
conf := &Config{}
99
100
fr := NewAppAgentReceiverHandler(conf, []appAgentReceiverExporter{&exporter1, &exporter2}, reg)
101
handler := fr.HTTPHandler(log.NewNopLogger())
102
103
rr := httptest.NewRecorder()
104
105
handler.ServeHTTP(rr, req)
106
107
metrics, err := reg.Gather()
108
require.NoError(t, err)
109
110
metric := metrics[0]
111
require.Equal(t, "app_agent_receiver_exporter_errors_total", *metric.Name)
112
require.Len(t, metric.Metric, 1)
113
require.Equal(t, 1.0, *metric.Metric[0].Counter.Value)
114
require.Len(t, metric.Metric[0].Label, 1)
115
require.Equal(t, *metric.Metric[0].Label[0].Value, "exporter1")
116
require.Len(t, metrics, 1)
117
require.Equal(t, http.StatusAccepted, rr.Result().StatusCode)
118
require.Len(t, exporter1.payloads, 0)
119
require.Len(t, exporter2.payloads, 1)
120
}
121
122
func TestMultipleExportersAllFail(t *testing.T) {
123
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
124
125
reg := prometheus.NewRegistry()
126
127
require.NoError(t, err)
128
129
exporter1 := TestExporter{
130
name: "exporter1",
131
broken: true,
132
payloads: []Payload{},
133
}
134
exporter2 := TestExporter{
135
name: "exporter2",
136
broken: true,
137
payloads: []Payload{},
138
}
139
140
conf := &Config{}
141
142
fr := NewAppAgentReceiverHandler(conf, []appAgentReceiverExporter{&exporter1, &exporter2}, reg)
143
handler := fr.HTTPHandler(log.NewNopLogger())
144
145
rr := httptest.NewRecorder()
146
147
handler.ServeHTTP(rr, req)
148
149
metrics, err := reg.Gather()
150
require.NoError(t, err)
151
152
require.Len(t, metrics, 1)
153
metric := metrics[0]
154
155
require.Equal(t, "app_agent_receiver_exporter_errors_total", *metric.Name)
156
require.Len(t, metric.Metric, 2)
157
require.Equal(t, 1.0, *metric.Metric[0].Counter.Value)
158
require.Equal(t, 1.0, *metric.Metric[1].Counter.Value)
159
require.Len(t, metric.Metric[0].Label, 1)
160
require.Len(t, metric.Metric[1].Label, 1)
161
require.Equal(t, *metric.Metric[0].Label[0].Value, "exporter1")
162
require.Equal(t, *metric.Metric[1].Label[0].Value, "exporter2")
163
require.Equal(t, http.StatusAccepted, rr.Result().StatusCode)
164
require.Len(t, exporter1.payloads, 0)
165
require.Len(t, exporter2.payloads, 0)
166
}
167
168
func TestNoContentLengthLimitSet(t *testing.T) {
169
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
170
require.NoError(t, err)
171
reg := prometheus.NewRegistry()
172
173
conf := &Config{}
174
175
req.ContentLength = 89348593894
176
177
fr := NewAppAgentReceiverHandler(conf, []appAgentReceiverExporter{}, reg)
178
handler := fr.HTTPHandler(nil)
179
180
rr := httptest.NewRecorder()
181
182
handler.ServeHTTP(rr, req)
183
184
require.Equal(t, http.StatusAccepted, rr.Result().StatusCode)
185
}
186
187
func TestLargePayload(t *testing.T) {
188
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
189
require.NoError(t, err)
190
reg := prometheus.NewRegistry()
191
192
conf := &Config{
193
Server: ServerConfig{
194
MaxAllowedPayloadSize: 10,
195
},
196
}
197
198
fr := NewAppAgentReceiverHandler(conf, []appAgentReceiverExporter{}, reg)
199
handler := fr.HTTPHandler(nil)
200
201
rr := httptest.NewRecorder()
202
203
handler.ServeHTTP(rr, req)
204
require.Equal(t, http.StatusRequestEntityTooLarge, rr.Result().StatusCode)
205
}
206
207
func TestAPIKeyRequiredButNotProvided(t *testing.T) {
208
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
209
210
if err != nil {
211
t.Fatal(err)
212
}
213
214
conf := &Config{
215
Server: ServerConfig{
216
APIKey: "foo",
217
},
218
}
219
220
fr := NewAppAgentReceiverHandler(conf, nil, prometheus.NewRegistry())
221
handler := fr.HTTPHandler(nil)
222
223
rr := httptest.NewRecorder()
224
225
handler.ServeHTTP(rr, req)
226
require.Equal(t, http.StatusUnauthorized, rr.Result().StatusCode)
227
}
228
229
func TestAPIKeyWrong(t *testing.T) {
230
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
231
req.Header.Set("x-api-key", "bar")
232
233
if err != nil {
234
t.Fatal(err)
235
}
236
237
conf := &Config{
238
Server: ServerConfig{
239
APIKey: "foo",
240
},
241
}
242
243
fr := NewAppAgentReceiverHandler(conf, nil, prometheus.NewRegistry())
244
handler := fr.HTTPHandler(nil)
245
246
rr := httptest.NewRecorder()
247
248
handler.ServeHTTP(rr, req)
249
require.Equal(t, http.StatusUnauthorized, rr.Result().StatusCode)
250
}
251
252
func TestAPIKeyCorrect(t *testing.T) {
253
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
254
req.Header.Set("x-api-key", "foo")
255
256
if err != nil {
257
t.Fatal(err)
258
}
259
260
conf := &Config{
261
Server: ServerConfig{
262
APIKey: "foo",
263
},
264
}
265
266
fr := NewAppAgentReceiverHandler(conf, nil, prometheus.NewRegistry())
267
handler := fr.HTTPHandler(nil)
268
269
rr := httptest.NewRecorder()
270
271
handler.ServeHTTP(rr, req)
272
require.Equal(t, http.StatusAccepted, rr.Result().StatusCode)
273
}
274
275
func TestRateLimiterNoReject(t *testing.T) {
276
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
277
278
if err != nil {
279
t.Fatal(err)
280
}
281
282
conf := &Config{
283
Server: ServerConfig{
284
RateLimiting: RateLimitingConfig{
285
Burstiness: 10,
286
RPS: 10,
287
Enabled: true,
288
},
289
},
290
}
291
292
fr := NewAppAgentReceiverHandler(conf, nil, prometheus.NewRegistry())
293
handler := fr.HTTPHandler(nil)
294
295
rr := httptest.NewRecorder()
296
297
handler.ServeHTTP(rr, req)
298
require.Equal(t, http.StatusAccepted, rr.Result().StatusCode)
299
}
300
301
func TestRateLimiterReject(t *testing.T) {
302
conf := &Config{
303
Server: ServerConfig{
304
RateLimiting: RateLimitingConfig{
305
Burstiness: 2,
306
RPS: 1,
307
Enabled: true,
308
},
309
},
310
}
311
312
fr := NewAppAgentReceiverHandler(conf, nil, prometheus.NewRegistry())
313
handler := fr.HTTPHandler(nil)
314
315
makeRequest := func() *httptest.ResponseRecorder {
316
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
317
require.NoError(t, err)
318
rr := httptest.NewRecorder()
319
handler.ServeHTTP(rr, req)
320
return rr
321
}
322
323
r1 := makeRequest()
324
r2 := makeRequest()
325
r3 := makeRequest()
326
327
require.Equal(t, http.StatusAccepted, r1.Result().StatusCode)
328
require.Equal(t, http.StatusAccepted, r2.Result().StatusCode)
329
require.Equal(t, http.StatusTooManyRequests, r3.Result().StatusCode)
330
}
331
332
func TestRateLimiterDisabled(t *testing.T) {
333
req, err := http.NewRequest("POST", "/collect", bytes.NewBuffer([]byte(PAYLOAD)))
334
335
if err != nil {
336
t.Fatal(err)
337
}
338
339
conf := &Config{
340
Server: ServerConfig{
341
RateLimiting: RateLimitingConfig{
342
Burstiness: 0,
343
RPS: 0,
344
Enabled: false,
345
},
346
},
347
}
348
349
fr := NewAppAgentReceiverHandler(conf, nil, prometheus.NewRegistry())
350
handler := fr.HTTPHandler(nil)
351
352
rr := httptest.NewRecorder()
353
354
handler.ServeHTTP(rr, req)
355
require.Equal(t, http.StatusAccepted, rr.Result().StatusCode)
356
}
357
358