Browse Source

Merge pull request #6409 from gotjosh/tests-for-target-metadata

Add tests for /api/v1/target/metadata
pull/6419/head
Brian Brazil 5 years ago committed by GitHub
parent
commit
0ae4899c47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      scrape/scrape.go
  2. 6
      scrape/scrape_test.go
  3. 14
      scrape/target.go
  4. 269
      web/api/v1/api_test.go

6
scrape/scrape.go

@ -209,7 +209,7 @@ func newScrapePool(cfg *config.ScrapeConfig, app Appendable, jitterSeed uint64,
sp.newLoop = func(opts scrapeLoopOptions) loop {
// Update the targets retrieval function for metadata to a new scrape cache.
cache := newScrapeCache()
opts.target.setMetadataStore(cache)
opts.target.SetMetadataStore(cache)
return newScrapeLoop(
ctx,
@ -794,7 +794,7 @@ func (c *scrapeCache) setUnit(metric, unit []byte) {
c.metaMtx.Unlock()
}
func (c *scrapeCache) getMetadata(metric string) (MetricMetadata, bool) {
func (c *scrapeCache) GetMetadata(metric string) (MetricMetadata, bool) {
c.metaMtx.Lock()
defer c.metaMtx.Unlock()
@ -810,7 +810,7 @@ func (c *scrapeCache) getMetadata(metric string) (MetricMetadata, bool) {
}, true
}
func (c *scrapeCache) listMetadata() []MetricMetadata {
func (c *scrapeCache) ListMetadata() []MetricMetadata {
c.metaMtx.Lock()
defer c.metaMtx.Unlock()

6
scrape/scrape_test.go

@ -615,19 +615,19 @@ test_metric 1
testutil.Ok(t, err)
testutil.Equals(t, 1, total)
md, ok := cache.getMetadata("test_metric")
md, ok := cache.GetMetadata("test_metric")
testutil.Assert(t, ok, "expected metadata to be present")
testutil.Assert(t, textparse.MetricTypeCounter == md.Type, "unexpected metric type")
testutil.Equals(t, "some help text", md.Help)
testutil.Equals(t, "metric", md.Unit)
md, ok = cache.getMetadata("test_metric_no_help")
md, ok = cache.GetMetadata("test_metric_no_help")
testutil.Assert(t, ok, "expected metadata to be present")
testutil.Assert(t, textparse.MetricTypeGauge == md.Type, "unexpected metric type")
testutil.Equals(t, "", md.Help)
testutil.Equals(t, "", md.Unit)
md, ok = cache.getMetadata("test_metric_no_type")
md, ok = cache.GetMetadata("test_metric_no_type")
testutil.Assert(t, ok, "expected metadata to be present")
testutil.Assert(t, textparse.MetricTypeUnknown == md.Type, "unexpected metric type")
testutil.Equals(t, "other help text", md.Help)

14
scrape/target.go

@ -58,7 +58,7 @@ type Target struct {
lastScrape time.Time
lastScrapeDuration time.Duration
health TargetHealth
metadata metricMetadataStore
metadata MetricMetadataStore
}
// NewTarget creates a reasonably configured target for querying.
@ -75,9 +75,9 @@ func (t *Target) String() string {
return t.URL().String()
}
type metricMetadataStore interface {
listMetadata() []MetricMetadata
getMetadata(metric string) (MetricMetadata, bool)
type MetricMetadataStore interface {
ListMetadata() []MetricMetadata
GetMetadata(metric string) (MetricMetadata, bool)
}
// MetricMetadata is a piece of metadata for a metric.
@ -95,7 +95,7 @@ func (t *Target) MetadataList() []MetricMetadata {
if t.metadata == nil {
return nil
}
return t.metadata.listMetadata()
return t.metadata.ListMetadata()
}
// Metadata returns type and help metadata for the given metric.
@ -106,10 +106,10 @@ func (t *Target) Metadata(metric string) (MetricMetadata, bool) {
if t.metadata == nil {
return MetricMetadata{}, false
}
return t.metadata.getMetadata(metric)
return t.metadata.GetMetadata(metric)
}
func (t *Target) setMetadataStore(s metricMetadataStore) {
func (t *Target) SetMetadataStore(s MetricMetadataStore) {
t.mtx.Lock()
defer t.mtx.Unlock()
t.metadata = s

269
web/api/v1/api_test.go

@ -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,55 +56,98 @@ import (
"github.com/prometheus/prometheus/util/testutil"
)
type testTargetRetriever struct{}
// 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
}
type testTargetParams struct {
Identifier string
Labels []labels.Label
DiscoveredLabels []labels.Label
Params url.Values
Reports []*testReport
Active bool
}
type testReport struct {
Start time.Time
Duration time.Duration
Error error
}
func newTestTargetRetriever(targetsInfo []*testTargetParams) *testTargetRetriever {
var activeTargets map[string][]*scrape.Target
var droppedTargets map[string][]*scrape.Target
activeTargets = make(map[string][]*scrape.Target)
droppedTargets = make(map[string][]*scrape.Target)
for _, t := range targetsInfo {
nt := scrape.NewTarget(t.Labels, t.DiscoveredLabels, t.Params)
for _, r := range t.Reports {
nt.Report(r.Start, r.Duration, r.Error)
}
if t.Active {
activeTargets[t.Identifier] = []*scrape.Target{nt}
} else {
droppedTargets[t.Identifier] = []*scrape.Target{nt}
}
}
return &testTargetRetriever{
activeTargets: activeTargets,
droppedTargets: droppedTargets,
}
}
var (
scrapeStart = time.Now().Add(-11 * time.Second)
)
func (t testTargetRetriever) TargetsActive() map[string][]*scrape.Target {
testTarget := scrape.NewTarget(
labels.FromMap(map[string]string{
model.SchemeLabel: "http",
model.AddressLabel: "example.com:8080",
model.MetricsPathLabel: "/metrics",
model.JobLabel: "test",
}),
nil,
url.Values{},
)
testTarget.Report(scrapeStart, 70*time.Millisecond, nil)
blackboxTarget := scrape.NewTarget(
labels.FromMap(map[string]string{
model.SchemeLabel: "http",
model.AddressLabel: "localhost:9115",
model.MetricsPathLabel: "/probe",
model.JobLabel: "blackbox",
}),
nil,
url.Values{"target": []string{"example.com"}},
)
blackboxTarget.Report(scrapeStart, 100*time.Millisecond, errors.New("failed"))
return map[string][]*scrape.Target{
"test": {testTarget},
"blackbox": {blackboxTarget},
}
return t.activeTargets
}
func (t testTargetRetriever) TargetsDropped() map[string][]*scrape.Target {
return map[string][]*scrape.Target{
"blackbox": {
scrape.NewTarget(
nil,
labels.FromMap(map[string]string{
model.AddressLabel: "http://dropped.example.com:9115",
model.MetricsPathLabel: "/probe",
model.SchemeLabel: "http",
model.JobLabel: "blackbox",
}),
url.Values{},
),
},
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{}
@ -243,10 +287,12 @@ func TestEndpoints(t *testing.T) {
algr.RuleGroups()
testTargetRetriever := setupTestTargetRetriever(t)
api := &API{
Queryable: suite.Storage(),
QueryEngine: suite.QueryEngine(),
targetRetriever: testTargetRetriever{},
targetRetriever: testTargetRetriever,
alertmanagerRetriever: testAlertmanagerRetriever{},
flagsMap: sampleFlagMap,
now: func() time.Time { return now },
@ -305,10 +351,12 @@ func TestEndpoints(t *testing.T) {
algr.RuleGroups()
testTargetRetriever := setupTestTargetRetriever(t)
api := &API{
Queryable: remote,
QueryEngine: suite.QueryEngine(),
targetRetriever: testTargetRetriever{},
targetRetriever: testTargetRetriever,
alertmanagerRetriever: testAlertmanagerRetriever{},
flagsMap: sampleFlagMap,
now: func() time.Time { return now },
@ -357,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)
@ -833,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…
Cancel
Save