@ -11,7 +11,6 @@ import (
"github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/promql"
"github.com/weaveworks/common/httpgrpc"
"github.com/weaveworks/common/middleware"
"github.com/weaveworks/common/user"
"github.com/grafana/loki/pkg/loghttp"
@ -19,13 +18,11 @@ import (
"github.com/grafana/loki/pkg/logql"
"github.com/grafana/loki/pkg/logql/marshal"
marshal_legacy "github.com/grafana/loki/pkg/logql/marshal/legacy"
serverutil "github.com/grafana/loki/pkg/util/server"
)
const (
wsPingPeriod = 1 * time . Second
// StatusClientClosedRequest is the status code for when a client request cancellation of an http request
StatusClientClosedRequest = 499
)
type QueryResponse struct {
@ -41,24 +38,24 @@ func (q *Querier) RangeQueryHandler(w http.ResponseWriter, r *http.Request) {
request , err := loghttp . ParseRangeQuery ( r )
if err != nil {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
if err := q . validateEntriesLimits ( ctx , request . Limit ) ; err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
query := q . engine . NewRangeQuery ( request . Query , request . Start , request . End , request . Step , request . Interval , request . Direction , request . Limit )
result , err := query . Exec ( ctx )
if err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
if err := marshal . WriteQueryResponseJSON ( result , w ) ; err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
}
@ -71,24 +68,24 @@ func (q *Querier) InstantQueryHandler(w http.ResponseWriter, r *http.Request) {
request , err := loghttp . ParseInstantQuery ( r )
if err != nil {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
if err := q . validateEntriesLimits ( ctx , request . Limit ) ; err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
query := q . engine . NewInstantQuery ( request . Query , request . Ts , request . Direction , request . Limit )
result , err := query . Exec ( ctx )
if err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
if err := marshal . WriteQueryResponseJSON ( result , w ) ; err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
}
@ -101,41 +98,41 @@ func (q *Querier) LogQueryHandler(w http.ResponseWriter, r *http.Request) {
request , err := loghttp . ParseRangeQuery ( r )
if err != nil {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
request . Query , err = parseRegexQuery ( r )
if err != nil {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
expr , err := logql . ParseExpr ( request . Query )
if err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
// short circuit metric queries
if _ , ok := expr . ( logql . SampleExpr ) ; ok {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , "legacy endpoints only support %s result type" , logql . ValueTypeStreams ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , "legacy endpoints only support %s result type" , logql . ValueTypeStreams ) , w )
return
}
if err := q . validateEntriesLimits ( ctx , request . Limit ) ; err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
query := q . engine . NewRangeQuery ( request . Query , request . Start , request . End , request . Step , request . Interval , request . Direction , request . Limit )
result , err := query . Exec ( ctx )
if err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
if err := marshal_legacy . WriteQueryResponseJSON ( result , w ) ; err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
}
@ -144,13 +141,13 @@ func (q *Querier) LogQueryHandler(w http.ResponseWriter, r *http.Request) {
func ( q * Querier ) LabelHandler ( w http . ResponseWriter , r * http . Request ) {
req , err := loghttp . ParseLabelQuery ( r )
if err != nil {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
resp , err := q . Label ( r . Context ( ) , req )
if err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
@ -160,7 +157,7 @@ func (q *Querier) LabelHandler(w http.ResponseWriter, r *http.Request) {
err = marshal_legacy . WriteLabelResponseJSON ( * resp , w )
}
if err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
}
@ -174,13 +171,13 @@ func (q *Querier) TailHandler(w http.ResponseWriter, r *http.Request) {
req , err := loghttp . ParseTailQuery ( r )
if err != nil {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
req . Query , err = parseRegexQuery ( r )
if err != nil {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
@ -281,39 +278,23 @@ func (q *Querier) TailHandler(w http.ResponseWriter, r *http.Request) {
func ( q * Querier ) SeriesHandler ( w http . ResponseWriter , r * http . Request ) {
req , err := loghttp . ParseSeriesQuery ( r )
if err != nil {
w riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
serverutil . W riteError( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
resp , err := q . Series ( r . Context ( ) , req )
if err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
err = marshal . WriteSeriesResponseJSON ( * resp , w )
if err != nil {
w riteError( err , w )
serverutil . W riteError( err , w )
return
}
}
// NewPrepopulateMiddleware creates a middleware which will parse incoming http forms.
// This is important because some endpoints can POST x-www-form-urlencoded bodies instead of GET w/ query strings.
func NewPrepopulateMiddleware ( ) middleware . Interface {
return middleware . Func ( func ( next http . Handler ) http . Handler {
return http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
err := req . ParseForm ( )
if err != nil {
writeError ( httpgrpc . Errorf ( http . StatusBadRequest , err . Error ( ) ) , w )
return
}
next . ServeHTTP ( w , req )
} )
} )
}
// parseRegexQuery parses regex and query querystring from httpRequest and returns the combined LogQL query.
// This is used only to keep regexp query string support until it gets fully deprecated.
func parseRegexQuery ( httpRequest * http . Request ) ( string , error ) {
@ -329,23 +310,6 @@ func parseRegexQuery(httpRequest *http.Request) (string, error) {
return query , nil
}
func writeError ( err error , w http . ResponseWriter ) {
switch {
case err == context . Canceled :
http . Error ( w , err . Error ( ) , StatusClientClosedRequest )
case err == context . DeadlineExceeded :
http . Error ( w , err . Error ( ) , http . StatusGatewayTimeout )
case logql . IsParseError ( err ) :
http . Error ( w , err . Error ( ) , http . StatusBadRequest )
default :
if grpcErr , ok := httpgrpc . HTTPResponseFromError ( err ) ; ok {
http . Error ( w , string ( grpcErr . Body ) , int ( grpcErr . Code ) )
return
}
http . Error ( w , err . Error ( ) , http . StatusInternalServerError )
}
}
func ( q * Querier ) validateEntriesLimits ( ctx context . Context , limit uint32 ) error {
userID , err := user . ExtractOrgID ( ctx )
if err != nil {