2023-06-20 05:55:12 +00:00
|
|
|
package logsql
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
|
2023-06-21 08:10:45 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
|
2023-06-20 05:55:12 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
|
|
|
|
)
|
|
|
|
|
2023-06-21 08:10:45 +00:00
|
|
|
var (
|
|
|
|
maxSortBufferSize = flagutil.NewBytes("select.maxSortBufferSize", 1024*1024, "Query results from /select/logsql/query are automatically sorted by _time "+
|
2023-07-19 08:10:51 +00:00
|
|
|
"if their summary size doesn't exceed this value; otherwise, query results are streamed in the response without sorting; "+
|
|
|
|
"too big value for this flag may result in high memory usage since the sorting is performed in memory")
|
2023-06-21 08:10:45 +00:00
|
|
|
)
|
|
|
|
|
2023-06-20 05:55:12 +00:00
|
|
|
// ProcessQueryRequest handles /select/logsql/query request
|
|
|
|
func ProcessQueryRequest(w http.ResponseWriter, r *http.Request, stopCh <-chan struct{}) {
|
|
|
|
// Extract tenantID
|
|
|
|
tenantID, err := logstorage.GetTenantIDFromRequest(r)
|
|
|
|
if err != nil {
|
|
|
|
httpserver.Errorf(w, r, "%s", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
qStr := r.FormValue("query")
|
|
|
|
q, err := logstorage.ParseQuery(qStr)
|
|
|
|
if err != nil {
|
|
|
|
httpserver.Errorf(w, r, "cannot parse query [%s]: %s", qStr, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/stream+json; charset=utf-8")
|
|
|
|
|
2023-06-21 08:10:45 +00:00
|
|
|
sw := getSortWriter()
|
|
|
|
sw.Init(w, maxSortBufferSize.IntN())
|
2023-06-20 05:55:12 +00:00
|
|
|
tenantIDs := []logstorage.TenantID{tenantID}
|
|
|
|
vlstorage.RunQuery(tenantIDs, q, stopCh, func(columns []logstorage.BlockColumn) {
|
|
|
|
if len(columns) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
rowsCount := len(columns[0].Values)
|
|
|
|
|
|
|
|
bb := blockResultPool.Get()
|
|
|
|
for rowIdx := 0; rowIdx < rowsCount; rowIdx++ {
|
|
|
|
WriteJSONRow(bb, columns, rowIdx)
|
|
|
|
}
|
2023-06-21 08:10:45 +00:00
|
|
|
sw.MustWrite(bb.B)
|
2023-06-20 05:55:12 +00:00
|
|
|
blockResultPool.Put(bb)
|
|
|
|
})
|
2023-06-21 08:10:45 +00:00
|
|
|
sw.FinalFlush()
|
|
|
|
putSortWriter(sw)
|
2023-06-20 05:55:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var blockResultPool bytesutil.ByteBufferPool
|