diff --git a/web/api/v1/json_codec.go b/web/api/v1/json_codec.go index 62e7563b1..3ac99a02d 100644 --- a/web/api/v1/json_codec.go +++ b/web/api/v1/json_codec.go @@ -19,6 +19,7 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/prometheus/prometheus/model/exemplar" + "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/util/jsonutil" ) @@ -29,6 +30,7 @@ func init() { jsoniter.RegisterTypeEncoderFunc("promql.FPoint", marshalFPointJSON, marshalPointJSONIsEmpty) jsoniter.RegisterTypeEncoderFunc("promql.HPoint", marshalHPointJSON, marshalPointJSONIsEmpty) jsoniter.RegisterTypeEncoderFunc("exemplar.Exemplar", marshalExemplarJSON, marshalExemplarJSONEmpty) + jsoniter.RegisterTypeEncoderFunc("labels.Labels", unsafeMarshalLabelsJSON, labelsIsEmpty) } // JSONCodec is a Codec that encodes API responses as JSON. @@ -217,3 +219,28 @@ func marshalExemplarJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { func marshalExemplarJSONEmpty(unsafe.Pointer) bool { return false } + +func unsafeMarshalLabelsJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { + labelsPtr := (*labels.Labels)(ptr) + marshalLabelsJSON(*labelsPtr, stream) +} + +func marshalLabelsJSON(lbls labels.Labels, stream *jsoniter.Stream) { + stream.WriteObjectStart() + i := 0 + lbls.Range(func(v labels.Label) { + if i != 0 { + stream.WriteMore() + } + i++ + stream.WriteString(v.Name) + stream.WriteRaw(`:`) + stream.WriteString(v.Value) + }) + stream.WriteObjectEnd() +} + +func labelsIsEmpty(ptr unsafe.Pointer) bool { + labelsPtr := (*labels.Labels)(ptr) + return labelsPtr.IsEmpty() +}