mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Merge 83eb216986
into 61aa82865d
This commit is contained in:
commit
b550a92cb2
|
@ -132,6 +132,7 @@ func ToQueryResult(ss storage.SeriesSet, sampleLimit int) (*prompb.QueryResult,
|
||||||
var (
|
var (
|
||||||
samples []prompb.Sample
|
samples []prompb.Sample
|
||||||
histograms []prompb.Histogram
|
histograms []prompb.Histogram
|
||||||
|
exemplars []prompb.Exemplar
|
||||||
)
|
)
|
||||||
|
|
||||||
for valType := iter.Next(); valType != chunkenc.ValNone; valType = iter.Next() {
|
for valType := iter.Next(); valType != chunkenc.ValNone; valType = iter.Next() {
|
||||||
|
@ -164,10 +165,16 @@ func ToQueryResult(ss storage.SeriesSet, sampleLimit int) (*prompb.QueryResult,
|
||||||
return nil, ss.Warnings(), err
|
return nil, ss.Warnings(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sse, ok := ss.(*seriesSetWithExemplars); ok {
|
||||||
|
key := series.Labels().Hash()
|
||||||
|
exemplars = sse.exemplarMap[key]
|
||||||
|
}
|
||||||
|
|
||||||
resp.Timeseries = append(resp.Timeseries, &prompb.TimeSeries{
|
resp.Timeseries = append(resp.Timeseries, &prompb.TimeSeries{
|
||||||
Labels: prompb.FromLabels(series.Labels(), nil),
|
Labels: prompb.FromLabels(series.Labels(), nil),
|
||||||
Samples: samples,
|
Samples: samples,
|
||||||
Histograms: histograms,
|
Histograms: histograms,
|
||||||
|
Exemplars: exemplars,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return resp, ss.Warnings(), ss.Err()
|
return resp, ss.Warnings(), ss.Err()
|
||||||
|
@ -182,7 +189,7 @@ func FromQueryResult(sortSeries bool, res *prompb.QueryResult) storage.SeriesSet
|
||||||
return errSeriesSet{err: err}
|
return errSeriesSet{err: err}
|
||||||
}
|
}
|
||||||
lbls := ts.ToLabels(&b, nil)
|
lbls := ts.ToLabels(&b, nil)
|
||||||
series = append(series, &concreteSeries{labels: lbls, floats: ts.Samples, histograms: ts.Histograms})
|
series = append(series, &concreteSeries{labels: lbls, floats: ts.Samples, histograms: ts.Histograms, exemplars: ts.Exemplars})
|
||||||
}
|
}
|
||||||
|
|
||||||
if sortSeries {
|
if sortSeries {
|
||||||
|
@ -368,6 +375,7 @@ type concreteSeries struct {
|
||||||
labels labels.Labels
|
labels labels.Labels
|
||||||
floats []prompb.Sample
|
floats []prompb.Sample
|
||||||
histograms []prompb.Histogram
|
histograms []prompb.Histogram
|
||||||
|
exemplars []prompb.Exemplar
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *concreteSeries) Labels() labels.Labels {
|
func (c *concreteSeries) Labels() labels.Labels {
|
||||||
|
|
|
@ -18,7 +18,9 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prometheus/prometheus/model/exemplar"
|
||||||
"github.com/prometheus/prometheus/model/labels"
|
"github.com/prometheus/prometheus/model/labels"
|
||||||
|
"github.com/prometheus/prometheus/prompb"
|
||||||
"github.com/prometheus/prometheus/storage"
|
"github.com/prometheus/prometheus/storage"
|
||||||
"github.com/prometheus/prometheus/util/annotations"
|
"github.com/prometheus/prometheus/util/annotations"
|
||||||
)
|
)
|
||||||
|
@ -29,6 +31,7 @@ type sampleAndChunkQueryableClient struct {
|
||||||
requiredMatchers []*labels.Matcher
|
requiredMatchers []*labels.Matcher
|
||||||
readRecent bool
|
readRecent bool
|
||||||
callback startTimeCallback
|
callback startTimeCallback
|
||||||
|
exemplarQueryable storage.ExemplarQueryable
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSampleAndChunkQueryableClient returns a storage.SampleAndChunkQueryable which queries the given client to select series sets.
|
// NewSampleAndChunkQueryableClient returns a storage.SampleAndChunkQueryable which queries the given client to select series sets.
|
||||||
|
@ -38,6 +41,7 @@ func NewSampleAndChunkQueryableClient(
|
||||||
requiredMatchers []*labels.Matcher,
|
requiredMatchers []*labels.Matcher,
|
||||||
readRecent bool,
|
readRecent bool,
|
||||||
callback startTimeCallback,
|
callback startTimeCallback,
|
||||||
|
exemplarQueryable storage.ExemplarQueryable,
|
||||||
) storage.SampleAndChunkQueryable {
|
) storage.SampleAndChunkQueryable {
|
||||||
return &sampleAndChunkQueryableClient{
|
return &sampleAndChunkQueryableClient{
|
||||||
client: c,
|
client: c,
|
||||||
|
@ -46,6 +50,7 @@ func NewSampleAndChunkQueryableClient(
|
||||||
requiredMatchers: requiredMatchers,
|
requiredMatchers: requiredMatchers,
|
||||||
readRecent: readRecent,
|
readRecent: readRecent,
|
||||||
callback: callback,
|
callback: callback,
|
||||||
|
exemplarQueryable: exemplarQueryable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +61,7 @@ func (c *sampleAndChunkQueryableClient) Querier(mint, maxt int64) (storage.Queri
|
||||||
client: c.client,
|
client: c.client,
|
||||||
externalLabels: c.externalLabels,
|
externalLabels: c.externalLabels,
|
||||||
requiredMatchers: c.requiredMatchers,
|
requiredMatchers: c.requiredMatchers,
|
||||||
|
exemplarQueryable: c.exemplarQueryable,
|
||||||
}
|
}
|
||||||
if c.readRecent {
|
if c.readRecent {
|
||||||
return q, nil
|
return q, nil
|
||||||
|
@ -83,6 +89,7 @@ func (c *sampleAndChunkQueryableClient) ChunkQuerier(mint, maxt int64) (storage.
|
||||||
client: c.client,
|
client: c.client,
|
||||||
externalLabels: c.externalLabels,
|
externalLabels: c.externalLabels,
|
||||||
requiredMatchers: c.requiredMatchers,
|
requiredMatchers: c.requiredMatchers,
|
||||||
|
exemplarQueryable: c.exemplarQueryable,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if c.readRecent {
|
if c.readRecent {
|
||||||
|
@ -130,6 +137,7 @@ type querier struct {
|
||||||
// Derived from configuration.
|
// Derived from configuration.
|
||||||
externalLabels labels.Labels
|
externalLabels labels.Labels
|
||||||
requiredMatchers []*labels.Matcher
|
requiredMatchers []*labels.Matcher
|
||||||
|
exemplarQueryable storage.ExemplarQueryable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select implements storage.Querier and uses the given matchers to read series sets from the client.
|
// Select implements storage.Querier and uses the given matchers to read series sets from the client.
|
||||||
|
@ -164,11 +172,22 @@ func (q *querier) Select(ctx context.Context, sortSeries bool, hints *storage.Se
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return storage.ErrSeriesSet(fmt.Errorf("toQuery: %w", err))
|
return storage.ErrSeriesSet(fmt.Errorf("toQuery: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := q.client.Read(ctx, query, sortSeries)
|
res, err := q.client.Read(ctx, query, sortSeries)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return storage.ErrSeriesSet(fmt.Errorf("remote_read: %w", err))
|
return storage.ErrSeriesSet(fmt.Errorf("remote_read: %w", err))
|
||||||
}
|
}
|
||||||
|
if q.exemplarQueryable != nil {
|
||||||
|
exemplarQuerier, err := q.exemplarQueryable.ExemplarQuerier(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return storage.ErrSeriesSet(fmt.Errorf("ExemplarQuerier: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
exemplars, err := exemplarQuerier.Select(q.mint, q.maxt, [][]*labels.Matcher{matchers}...)
|
||||||
|
if err != nil {
|
||||||
|
return storage.ErrSeriesSet(fmt.Errorf("exemplar select: %w", err))
|
||||||
|
}
|
||||||
|
res = mergeSeriesWithExemplars(res, exemplars)
|
||||||
|
}
|
||||||
return newSeriesSetFilter(res, added)
|
return newSeriesSetFilter(res, added)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,3 +297,48 @@ func (sf seriesFilter) Labels() labels.Labels {
|
||||||
b.Del(sf.toFilter...)
|
b.Del(sf.toFilter...)
|
||||||
return b.Labels()
|
return b.Labels()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeSeriesWithExemplars(ss storage.SeriesSet, exemplars []exemplar.QueryResult) storage.SeriesSet {
|
||||||
|
exemplarMap := make(map[uint64][]prompb.Exemplar)
|
||||||
|
for _, result := range exemplars {
|
||||||
|
key := result.SeriesLabels.Hash()
|
||||||
|
for _, ex := range result.Exemplars {
|
||||||
|
if ex.HasTs {
|
||||||
|
exemplarMap[key] = append(exemplarMap[key], prompb.Exemplar{
|
||||||
|
Labels: prompb.FromLabels(ex.Labels, nil),
|
||||||
|
Value: ex.Value,
|
||||||
|
Timestamp: ex.Ts,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &seriesSetWithExemplars{
|
||||||
|
SeriesSet: ss,
|
||||||
|
exemplarMap: exemplarMap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type seriesSetWithExemplars struct {
|
||||||
|
storage.SeriesSet
|
||||||
|
exemplarMap map[uint64][]prompb.Exemplar
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sswe *seriesSetWithExemplars) At() storage.Series {
|
||||||
|
series := sswe.SeriesSet.At()
|
||||||
|
key := series.Labels().Hash()
|
||||||
|
exemplars := sswe.exemplarMap[key]
|
||||||
|
|
||||||
|
return &seriesWithExemplars{
|
||||||
|
Series: series,
|
||||||
|
exemplars: exemplars,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type seriesWithExemplars struct {
|
||||||
|
storage.Series
|
||||||
|
exemplars []prompb.Exemplar
|
||||||
|
}
|
||||||
|
|
||||||
|
func (swe *seriesWithExemplars) Exemplars() []prompb.Exemplar {
|
||||||
|
return swe.exemplars
|
||||||
|
}
|
||||||
|
|
|
@ -258,6 +258,7 @@ func TestSampleAndChunkQueryableClient(t *testing.T) {
|
||||||
|
|
||||||
expectedQuery *prompb.Query
|
expectedQuery *prompb.Query
|
||||||
expectedSeries []labels.Labels
|
expectedSeries []labels.Labels
|
||||||
|
exemplarQueryable storage.ExemplarQueryable
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
|
@ -472,6 +473,7 @@ func TestSampleAndChunkQueryableClient(t *testing.T) {
|
||||||
tc.requiredMatchers,
|
tc.requiredMatchers,
|
||||||
tc.readRecent,
|
tc.readRecent,
|
||||||
tc.callback,
|
tc.callback,
|
||||||
|
tc.exemplarQueryable,
|
||||||
)
|
)
|
||||||
q, err := c.Querier(tc.mint, tc.maxt)
|
q, err := c.Querier(tc.mint, tc.maxt)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -61,6 +61,7 @@ type Storage struct {
|
||||||
// For reads.
|
// For reads.
|
||||||
queryables []storage.SampleAndChunkQueryable
|
queryables []storage.SampleAndChunkQueryable
|
||||||
localStartTimeCallback startTimeCallback
|
localStartTimeCallback startTimeCallback
|
||||||
|
exemplarQueryable storage.ExemplarQueryable
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStorage returns a remote.Storage.
|
// NewStorage returns a remote.Storage.
|
||||||
|
@ -137,6 +138,7 @@ func (s *Storage) ApplyConfig(conf *config.Config) error {
|
||||||
labelsToEqualityMatchers(rrConf.RequiredMatchers),
|
labelsToEqualityMatchers(rrConf.RequiredMatchers),
|
||||||
rrConf.ReadRecent,
|
rrConf.ReadRecent,
|
||||||
s.localStartTimeCallback,
|
s.localStartTimeCallback,
|
||||||
|
s.exemplarQueryable,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
s.queryables = queryables
|
s.queryables = queryables
|
||||||
|
|
Loading…
Reference in a new issue