Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(format_query): Change response type to application/json #9016

Merged
merged 4 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

* [8953](https://github.com/grafana/loki/pull/8953) **dannykopping**: Querier: block queries by hash.
* [8851](https://github.com/grafana/loki/pull/8851) **jeschkies**: Introduce limit to require a set of labels for selecting streams.
* [9016](https://github.com/grafana/loki/pull/9016) **kavirajk**: Change response type of `format_query` handler to `application/json`

##### Fixes

Expand Down
9 changes: 9 additions & 0 deletions docs/sources/api/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,15 @@ Params:

The `/loki/api/v1/format_query` endpoint allows to format LogQL queries. It returns an error if the passed LogQL is invalid. It is exposed by all Loki components and helps to improve readability and the debugging experience of LogQL queries.

The following example formats the expression LogQL `{foo= "bar"}` into

```json
{
"status" : "success",
"data" : "{foo=\"bar\"}"
}
```

## List series

The Series API is available under the following:
Expand Down
41 changes: 34 additions & 7 deletions pkg/loki/format_query_handler.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,51 @@
package loki

import (
"fmt"
"encoding/json"
"net/http"

"github.com/grafana/loki/pkg/logql/syntax"
serverutil "github.com/grafana/loki/pkg/util/server"
"github.com/grafana/loki/pkg/util/server"
)

func formatQueryHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
statusCode = http.StatusOK
status = "success"
formatted string
errStr string
)

expr, err := syntax.ParseExpr(r.FormValue("query"))
if err != nil {
serverutil.WriteError(err, w)
return
statusCode = http.StatusBadRequest
status = "invalid-query"
errStr = err.Error()
}

if err == nil {
formatted = syntax.Prettify(expr)
}

resp := FormatQueryResponse{
Status: status,
Data: formatted,
Err: errStr,
}

w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(statusCode)

if err := json.NewEncoder(w).Encode(resp); err != nil {
server.WriteError(err, w)
}

fmt.Fprintf(w, "%s", syntax.Prettify(expr))
}
}

type FormatQueryResponse struct {
Status string `json:"status"`
Data string `json:"data,omitempty"`
Err string `json:"error,omitempty"`
}
55 changes: 55 additions & 0 deletions pkg/loki/format_query_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package loki

import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_formatQueryHandlerResponse(t *testing.T) {
cases := []struct {
name string
query string
expected FormatQueryResponse
}{
{
name: "happy-path",
query: `{foo="bar"}`,
expected: FormatQueryResponse{
Status: "success",
Data: `{foo="bar"}`,
},
},
{
name: "invalid-query",
query: `{foo="bar}`,
expected: FormatQueryResponse{
Status: "invalid-query",
Err: "parse error at line 1, col 6: literal not terminated",
},
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost:808?query=%s", tc.query), nil)
require.NoError(t, err)

w := httptest.NewRecorder()

formatQueryHandler()(w, req)

var got FormatQueryResponse

err = json.NewDecoder(w.Body).Decode(&got)
require.NoError(t, err)

assert.Equal(t, tc.expected, got)
})
}
}