|
|
|
|
@ -18,6 +18,7 @@ import ( |
|
|
|
|
"context" |
|
|
|
|
"fmt" |
|
|
|
|
"io" |
|
|
|
|
"math" |
|
|
|
|
"net/http" |
|
|
|
|
"net/http/httptest" |
|
|
|
|
"strconv" |
|
|
|
|
@ -87,73 +88,127 @@ func TestRemoteWriteHandler(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestOutOfOrderSample(t *testing.T) { |
|
|
|
|
buf, _, _, err := buildWriteRequest(nil, []prompb.TimeSeries{{ |
|
|
|
|
Labels: []prompb.Label{{Name: "__name__", Value: "test_metric"}}, |
|
|
|
|
Samples: []prompb.Sample{{Value: 1, Timestamp: 0}}, |
|
|
|
|
}}, nil, nil, nil, nil) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
tests := []struct { |
|
|
|
|
Name string |
|
|
|
|
Timestamp int64 |
|
|
|
|
}{ |
|
|
|
|
{ |
|
|
|
|
Name: "historic", |
|
|
|
|
Timestamp: 0, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
Name: "future", |
|
|
|
|
Timestamp: math.MaxInt64, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
req, err := http.NewRequest("", "", bytes.NewReader(buf)) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
for _, tc := range tests { |
|
|
|
|
t.Run(tc.Name, func(t *testing.T) { |
|
|
|
|
buf, _, _, err := buildWriteRequest(nil, []prompb.TimeSeries{{ |
|
|
|
|
Labels: []prompb.Label{{Name: "__name__", Value: "test_metric"}}, |
|
|
|
|
Samples: []prompb.Sample{{Value: 1, Timestamp: tc.Timestamp}}, |
|
|
|
|
}}, nil, nil, nil, nil) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
appendable := &mockAppendable{ |
|
|
|
|
latestSample: 100, |
|
|
|
|
} |
|
|
|
|
handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) |
|
|
|
|
req, err := http.NewRequest("", "", bytes.NewReader(buf)) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
recorder := httptest.NewRecorder() |
|
|
|
|
handler.ServeHTTP(recorder, req) |
|
|
|
|
appendable := &mockAppendable{ |
|
|
|
|
latestSample: 100, |
|
|
|
|
} |
|
|
|
|
handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) |
|
|
|
|
|
|
|
|
|
resp := recorder.Result() |
|
|
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
|
|
|
|
recorder := httptest.NewRecorder() |
|
|
|
|
handler.ServeHTTP(recorder, req) |
|
|
|
|
|
|
|
|
|
resp := recorder.Result() |
|
|
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This test case currently aims to verify that the WriteHandler endpoint
|
|
|
|
|
// don't fail on ingestion errors since the exemplar storage is
|
|
|
|
|
// still experimental.
|
|
|
|
|
func TestOutOfOrderExemplar(t *testing.T) { |
|
|
|
|
buf, _, _, err := buildWriteRequest(nil, []prompb.TimeSeries{{ |
|
|
|
|
Labels: []prompb.Label{{Name: "__name__", Value: "test_metric"}}, |
|
|
|
|
Exemplars: []prompb.Exemplar{{Labels: []prompb.Label{{Name: "foo", Value: "bar"}}, Value: 1, Timestamp: 0}}, |
|
|
|
|
}}, nil, nil, nil, nil) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
tests := []struct { |
|
|
|
|
Name string |
|
|
|
|
Timestamp int64 |
|
|
|
|
}{ |
|
|
|
|
{ |
|
|
|
|
Name: "historic", |
|
|
|
|
Timestamp: 0, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
Name: "future", |
|
|
|
|
Timestamp: math.MaxInt64, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
req, err := http.NewRequest("", "", bytes.NewReader(buf)) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
for _, tc := range tests { |
|
|
|
|
t.Run(tc.Name, func(t *testing.T) { |
|
|
|
|
buf, _, _, err := buildWriteRequest(nil, []prompb.TimeSeries{{ |
|
|
|
|
Labels: []prompb.Label{{Name: "__name__", Value: "test_metric"}}, |
|
|
|
|
Exemplars: []prompb.Exemplar{{Labels: []prompb.Label{{Name: "foo", Value: "bar"}}, Value: 1, Timestamp: tc.Timestamp}}, |
|
|
|
|
}}, nil, nil, nil, nil) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
appendable := &mockAppendable{ |
|
|
|
|
latestExemplar: 100, |
|
|
|
|
} |
|
|
|
|
handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) |
|
|
|
|
req, err := http.NewRequest("", "", bytes.NewReader(buf)) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
recorder := httptest.NewRecorder() |
|
|
|
|
handler.ServeHTTP(recorder, req) |
|
|
|
|
appendable := &mockAppendable{ |
|
|
|
|
latestExemplar: 100, |
|
|
|
|
} |
|
|
|
|
handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) |
|
|
|
|
|
|
|
|
|
resp := recorder.Result() |
|
|
|
|
// TODO: update to require.Equal(t, http.StatusConflict, resp.StatusCode) once exemplar storage is not experimental.
|
|
|
|
|
require.Equal(t, http.StatusNoContent, resp.StatusCode) |
|
|
|
|
recorder := httptest.NewRecorder() |
|
|
|
|
handler.ServeHTTP(recorder, req) |
|
|
|
|
|
|
|
|
|
resp := recorder.Result() |
|
|
|
|
// TODO: update to require.Equal(t, http.StatusConflict, resp.StatusCode) once exemplar storage is not experimental.
|
|
|
|
|
require.Equal(t, http.StatusNoContent, resp.StatusCode) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestOutOfOrderHistogram(t *testing.T) { |
|
|
|
|
buf, _, _, err := buildWriteRequest(nil, []prompb.TimeSeries{{ |
|
|
|
|
Labels: []prompb.Label{{Name: "__name__", Value: "test_metric"}}, |
|
|
|
|
Histograms: []prompb.Histogram{HistogramToHistogramProto(0, &testHistogram), FloatHistogramToHistogramProto(1, testHistogram.ToFloat(nil))}, |
|
|
|
|
}}, nil, nil, nil, nil) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
tests := []struct { |
|
|
|
|
Name string |
|
|
|
|
Timestamp int64 |
|
|
|
|
}{ |
|
|
|
|
{ |
|
|
|
|
Name: "historic", |
|
|
|
|
Timestamp: 0, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
Name: "future", |
|
|
|
|
Timestamp: math.MaxInt64, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
req, err := http.NewRequest("", "", bytes.NewReader(buf)) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
for _, tc := range tests { |
|
|
|
|
t.Run(tc.Name, func(t *testing.T) { |
|
|
|
|
buf, _, _, err := buildWriteRequest(nil, []prompb.TimeSeries{{ |
|
|
|
|
Labels: []prompb.Label{{Name: "__name__", Value: "test_metric"}}, |
|
|
|
|
Histograms: []prompb.Histogram{HistogramToHistogramProto(tc.Timestamp, &testHistogram), FloatHistogramToHistogramProto(1, testHistogram.ToFloat(nil))}, |
|
|
|
|
}}, nil, nil, nil, nil) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
appendable := &mockAppendable{ |
|
|
|
|
latestHistogram: 100, |
|
|
|
|
} |
|
|
|
|
handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) |
|
|
|
|
req, err := http.NewRequest("", "", bytes.NewReader(buf)) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
recorder := httptest.NewRecorder() |
|
|
|
|
handler.ServeHTTP(recorder, req) |
|
|
|
|
appendable := &mockAppendable{ |
|
|
|
|
latestHistogram: 100, |
|
|
|
|
} |
|
|
|
|
handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) |
|
|
|
|
|
|
|
|
|
resp := recorder.Result() |
|
|
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
|
|
|
|
recorder := httptest.NewRecorder() |
|
|
|
|
handler.ServeHTTP(recorder, req) |
|
|
|
|
|
|
|
|
|
resp := recorder.Result() |
|
|
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func BenchmarkRemoteWritehandler(b *testing.B) { |
|
|
|
|
|