Merge pull request #6442 from gotjosh/single-metric-api

api: provide metadata for a specified metric
This commit is contained in:
Björn Rabenstein 2019-12-11 18:21:16 +01:00 committed by GitHub
commit af2257b100
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 116 additions and 9 deletions

View file

@ -668,6 +668,7 @@ GET /api/v1/metadata
URL query parameters: URL query parameters:
- `limit=<number>`: Maximum number of metrics to return. - `limit=<number>`: Maximum number of metrics to return.
- `metric=<string>`: A metric name to filter metadata for. All metric metadata is retrieved if left empty.
The `data` section of the query result consists of an object where each key is a metric name and each value is a list of unique metadata objects, as exposed for that metric name across all targets. The `data` section of the query result consists of an object where each key is a metric name and each value is a list of unique metadata objects, as exposed for that metric name across all targets.
@ -702,6 +703,30 @@ curl -G http://localhost:9090/api/v1/metadata?limit=2
} }
``` ```
The following example returns metadata only for the metric `http_requests_total`.
```json
curl -G http://localhost:9090/api/v1/metadata?metric=http_requests_total
{
"status": "success",
"data": {
"http_requests_total": [
{
"type": "counter",
"help": "Number of HTTP requests",
"unit": ""
},
{
"type": "counter",
"help": "Amount of HTTP requests",
"unit": ""
}
]
}
}
```
## Alertmanagers ## Alertmanagers
The following endpoint returns an overview of the current state of the The following endpoint returns an overview of the current state of the

View file

@ -822,8 +822,12 @@ func (api *API) metricMetadata(r *http.Request) apiFuncResult {
} }
} }
metric := r.FormValue("metric")
for _, tt := range api.targetRetriever.TargetsActive() { for _, tt := range api.targetRetriever.TargetsActive() {
for _, t := range tt { for _, t := range tt {
if metric == "" {
for _, mm := range t.MetadataList() { for _, mm := range t.MetadataList() {
m := metadata{Type: mm.Type, Help: mm.Help, Unit: mm.Unit} m := metadata{Type: mm.Type, Help: mm.Help, Unit: mm.Unit}
ms, ok := metrics[mm.Metric] ms, ok := metrics[mm.Metric]
@ -832,12 +836,25 @@ func (api *API) metricMetadata(r *http.Request) apiFuncResult {
ms = map[metadata]struct{}{} ms = map[metadata]struct{}{}
metrics[mm.Metric] = ms metrics[mm.Metric] = ms
} }
ms[m] = struct{}{}
}
continue
}
if md, ok := t.Metadata(metric); ok {
m := metadata{Type: md.Type, Help: md.Help, Unit: md.Unit}
ms, ok := metrics[md.Metric]
if !ok {
ms = map[metadata]struct{}{}
metrics[md.Metric] = ms
}
ms[m] = struct{}{} ms[m] = struct{}{}
} }
} }
} }
// Put the elements from the pseudo-set into a slice for marshaling.
res := map[string][]metadata{} res := map[string][]metadata{}
for name, set := range metrics { for name, set := range metrics {
@ -846,11 +863,9 @@ func (api *API) metricMetadata(r *http.Request) apiFuncResult {
} }
s := []metadata{} s := []metadata{}
for metadata := range set { for metadata := range set {
s = append(s, metadata) s = append(s, metadata)
} }
res[name] = s res[name] = s
} }

View file

@ -1182,7 +1182,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
}) })
}, },
}, },
// With a limit for the number of metrics returned // With a limit for the number of metrics returned.
{ {
endpoint: api.metricMetadata, endpoint: api.metricMetadata,
query: url.Values{ query: url.Values{
@ -1220,7 +1220,74 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, testLabelAPI
}, },
responseLen: 2, responseLen: 2,
}, },
// With no available metadata // When requesting a specific metric that is present.
{
endpoint: api.metricMetadata,
query: url.Values{"metric": []string{"go_threads"}},
metadata: []targetMetadata{
{
identifier: "test",
metadata: []scrape.MetricMetadata{
{
Metric: "go_threads",
Type: textparse.MetricTypeGauge,
Help: "Number of OS threads created",
Unit: "",
},
},
},
{
identifier: "blackbox",
metadata: []scrape.MetricMetadata{
{
Metric: "go_gc_duration_seconds",
Type: textparse.MetricTypeSummary,
Help: "A summary of the GC invocation durations.",
Unit: "",
},
{
Metric: "go_threads",
Type: textparse.MetricTypeGauge,
Help: "Number of OS threads that were created.",
Unit: "",
},
},
},
},
response: map[string][]metadata{
"go_threads": []metadata{
{textparse.MetricTypeGauge, "Number of OS threads created", ""},
{textparse.MetricTypeGauge, "Number of OS threads that were created.", ""},
},
},
sorter: func(m interface{}) {
v := m.(map[string][]metadata)["go_threads"]
sort.Slice(v, func(i, j int) bool {
return v[i].Help < v[j].Help
})
},
},
// With a specific metric that is not present.
{
endpoint: api.metricMetadata,
query: url.Values{"metric": []string{"go_gc_duration_seconds"}},
metadata: []targetMetadata{
{
identifier: "test",
metadata: []scrape.MetricMetadata{
{
Metric: "go_threads",
Type: textparse.MetricTypeGauge,
Help: "Number of OS threads created",
Unit: "",
},
},
},
},
response: map[string][]metadata{},
},
// With no available metadata.
{ {
endpoint: api.metricMetadata, endpoint: api.metricMetadata,
response: map[string][]metadata{}, response: map[string][]metadata{},