| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | // Copyright 2021 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package remote | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2022-04-27 17:24:36 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"net/http/httptest" | 
					
						
							| 
									
										
										
										
											2022-12-09 15:27:56 +08:00
										 |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2023-01-13 21:30:50 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-12 00:17:59 +08:00
										 |  |  | 	"github.com/go-kit/log" | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 22:23:17 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/model/exemplar" | 
					
						
							| 
									
										
											  
											
												Style cleanup of all the changes in sparsehistogram so far
A lot of this code was hacked together, literally during a
hackathon. This commit intends not to change the code substantially,
but just make the code obey the usual style practices.
A (possibly incomplete) list of areas:
* Generally address linter warnings.
* The `pgk` directory is deprecated as per dev-summit. No new packages should
  be added to it. I moved the new `pkg/histogram` package to `model`
  anticipating what's proposed in #9478.
* Make the naming of the Sparse Histogram more consistent. Including
  abbreviations, there were just too many names for it: SparseHistogram,
  Histogram, Histo, hist, his, shs, h. The idea is to call it "Histogram" in
  general. Only add "Sparse" if it is needed to avoid confusion with
  conventional Histograms (which is rare because the TSDB really has no notion
  of conventional Histograms). Use abbreviations only in local scope, and then
  really abbreviate (not just removing three out of seven letters like in
  "Histo"). This is in the spirit of
  https://github.com/golang/go/wiki/CodeReviewComments#variable-names
* Several other minor name changes.
* A lot of formatting of doc comments. For one, following
  https://github.com/golang/go/wiki/CodeReviewComments#comment-sentences
  , but also layout question, anticipating how things will look like
  when rendered by `godoc` (even where `godoc` doesn't render them
  right now because they are for unexported types or not a doc comment
  at all but just a normal code comment - consistency is queen!).
* Re-enabled `TestQueryLog` and `TestEndopints` (they pass now,
  leaving them disabled was presumably an oversight).
* Bucket iterator for histogram.Histogram is now created with a
  method.
* HistogramChunk.iterator now allows iterator recycling. (I think
  @dieterbe only commented it out because he was confused by the
  question in the comment.)
* HistogramAppender.Append panics now because we decided to treat
  staleness marker differently.
