[v10.1.x] Prometheus: Handle the response with different field key order (#74621)

* Prometheus: Handle the response with different field key order (#74567)

* Handle the response with different field key order

* More unit tests to cover edge cases

* Cover more edge cases

* make it simpler

* Better test inputs

(cherry picked from commit 3107459e57)

* Adjust the code for 10.1.x
This commit is contained in:
ismail simsek
2023-09-11 12:53:54 +02:00
committed by GitHub
parent 246b414c58
commit 269fe354ca
2 changed files with 103 additions and 24 deletions
+46 -24
View File
@@ -106,37 +106,30 @@ func readPrometheusData(iter *jsoniter.Iterator, opt Options) backend.DataRespon
resultType := ""
var rsp backend.DataResponse
resultTypeFound := false
var resultBytes []byte
for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
switch l1Field {
case "resultType":
resultType = iter.ReadString()
resultTypeFound = true
// if we have saved resultBytes we will parse them here
// we saved them because when we had them we don't know the resultType
if len(resultBytes) > 0 {
ji := jsoniter.ParseBytes(jsoniter.ConfigDefault, resultBytes)
rsp = readResult(resultType, rsp, ji, opt)
}
case "result":
switch resultType {
case "matrix":
if opt.MatrixWideSeries {
rsp = readMatrixOrVectorWide(iter, resultType, opt)
} else {
rsp = readMatrixOrVectorMulti(iter, resultType, opt)
}
case "vector":
if opt.VectorWideSeries {
rsp = readMatrixOrVectorWide(iter, resultType, opt)
} else {
rsp = readMatrixOrVectorMulti(iter, resultType, opt)
}
case "streams":
rsp = readStream(iter)
case "string":
rsp = readString(iter)
case "scalar":
rsp = readScalar(iter)
default:
iter.Skip()
rsp = backend.DataResponse{
Error: fmt.Errorf("unknown result type: %s", resultType),
}
// for some rare cases resultType is coming after the result.
// when that happens we save the bytes and parse them after reading resultType
// see: https://github.com/grafana/grafana/issues/64693
if resultTypeFound {
rsp = readResult(resultType, rsp, iter, opt)
} else {
resultBytes = iter.SkipAndReturnBytes()
}
case "stats":
@@ -157,7 +150,36 @@ func readPrometheusData(iter *jsoniter.Iterator, opt Options) backend.DataRespon
logf("[data] TODO, support key: %s / %v\n", l1Field, v)
}
}
return rsp
}
// will read the result object based on the resultType and return a DataResponse
func readResult(resultType string, rsp backend.DataResponse, iter *jsoniter.Iterator, opt Options) backend.DataResponse {
switch resultType {
case "matrix":
if opt.MatrixWideSeries {
rsp = readMatrixOrVectorWide(iter, resultType, opt)
} else {
rsp = readMatrixOrVectorMulti(iter, resultType, opt)
}
case "vector":
if opt.VectorWideSeries {
rsp = readMatrixOrVectorWide(iter, resultType, opt)
} else {
rsp = readMatrixOrVectorMulti(iter, resultType, opt)
}
case "streams":
rsp = readStream(iter)
case "string":
rsp = readString(iter)
case "scalar":
rsp = readScalar(iter)
default:
iter.Skip()
rsp = backend.DataResponse{
Error: fmt.Errorf("unknown result type: %s", resultType),
}
}
return rsp
}