mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
api: tests for /target/metadata API endpoint
This commit introduces several test cases for the current /targets/metadata API endpoint. To achieve so, we use a mock of the metadataStore and inject it to the targets under test. Currently, three success cases are covered: with a metric name, with a target matcher, and with both. As for the failure scenario, the one where we couldn't match against a particular metric is covered. Signed-off-by: gotjosh <josue@grafana.com>
This commit is contained in:
parent
05842176a6
commit
428089f83f
|
@ -43,6 +43,7 @@ import (
|
|||
"github.com/prometheus/prometheus/config"
|
||||
"github.com/prometheus/prometheus/pkg/gate"
|
||||
"github.com/prometheus/prometheus/pkg/labels"
|
||||
"github.com/prometheus/prometheus/pkg/textparse"
|
||||
"github.com/prometheus/prometheus/pkg/timestamp"
|
||||
"github.com/prometheus/prometheus/prompb"
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
|
@ -55,6 +56,28 @@ import (
|
|||
"github.com/prometheus/prometheus/util/testutil"
|
||||
)
|
||||
|
||||
// testMetaStore satisfies the scrape.MetricMetadataStore interface.
|
||||
// It is used to inject specific metadata as part of a test case.
|
||||
type testMetaStore struct {
|
||||
Metadata []scrape.MetricMetadata
|
||||
}
|
||||
|
||||
func (s *testMetaStore) ListMetadata() []scrape.MetricMetadata {
|
||||
return s.Metadata
|
||||
}
|
||||
|
||||
func (s *testMetaStore) GetMetadata(metric string) (scrape.MetricMetadata, bool) {
|
||||
for _, m := range s.Metadata {
|
||||
if metric == m.Metric {
|
||||
return m, true
|
||||
}
|
||||
}
|
||||
|
||||
return scrape.MetricMetadata{}, false
|
||||
}
|
||||
|
||||
// testTargetRetriever represents a list of targets to scrape.
|
||||
// It is used to represent targets as part of test cases.
|
||||
type testTargetRetriever struct {
|
||||
activeTargets map[string][]*scrape.Target
|
||||
droppedTargets map[string][]*scrape.Target
|
||||
|
@ -113,6 +136,20 @@ func (t testTargetRetriever) TargetsDropped() map[string][]*scrape.Target {
|
|||
return t.droppedTargets
|
||||
}
|
||||
|
||||
func (t testTargetRetriever) setMetadataStoreForTargets(identifier string, metadata scrape.MetricMetadataStore) error {
|
||||
targets, ok := t.activeTargets[identifier]
|
||||
|
||||
if !ok {
|
||||
return errors.New("targets not found")
|
||||
}
|
||||
|
||||
for _, at := range targets {
|
||||
at.SetMetadataStore(metadata)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type testAlertmanagerRetriever struct{}
|
||||
|
||||
func (t testAlertmanagerRetriever) Alertmanagers() []*url.URL {
|
||||
|
@ -250,48 +287,7 @@ func TestEndpoints(t *testing.T) {
|
|||
|
||||
algr.RuleGroups()
|
||||
|
||||
targets := []*testTargetParams{
|
||||
{
|
||||
Identifier: "test",
|
||||
Labels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "example.com:8080",
|
||||
model.MetricsPathLabel: "/metrics",
|
||||
model.JobLabel: "test",
|
||||
}),
|
||||
DiscoveredLabels: nil,
|
||||
Params: url.Values{},
|
||||
Reports: []*testReport{{scrapeStart, 70 * time.Millisecond, nil}},
|
||||
Active: true,
|
||||
},
|
||||
{
|
||||
Identifier: "blackbox",
|
||||
Labels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "localhost:9115",
|
||||
model.MetricsPathLabel: "/probe",
|
||||
model.JobLabel: "blackbox",
|
||||
}),
|
||||
DiscoveredLabels: nil,
|
||||
Params: url.Values{"target": []string{"example.com"}},
|
||||
Reports: []*testReport{{scrapeStart, 100 * time.Millisecond, errors.New("failed")}},
|
||||
Active: true,
|
||||
},
|
||||
{
|
||||
Identifier: "blackbox",
|
||||
Labels: nil,
|
||||
DiscoveredLabels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "http://dropped.example.com:9115",
|
||||
model.MetricsPathLabel: "/probe",
|
||||
model.JobLabel: "blackbox",
|
||||
}),
|
||||
Params: url.Values{},
|
||||
Active: false,
|
||||
},
|
||||
}
|
||||
|
||||
testTargetRetriever := newTestTargetRetriever(targets)
|
||||
testTargetRetriever := setupTestTargetRetriever(t)
|
||||
|
||||
api := &API{
|
||||
Queryable: suite.Storage(),
|
||||
|
@ -355,48 +351,7 @@ func TestEndpoints(t *testing.T) {
|
|||
|
||||
algr.RuleGroups()
|
||||
|
||||
targets := []*testTargetParams{
|
||||
{
|
||||
Identifier: "test",
|
||||
Labels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "example.com:8080",
|
||||
model.MetricsPathLabel: "/metrics",
|
||||
model.JobLabel: "test",
|
||||
}),
|
||||
DiscoveredLabels: nil,
|
||||
Params: url.Values{},
|
||||
Reports: []*testReport{{scrapeStart, 70 * time.Millisecond, nil}},
|
||||
Active: true,
|
||||
},
|
||||
{
|
||||
Identifier: "blackbox",
|
||||
Labels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "localhost:9115",
|
||||
model.MetricsPathLabel: "/probe",
|
||||
model.JobLabel: "blackbox",
|
||||
}),
|
||||
DiscoveredLabels: nil,
|
||||
Params: url.Values{"target": []string{"example.com"}},
|
||||
Reports: []*testReport{{scrapeStart, 100 * time.Millisecond, errors.New("failed")}},
|
||||
Active: true,
|
||||
},
|
||||
{
|
||||
Identifier: "blackbox",
|
||||
Labels: nil,
|
||||
DiscoveredLabels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "http://dropped.example.com:9115",
|
||||
model.MetricsPathLabel: "/probe",
|
||||
model.JobLabel: "blackbox",
|
||||
}),
|
||||
Params: url.Values{},
|
||||
Active: false,
|
||||
},
|
||||
}
|
||||
|
||||
testTargetRetriever := newTestTargetRetriever(targets)
|
||||
testTargetRetriever := setupTestTargetRetriever(t)
|
||||
|
||||
api := &API{
|
||||
Queryable: remote,
|
||||
|
@ -450,6 +405,76 @@ func TestLabelNames(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func setupTestTargetRetriever(t *testing.T) *testTargetRetriever {
|
||||
t.Helper()
|
||||
|
||||
targets := []*testTargetParams{
|
||||
{
|
||||
Identifier: "test",
|
||||
Labels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "example.com:8080",
|
||||
model.MetricsPathLabel: "/metrics",
|
||||
model.JobLabel: "test",
|
||||
}),
|
||||
DiscoveredLabels: nil,
|
||||
Params: url.Values{},
|
||||
Reports: []*testReport{{scrapeStart, 70 * time.Millisecond, nil}},
|
||||
Active: true,
|
||||
},
|
||||
{
|
||||
Identifier: "blackbox",
|
||||
Labels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "localhost:9115",
|
||||
model.MetricsPathLabel: "/probe",
|
||||
model.JobLabel: "blackbox",
|
||||
}),
|
||||
DiscoveredLabels: nil,
|
||||
Params: url.Values{"target": []string{"example.com"}},
|
||||
Reports: []*testReport{{scrapeStart, 100 * time.Millisecond, errors.New("failed")}},
|
||||
Active: true,
|
||||
},
|
||||
{
|
||||
Identifier: "blackbox",
|
||||
Labels: nil,
|
||||
DiscoveredLabels: labels.FromMap(map[string]string{
|
||||
model.SchemeLabel: "http",
|
||||
model.AddressLabel: "http://dropped.example.com:9115",
|
||||
model.MetricsPathLabel: "/probe",
|
||||
model.JobLabel: "blackbox",
|
||||
}),
|
||||
Params: url.Values{},
|
||||
Active: false,
|
||||
},
|
||||
}
|
||||
targetRetriever := newTestTargetRetriever(targets)
|
||||
|
||||
targetRetriever.setMetadataStoreForTargets("test", &testMetaStore{
|
||||
Metadata: []scrape.MetricMetadata{
|
||||
{
|
||||
Metric: "go_threads",
|
||||
Type: textparse.MetricTypeGauge,
|
||||
Help: "Number of OS threads created.",
|
||||
Unit: "",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
targetRetriever.setMetadataStoreForTargets("blackbox", &testMetaStore{
|
||||
Metadata: []scrape.MetricMetadata{
|
||||
{
|
||||
Metric: "prometheus_tsdb_storage_blocks_bytes",
|
||||
Type: textparse.MetricTypeGauge,
|
||||
Help: "The number of bytes that are currently used for local storage by all blocks.",
|
||||
Unit: "",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return targetRetriever
|
||||
}
|
||||
|
||||
func setupRemote(s storage.Storage) *httptest.Server {
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := remote.DecodeReadRequest(r)
|
||||
|
@ -926,6 +951,73 @@ func testEndpoints(t *testing.T, api *API, testLabelAPI bool) {
|
|||
},
|
||||
},
|
||||
},
|
||||
// With a matching metric.
|
||||
{
|
||||
endpoint: api.targetMetadata,
|
||||
query: url.Values{
|
||||
"metric": []string{"go_threads"},
|
||||
},
|
||||
response: []metricMetadata{
|
||||
{
|
||||
Target: labels.FromMap(map[string]string{
|
||||
"job": "test",
|
||||
}),
|
||||
Help: "Number of OS threads created.",
|
||||
Type: textparse.MetricTypeGauge,
|
||||
Unit: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
// With a matching target.
|
||||
{
|
||||
endpoint: api.targetMetadata,
|
||||
query: url.Values{
|
||||
"match_target": []string{"{job=\"blackbox\"}"},
|
||||
},
|
||||
response: []metricMetadata{
|
||||
{
|
||||
Target: labels.FromMap(map[string]string{
|
||||
"job": "blackbox",
|
||||
}),
|
||||
Metric: "prometheus_tsdb_storage_blocks_bytes",
|
||||
Help: "The number of bytes that are currently used for local storage by all blocks.",
|
||||
Type: textparse.MetricTypeGauge,
|
||||
Unit: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Without a target or metric.
|
||||
{
|
||||
endpoint: api.targetMetadata,
|
||||
response: []metricMetadata{
|
||||
{
|
||||
Target: labels.FromMap(map[string]string{
|
||||
"job": "test",
|
||||
}),
|
||||
Metric: "go_threads",
|
||||
Help: "Number of OS threads created.",
|
||||
Type: textparse.MetricTypeGauge,
|
||||
Unit: "",
|
||||
},
|
||||
{
|
||||
Target: labels.FromMap(map[string]string{
|
||||
"job": "blackbox",
|
||||
}),
|
||||
Metric: "prometheus_tsdb_storage_blocks_bytes",
|
||||
Help: "The number of bytes that are currently used for local storage by all blocks.",
|
||||
Type: textparse.MetricTypeGauge,
|
||||
Unit: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Without a matching metric.
|
||||
{
|
||||
endpoint: api.targetMetadata,
|
||||
query: url.Values{
|
||||
"match_target": []string{"{job=\"non-existentblackbox\"}"},
|
||||
},
|
||||
errType: errorNotFound,
|
||||
},
|
||||
{
|
||||
endpoint: api.alertmanagers,
|
||||
response: &AlertmanagerDiscovery{
|
||||
|
|
Loading…
Reference in a new issue