Signed-off-by: beorn7 <beorn@grafana.com>
											
										 
											2021-10-09 21:57:07 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/model/histogram" | 
					
						
							| 
									
										
										
										
											2021-11-08 22:23:17 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/model/labels" | 
					
						
							| 
									
										
										
										
											2022-07-19 16:58:52 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/model/metadata" | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/prompb" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/storage" | 
					
						
							| 
									
										
										
										
											2023-01-13 21:30:50 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/tsdb" | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRemoteWriteHandler(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2021-10-30 05:44:40 +08:00
										 |  |  | 	buf, _, err := buildWriteRequest(writeRequestFixture.Timeseries, nil, nil, nil) | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	req, err := http.NewRequest("", "", bytes.NewReader(buf)) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	appendable := &mockAppendable{} | 
					
						
							| 
									
										
										
										
											2022-12-09 15:27:56 +08:00
										 |  |  | 	handler := NewWriteHandler(nil, nil, appendable) | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	recorder := httptest.NewRecorder() | 
					
						
							|  |  |  | 	handler.ServeHTTP(recorder, req) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp := recorder.Result() | 
					
						
							|  |  |  | 	require.Equal(t, http.StatusNoContent, resp.StatusCode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	i := 0 | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 	j := 0 | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | 	k := 0 | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	for _, ts := range writeRequestFixture.Timeseries { | 
					
						
							|  |  |  | 		labels := labelProtosToLabels(ts.Labels) | 
					
						
							|  |  |  | 		for _, s := range ts.Samples { | 
					
						
							|  |  |  | 			require.Equal(t, mockSample{labels, s.Timestamp, s.Value}, appendable.samples[i]) | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for _, e := range ts.Exemplars { | 
					
						
							|  |  |  | 			exemplarLabels := labelProtosToLabels(e.Labels) | 
					
						
							|  |  |  | 			require.Equal(t, mockExemplar{labels, exemplarLabels, e.Timestamp, e.Value}, appendable.exemplars[j]) | 
					
						
							|  |  |  | 			j++ | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for _, hp := range ts.Histograms { | 
					
						
							| 
									
										
										
										
											2023-04-22 02:27:15 +08:00
										 |  |  | 			if hp.IsFloatHistogram() { | 
					
						
							| 
									
										
										
										
											2023-03-28 08:02:20 +08:00
										 |  |  | 				fh := FloatHistogramProtoToFloatHistogram(hp) | 
					
						
							| 
									
										
										
										
											2023-01-13 19:09:20 +08:00
										 |  |  | 				require.Equal(t, mockHistogram{labels, hp.Timestamp, nil, fh}, appendable.histograms[k]) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				h := HistogramProtoToHistogram(hp) | 
					
						
							|  |  |  | 				require.Equal(t, mockHistogram{labels, hp.Timestamp, h, nil}, appendable.histograms[k]) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | 			k++ | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | func TestOutOfOrderSample(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	buf, _, err := buildWriteRequest([]prompb.TimeSeries{{ | 
					
						
							|  |  |  | 		Labels:  []prompb.Label{{Name: "__name__", Value: "test_metric"}}, | 
					
						
							|  |  |  | 		Samples: []prompb.Sample{{Value: 1, Timestamp: 0}}, | 
					
						
							| 
									
										
										
										
											2021-10-30 05:44:40 +08:00
										 |  |  | 	}}, nil, nil, nil) | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	req, err := http.NewRequest("", "", bytes.NewReader(buf)) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	appendable := &mockAppendable{ | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 		latestSample: 100, | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-09 15:27:56 +08:00
										 |  |  | 	handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	recorder := httptest.NewRecorder() | 
					
						
							|  |  |  | 	handler.ServeHTTP(recorder, req) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp := recorder.Result() | 
					
						
							|  |  |  | 	require.Equal(t, http.StatusBadRequest, resp.StatusCode) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | // 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([]prompb.TimeSeries{{ | 
					
						
							|  |  |  | 		Labels:    []prompb.Label{{Name: "__name__", Value: "test_metric"}}, | 
					
						
							|  |  |  | 		Exemplars: []prompb.Exemplar{{Labels: []prompb.Label{{Name: "foo", Value: "bar"}}, Value: 1, Timestamp: 0}}, | 
					
						
							| 
									
										
										
										
											2021-10-30 05:44:40 +08:00
										 |  |  | 	}}, nil, nil, nil) | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	req, err := http.NewRequest("", "", bytes.NewReader(buf)) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	appendable := &mockAppendable{ | 
					
						
							|  |  |  | 		latestExemplar: 100, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-09 15:27:56 +08:00
										 |  |  | 	handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | func TestOutOfOrderHistogram(t *testing.T) { | 
					
						
							|  |  |  | 	buf, _, err := buildWriteRequest([]prompb.TimeSeries{{ | 
					
						
							|  |  |  | 		Labels:     []prompb.Label{{Name: "__name__", Value: "test_metric"}}, | 
					
						
							| 
									
										
										
										
											2023-01-13 19:09:20 +08:00
										 |  |  | 		Histograms: []prompb.Histogram{HistogramToHistogramProto(0, &testHistogram), FloatHistogramToHistogramProto(1, testHistogram.ToFloat())}, | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | 	}}, nil, nil, nil) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	req, err := http.NewRequest("", "", bytes.NewReader(buf)) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	appendable := &mockAppendable{ | 
					
						
							|  |  |  | 		latestHistogram: 100, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-09 15:27:56 +08:00
										 |  |  | 	handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	recorder := httptest.NewRecorder() | 
					
						
							|  |  |  | 	handler.ServeHTTP(recorder, req) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp := recorder.Result() | 
					
						
							|  |  |  | 	require.Equal(t, http.StatusBadRequest, resp.StatusCode) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-09 15:27:56 +08:00
										 |  |  | func BenchmarkRemoteWritehandler(b *testing.B) { | 
					
						
							|  |  |  | 	const labelValue = "abcdefg'hijlmn234!@#$%^&*()_+~`\"{}[],./<>?hello0123hiOlá你好Dzieńdobry9Zd8ra765v4stvuyte" | 
					
						
							|  |  |  | 	reqs := []*http.Request{} | 
					
						
							|  |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							|  |  |  | 		num := strings.Repeat(strconv.Itoa(i), 16) | 
					
						
							|  |  |  | 		buf, _, err := buildWriteRequest([]prompb.TimeSeries{{ | 
					
						
							|  |  |  | 			Labels: []prompb.Label{ | 
					
						
							|  |  |  | 				{Name: "__name__", Value: "test_metric"}, | 
					
						
							|  |  |  | 				{Name: "test_label_name_" + num, Value: labelValue + num}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Histograms: []prompb.Histogram{HistogramToHistogramProto(0, &testHistogram)}, | 
					
						
							|  |  |  | 		}}, nil, nil, nil) | 
					
						
							|  |  |  | 		require.NoError(b, err) | 
					
						
							|  |  |  | 		req, err := http.NewRequest("", "", bytes.NewReader(buf)) | 
					
						
							|  |  |  | 		require.NoError(b, err) | 
					
						
							|  |  |  | 		reqs = append(reqs, req) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	appendable := &mockAppendable{} | 
					
						
							|  |  |  | 	handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) | 
					
						
							|  |  |  | 	recorder := httptest.NewRecorder() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	for _, req := range reqs { | 
					
						
							|  |  |  | 		handler.ServeHTTP(recorder, req) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | func TestCommitErr(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2021-10-30 05:44:40 +08:00
										 |  |  | 	buf, _, err := buildWriteRequest(writeRequestFixture.Timeseries, nil, nil, nil) | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	req, err := http.NewRequest("", "", bytes.NewReader(buf)) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	appendable := &mockAppendable{ | 
					
						
							|  |  |  | 		commitErr: fmt.Errorf("commit error"), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-09 15:27:56 +08:00
										 |  |  | 	handler := NewWriteHandler(log.NewNopLogger(), nil, appendable) | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	recorder := httptest.NewRecorder() | 
					
						
							|  |  |  | 	handler.ServeHTTP(recorder, req) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp := recorder.Result() | 
					
						
							| 
									
										
										
										
											2022-04-27 17:24:36 +08:00
										 |  |  | 	body, err := io.ReadAll(resp.Body) | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Equal(t, http.StatusInternalServerError, resp.StatusCode) | 
					
						
							|  |  |  | 	require.Equal(t, "commit error\n", string(body)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-13 21:30:50 +08:00
										 |  |  | func BenchmarkRemoteWriteOOOSamples(b *testing.B) { | 
					
						
							|  |  |  | 	dir := b.TempDir() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	opts := tsdb.DefaultOptions() | 
					
						
							|  |  |  | 	opts.OutOfOrderCapMax = 30 | 
					
						
							|  |  |  | 	opts.OutOfOrderTimeWindow = 120 * time.Minute.Milliseconds() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	db, err := tsdb.Open(dir, nil, nil, opts, nil) | 
					
						
							|  |  |  | 	require.NoError(b, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b.Cleanup(func() { | 
					
						
							|  |  |  | 		require.NoError(b, db.Close()) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-09 15:27:56 +08:00
										 |  |  | 	handler := NewWriteHandler(log.NewNopLogger(), nil, db.Head()) | 
					
						
							| 
									
										
										
										
											2023-01-13 21:30:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	buf, _, err := buildWriteRequest(genSeriesWithSample(1000, 200*time.Minute.Milliseconds()), nil, nil, nil) | 
					
						
							|  |  |  | 	require.NoError(b, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	req, err := http.NewRequest("", "", bytes.NewReader(buf)) | 
					
						
							|  |  |  | 	require.NoError(b, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	recorder := httptest.NewRecorder() | 
					
						
							|  |  |  | 	handler.ServeHTTP(recorder, req) | 
					
						
							|  |  |  | 	require.Equal(b, http.StatusNoContent, recorder.Code) | 
					
						
							|  |  |  | 	require.Equal(b, db.Head().NumSeries(), uint64(1000)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var bufRequests [][]byte | 
					
						
							|  |  |  | 	for i := 0; i < 100; i++ { | 
					
						
							|  |  |  | 		buf, _, err = buildWriteRequest(genSeriesWithSample(1000, int64(80+i)*time.Minute.Milliseconds()), nil, nil, nil) | 
					
						
							|  |  |  | 		require.NoError(b, err) | 
					
						
							|  |  |  | 		bufRequests = append(bufRequests, buf) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b.ResetTimer() | 
					
						
							|  |  |  | 	for i := 0; i < 100; i++ { | 
					
						
							|  |  |  | 		req, err = http.NewRequest("", "", bytes.NewReader(bufRequests[i])) | 
					
						
							|  |  |  | 		require.NoError(b, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		recorder = httptest.NewRecorder() | 
					
						
							|  |  |  | 		handler.ServeHTTP(recorder, req) | 
					
						
							|  |  |  | 		require.Equal(b, http.StatusNoContent, recorder.Code) | 
					
						
							|  |  |  | 		require.Equal(b, db.Head().NumSeries(), uint64(1000)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func genSeriesWithSample(numSeries int, ts int64) []prompb.TimeSeries { | 
					
						
							|  |  |  | 	var series []prompb.TimeSeries | 
					
						
							|  |  |  | 	for i := 0; i < numSeries; i++ { | 
					
						
							|  |  |  | 		s := prompb.TimeSeries{ | 
					
						
							|  |  |  | 			Labels:  []prompb.Label{{Name: "__name__", Value: fmt.Sprintf("test_metric_%d", i)}}, | 
					
						
							|  |  |  | 			Samples: []prompb.Sample{{Value: float64(i), Timestamp: ts}}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		series = append(series, s) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return series | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | type mockAppendable struct { | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | 	latestSample    int64 | 
					
						
							|  |  |  | 	samples         []mockSample | 
					
						
							|  |  |  | 	latestExemplar  int64 | 
					
						
							|  |  |  | 	exemplars       []mockExemplar | 
					
						
							|  |  |  | 	latestHistogram int64 | 
					
						
							|  |  |  | 	histograms      []mockHistogram | 
					
						
							|  |  |  | 	commitErr       error | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type mockSample struct { | 
					
						
							|  |  |  | 	l labels.Labels | 
					
						
							|  |  |  | 	t int64 | 
					
						
							|  |  |  | 	v float64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | type mockExemplar struct { | 
					
						
							|  |  |  | 	l  labels.Labels | 
					
						
							|  |  |  | 	el labels.Labels | 
					
						
							|  |  |  | 	t  int64 | 
					
						
							|  |  |  | 	v  float64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | type mockHistogram struct { | 
					
						
							| 
									
										
										
										
											2022-12-28 16:55:07 +08:00
										 |  |  | 	l  labels.Labels | 
					
						
							|  |  |  | 	t  int64 | 
					
						
							|  |  |  | 	h  *histogram.Histogram | 
					
						
							|  |  |  | 	fh *histogram.FloatHistogram | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | func (m *mockAppendable) Appender(_ context.Context) storage.Appender { | 
					
						
							|  |  |  | 	return m | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-06 18:10:04 +08:00
										 |  |  | func (m *mockAppendable) Append(_ storage.SeriesRef, l labels.Labels, t int64, v float64) (storage.SeriesRef, error) { | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 	if t < m.latestSample { | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 		return 0, storage.ErrOutOfOrderSample | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 	m.latestSample = t | 
					
						
							| 
									
										
										
										
											2021-01-30 19:04:48 +08:00
										 |  |  | 	m.samples = append(m.samples, mockSample{l, t, v}) | 
					
						
							|  |  |  | 	return 0, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (m *mockAppendable) Commit() error { | 
					
						
							|  |  |  | 	return m.commitErr | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (*mockAppendable) Rollback() error { | 
					
						
							|  |  |  | 	return fmt.Errorf("not implemented") | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-16 17:47:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-06 18:10:04 +08:00
										 |  |  | func (m *mockAppendable) AppendExemplar(_ storage.SeriesRef, l labels.Labels, e exemplar.Exemplar) (storage.SeriesRef, error) { | 
					
						
							| 
									
										
										
										
											2021-09-22 04:53:27 +08:00
										 |  |  | 	if e.Ts < m.latestExemplar { | 
					
						
							|  |  |  | 		return 0, storage.ErrOutOfOrderExemplar | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m.latestExemplar = e.Ts | 
					
						
							|  |  |  | 	m.exemplars = append(m.exemplars, mockExemplar{l, e.Labels, e.Ts, e.Value}) | 
					
						
							| 
									
										
										
										
											2021-03-16 17:47:45 +08:00
										 |  |  | 	return 0, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-28 23:00:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 19:05:41 +08:00
										 |  |  | func (m *mockAppendable) AppendHistogram(_ storage.SeriesRef, l labels.Labels, t int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { | 
					
						
							| 
									
										
										
										
											2022-07-14 21:13:12 +08:00
										 |  |  | 	if t < m.latestHistogram { | 
					
						
							|  |  |  | 		return 0, storage.ErrOutOfOrderSample | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m.latestHistogram = t | 
					
						
							| 
									
										
										
										
											2022-12-28 16:55:07 +08:00
										 |  |  | 	m.histograms = append(m.histograms, mockHistogram{l, t, h, fh}) | 
					
						
							| 
									
										
										
										
											2021-06-28 23:00:55 +08:00
										 |  |  | 	return 0, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-08-10 23:54:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 16:58:52 +08:00
										 |  |  | func (m *mockAppendable) UpdateMetadata(_ storage.SeriesRef, _ labels.Labels, _ metadata.Metadata) (storage.SeriesRef, error) { | 
					
						
							|  |  |  | 	// TODO: Wire metadata in a mockAppendable field when we get around to handling metadata in remote_write.
 | 
					
						
							|  |  |  | 	// UpdateMetadata is no-op for remote write (where mockAppendable is being used to test) for now.
 | 
					
						
							|  |  |  | 	return 0, nil | 
					
						
							|  |  |  | } |