Fix v1 label API to be Prometheus-compatible (#1322)

The label and label values API will now return the expected form
of:

```json
{
  "status": "success",
  "data": [
    "label1",
    "label2",
    "labeln"
  ]
}
```
pull/1326/head
Robert Fratto 6 years ago committed by GitHub
parent 715f215c50
commit 822e94fe6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 86
      docs/api.md
  2. 2
      pkg/logcli/labelquery/labels.go
  3. 3
      pkg/loghttp/labels.go
  4. 4
      pkg/logql/marshal/legacy/marshal_test.go
  5. 22
      pkg/logql/marshal/marshal.go
  6. 2
      pkg/logql/marshal/marshal_test.go

@ -14,6 +14,8 @@ The HTTP API includes the following endpoints:
- [`POST /loki/api/v1/push`](#post-lokiapiv1push) - [`POST /loki/api/v1/push`](#post-lokiapiv1push)
- [`GET /api/prom/tail`](#get-apipromtail) - [`GET /api/prom/tail`](#get-apipromtail)
- [`GET /api/prom/query`](#get-apipromquery) - [`GET /api/prom/query`](#get-apipromquery)
- [`GET /api/prom/label`](#get-apipromlabel)
- [`GET /api/prom/label/<name>/values`](#get-apipromlabelnamevalues)
- [`POST /api/prom/push`](#post-apiprompush) - [`POST /api/prom/push`](#post-apiprompush)
- [`GET /ready`](#get-ready) - [`GET /ready`](#get-ready)
- [`POST /flush`](#post-flush) - [`POST /flush`](#post-flush)
@ -38,6 +40,8 @@ These endpoints are exposed by just the querier:
- [`GET /loki/api/v1/tail`](#get-lokiapiv1tail) - [`GET /loki/api/v1/tail`](#get-lokiapiv1tail)
- [`GET /api/prom/tail`](#get-lokiapipromtail) - [`GET /api/prom/tail`](#get-lokiapipromtail)
- [`GET /api/prom/query`](#get-apipromquery) - [`GET /api/prom/query`](#get-apipromquery)
- [`GET /api/prom/label`](#get-apipromlabel)
- [`GET /api/prom/label/<name>/values`](#get-apipromlabelnamevalues)
While these endpoints are exposed by just the distributor: While these endpoints are exposed by just the distributor:
@ -348,7 +352,8 @@ Response:
``` ```
{ {
"values": [ "status": "success",
"data": [
<label string>, <label string>,
... ...
] ]
@ -360,7 +365,8 @@ Response:
```bash ```bash
$ curl -G -s "http://localhost:3100/loki/api/v1/label" | jq $ curl -G -s "http://localhost:3100/loki/api/v1/label" | jq
{ {
"values": [ "status": "success",
"data": [
"foo", "foo",
"bar", "bar",
"baz" "baz"
@ -383,7 +389,8 @@ Response:
``` ```
{ {
"values": [ "status": "success",
"data": [
<label value>, <label value>,
... ...
] ]
@ -395,7 +402,8 @@ Response:
```bash ```bash
$ curl -G -s "http://localhost:3100/loki/api/v1/label/foo/values" | jq $ curl -G -s "http://localhost:3100/loki/api/v1/label/foo/values" | jq
{ {
"values": [ "status": "success",
"data": [
"cat", "cat",
"dog", "dog",
"axolotl" "axolotl"
@ -597,11 +605,77 @@ $ curl -G -s "http://localhost:3100/api/prom/query" --data-urlencode '{foo="bar
} }
``` ```
## `GET /api/prom/label`
> **WARNING**: `/api/prom/label` is DEPRECATED; use `/loki/api/v1/label`
`/api/prom/label` retrieves the list of known labels within a given time span. It
accepts the following query parameters in the URL:
- `start`: The start time for the query as a nanosecond Unix epoch. Defaults to 6 hours ago.
- `end`: The start time for the query as a nanosecond Unix epoch. Defaults to now.
In microservices mode, `/api/prom/label` is exposed by the querier.
Response:
```
{
"values": [
<label string>,
...
]
}
```
### Examples ### Examples
```bash ```bash
$ curl -H "Content-Type: application/json" -XPOST -s "https://localhost:3100/loki/api/v1/push" --data-raw \ $ curl -G -s "http://localhost:3100/api/prom/label" | jq
'{"streams": [{ "labels": "{foo=\"bar\"}", "entries": [{ "ts": "2018-12-18T08:28:06.801064-04:00", "line": "fizzbuzz" }] }]}' {
"values": [
"foo",
"bar",
"baz"
]
}
```
## `GET /api/prom/label/<name>/values`
> **WARNING**: `/api/prom/label/<name>/values` is DEPRECATED; use `/loki/api/v1/label/<name>/values`
`/api/prom/label/<name>/values` retrieves the list of known values for a given
label within a given time span. It accepts the following query parameters in
the URL:
- `start`: The start time for the query as a nanosecond Unix epoch. Defaults to 6 hours ago.
- `end`: The start time for the query as a nanosecond Unix epoch. Defaults to now.
In microservices mode, `/api/prom/label/<name>/values` is exposed by the querier.
Response:
```
{
"values": [
<label value>,
...
]
}
```
### Examples
```bash
$ curl -G -s "http://localhost:3100/api/prom/label/foo/values" | jq
{
"values": [
"cat",
"dog",
"axolotl"
]
}
``` ```
## `POST /api/prom/push` ## `POST /api/prom/push`

@ -35,5 +35,5 @@ func (q *LabelQuery) ListLabels(c *client.Client) []string {
if err != nil { if err != nil {
log.Fatalf("Error doing request: %+v", err) log.Fatalf("Error doing request: %+v", err)
} }
return labelResponse.Values return labelResponse.Data
} }

@ -12,7 +12,8 @@ import (
// LabelResponse represents the http json response to a label query // LabelResponse represents the http json response to a label query
type LabelResponse struct { type LabelResponse struct {
Values []string `json:"values,omitempty"` Status string `json:"status"`
Data []string `json:"data,omitempty"`
} }
// LabelSet is a key/value pair mapping of labels // LabelSet is a key/value pair mapping of labels

@ -37,7 +37,7 @@ var queryTests = []struct {
"entries":[ "entries":[
{ {
"ts": "2019-09-13T18:32:22.380001319Z", "ts": "2019-09-13T18:32:22.380001319Z",
"line": "super line" "line": "super line"
} }
] ]
} }
@ -95,7 +95,7 @@ var tailTests = []struct {
"entries": [ "entries": [
{ {
"ts": "2019-09-13T18:32:22.380001319Z", "ts": "2019-09-13T18:32:22.380001319Z",
"line": "super line" "line": "super line"
} }
] ]
} }

@ -1,5 +1,5 @@
// Package marshal converts internal objects to loghttp model objects. This package is designed to work with // Package marshal converts internal objects to loghttp model objects. This
// models in pkg/loghttp. // package is designed to work with models in pkg/loghttp.
package marshal package marshal
import ( import (
@ -14,7 +14,8 @@ import (
"github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/promql"
) )
// WriteQueryResponseJSON marshals the promql.Value to v1 loghttp JSON and then writes it to the provided io.Writer // WriteQueryResponseJSON marshals the promql.Value to v1 loghttp JSON and then
// writes it to the provided io.Writer.
func WriteQueryResponseJSON(v promql.Value, w io.Writer) error { func WriteQueryResponseJSON(v promql.Value, w io.Writer) error {
value, err := NewResultValue(v) value, err := NewResultValue(v)
@ -34,14 +35,19 @@ func WriteQueryResponseJSON(v promql.Value, w io.Writer) error {
return json.NewEncoder(w).Encode(q) return json.NewEncoder(w).Encode(q)
} }
// WriteLabelResponseJSON marshals a logproto.LabelResponse to v1 loghttp JSON and then writes it to the provided io.Writer // WriteLabelResponseJSON marshals a logproto.LabelResponse to v1 loghttp JSON
// Note that it simply directly marshals the value passed in. This is because the label currently marshals // and then writes it to the provided io.Writer.
// cleanly to the v1 http protocol. If this ever changes, it will be caught by testing.
func WriteLabelResponseJSON(l logproto.LabelResponse, w io.Writer) error { func WriteLabelResponseJSON(l logproto.LabelResponse, w io.Writer) error {
return json.NewEncoder(w).Encode(l) v1Response := loghttp.LabelResponse{
Status: "success",
Data: l.GetValues(),
}
return json.NewEncoder(w).Encode(v1Response)
} }
// WriteTailResponseJSON marshals the legacy.TailResponse to v1 loghttp JSON and then writes it to the provided connection // WriteTailResponseJSON marshals the legacy.TailResponse to v1 loghttp JSON and
// then writes it to the provided connection.
func WriteTailResponseJSON(r legacy.TailResponse, c *websocket.Conn) error { func WriteTailResponseJSON(r legacy.TailResponse, c *websocket.Conn) error {
v1Response, err := NewTailResponse(r) v1Response, err := NewTailResponse(r)

@ -212,7 +212,7 @@ var labelTests = []struct {
"value", "value",
}, },
}, },
`{"values": ["label1", "test", "value"]}`, `{"status": "success", "data": ["label1", "test", "value"]}`,
}, },
} }

Loading…
Cancel
Save