| 
									
										
										
										
											2023-01-25 11:30:47 +08:00
										 |  |  | // Copyright 2016 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package v1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"unsafe" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	jsoniter "github.com/json-iterator/go" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/model/exemplar" | 
					
						
							| 
									
										
										
										
											2023-07-05 05:59:43 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/model/labels" | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/promql" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/util/jsonutil" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2024-04-29 03:35:01 +08:00
										 |  |  | 	jsoniter.RegisterTypeEncoderFunc("promql.Vector", unsafeMarshalVectorJSON, neverEmpty) | 
					
						
							|  |  |  | 	jsoniter.RegisterTypeEncoderFunc("promql.Matrix", unsafeMarshalMatrixJSON, neverEmpty) | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | 	jsoniter.RegisterTypeEncoderFunc("promql.Series", unsafeMarshalSeriesJSON, neverEmpty) | 
					
						
							|  |  |  | 	jsoniter.RegisterTypeEncoderFunc("promql.Sample", unsafeMarshalSampleJSON, neverEmpty) | 
					
						
							|  |  |  | 	jsoniter.RegisterTypeEncoderFunc("promql.FPoint", unsafeMarshalFPointJSON, neverEmpty) | 
					
						
							|  |  |  | 	jsoniter.RegisterTypeEncoderFunc("promql.HPoint", unsafeMarshalHPointJSON, neverEmpty) | 
					
						
							| 
									
										
										
										
											2024-04-29 03:26:51 +08:00
										 |  |  | 	jsoniter.RegisterTypeEncoderFunc("exemplar.Exemplar", marshalExemplarJSON, neverEmpty) | 
					
						
							| 
									
										
										
										
											2023-07-05 05:59:43 +08:00
										 |  |  | 	jsoniter.RegisterTypeEncoderFunc("labels.Labels", unsafeMarshalLabelsJSON, labelsIsEmpty) | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-25 11:30:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // JSONCodec is a Codec that encodes API responses as JSON.
 | 
					
						
							|  |  |  | type JSONCodec struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-27 10:27:09 +08:00
										 |  |  | func (j JSONCodec) ContentType() MIMEType { | 
					
						
							|  |  |  | 	return MIMEType{Type: "application", SubType: "json"} | 
					
						
							| 
									
										
										
										
											2023-01-25 11:30:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (j JSONCodec) CanEncode(_ *Response) bool { | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (j JSONCodec) Encode(resp *Response) ([]byte, error) { | 
					
						
							|  |  |  | 	json := jsoniter.ConfigCompatibleWithStandardLibrary | 
					
						
							|  |  |  | 	return json.Marshal(resp) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // marshalSeriesJSON writes something like the following:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	{
 | 
					
						
							|  |  |  | //	   "metric" : {
 | 
					
						
							|  |  |  | //	      "__name__" : "up",
 | 
					
						
							|  |  |  | //	      "job" : "prometheus",
 | 
					
						
							|  |  |  | //	      "instance" : "localhost:9090"
 | 
					
						
							|  |  |  | //	   },
 | 
					
						
							|  |  |  | //	   "values": [
 | 
					
						
							|  |  |  | //	      [ 1435781451.781, "1" ],
 | 
					
						
							|  |  |  | //	      < more values>
 | 
					
						
							|  |  |  | //	   ],
 | 
					
						
							|  |  |  | //	   "histograms": [
 | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | //	      [ 1435781451.781, { < histogram, see jsonutil.MarshalHistogram > } ],
 | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | //	      < more histograms >
 | 
					
						
							|  |  |  | //	   ],
 | 
					
						
							|  |  |  | //	},
 | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | func unsafeMarshalSeriesJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	s := *((*promql.Series)(ptr)) | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | 	marshalSeriesJSON(s, stream) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func marshalSeriesJSON(s promql.Series, stream *jsoniter.Stream) { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	stream.WriteObjectStart() | 
					
						
							|  |  |  | 	stream.WriteObjectField(`metric`) | 
					
						
							| 
									
										
										
										
											2023-07-13 22:39:54 +08:00
										 |  |  | 	marshalLabelsJSON(s.Metric, stream) | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	for i, p := range s.Floats { | 
					
						
							|  |  |  | 		stream.WriteMore() | 
					
						
							|  |  |  | 		if i == 0 { | 
					
						
							|  |  |  | 			stream.WriteObjectField(`values`) | 
					
						
							|  |  |  | 			stream.WriteArrayStart() | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | 		marshalFPointJSON(p, stream) | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	if len(s.Floats) > 0 { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 		stream.WriteArrayEnd() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	for i, p := range s.Histograms { | 
					
						
							|  |  |  | 		stream.WriteMore() | 
					
						
							|  |  |  | 		if i == 0 { | 
					
						
							|  |  |  | 			stream.WriteObjectField(`histograms`) | 
					
						
							|  |  |  | 			stream.WriteArrayStart() | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | 		marshalHPointJSON(p, stream) | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if len(s.Histograms) > 0 { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 		stream.WriteArrayEnd() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	stream.WriteObjectEnd() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-29 03:26:51 +08:00
										 |  |  | // In the Prometheus API we render an empty object as `[]` or similar.
 | 
					
						
							|  |  |  | func neverEmpty(unsafe.Pointer) bool { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshalSampleJSON writes something like the following for normal value samples:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	{
 | 
					
						
							|  |  |  | //	   "metric" : {
 | 
					
						
							|  |  |  | //	      "__name__" : "up",
 | 
					
						
							|  |  |  | //	      "job" : "prometheus",
 | 
					
						
							|  |  |  | //	      "instance" : "localhost:9090"
 | 
					
						
							|  |  |  | //	   },
 | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | //	   "value": [ 1435781451.781, "1.234" ]
 | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | //	},
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // For histogram samples, it writes something like this:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	{
 | 
					
						
							|  |  |  | //	   "metric" : {
 | 
					
						
							|  |  |  | //	      "__name__" : "up",
 | 
					
						
							|  |  |  | //	      "job" : "prometheus",
 | 
					
						
							|  |  |  | //	      "instance" : "localhost:9090"
 | 
					
						
							|  |  |  | //	   },
 | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | //	   "histogram": [ 1435781451.781, { < histogram, see jsonutil.MarshalHistogram > } ]
 | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | //	},
 | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | func unsafeMarshalSampleJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	s := *((*promql.Sample)(ptr)) | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | 	marshalSampleJSON(s, stream) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func marshalSampleJSON(s promql.Sample, stream *jsoniter.Stream) { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	stream.WriteObjectStart() | 
					
						
							|  |  |  | 	stream.WriteObjectField(`metric`) | 
					
						
							| 
									
										
										
										
											2023-07-13 22:39:54 +08:00
										 |  |  | 	marshalLabelsJSON(s.Metric, stream) | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	stream.WriteMore() | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	if s.H == nil { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 		stream.WriteObjectField(`value`) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		stream.WriteObjectField(`histogram`) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	stream.WriteArrayStart() | 
					
						
							|  |  |  | 	jsonutil.MarshalTimestamp(s.T, stream) | 
					
						
							|  |  |  | 	stream.WriteMore() | 
					
						
							|  |  |  | 	if s.H == nil { | 
					
						
							|  |  |  | 		jsonutil.MarshalFloat(s.F, stream) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		jsonutil.MarshalHistogram(s.H, stream) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	stream.WriteArrayEnd() | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	stream.WriteObjectEnd() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | // marshalFPointJSON writes `[ts, "1.234"]`.
 | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | func unsafeMarshalFPointJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	p := *((*promql.FPoint)(ptr)) | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | 	marshalFPointJSON(p, stream) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func marshalFPointJSON(p promql.FPoint, stream *jsoniter.Stream) { | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	stream.WriteArrayStart() | 
					
						
							|  |  |  | 	jsonutil.MarshalTimestamp(p.T, stream) | 
					
						
							|  |  |  | 	stream.WriteMore() | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	jsonutil.MarshalFloat(p.F, stream) | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	stream.WriteArrayEnd() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | // marshalHPointJSON writes `[ts, { < histogram, see jsonutil.MarshalHistogram > } ]`.
 | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | func unsafeMarshalHPointJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	p := *((*promql.HPoint)(ptr)) | 
					
						
							| 
									
										
										
										
											2024-04-29 03:29:03 +08:00
										 |  |  | 	marshalHPointJSON(p, stream) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func marshalHPointJSON(p promql.HPoint, stream *jsoniter.Stream) { | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	stream.WriteArrayStart() | 
					
						
							|  |  |  | 	jsonutil.MarshalTimestamp(p.T, stream) | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 	stream.WriteMore() | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	jsonutil.MarshalHistogram(p.H, stream) | 
					
						
							|  |  |  | 	stream.WriteArrayEnd() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // marshalExemplarJSON writes.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	{
 | 
					
						
							|  |  |  | //	   labels: <labels>,
 | 
					
						
							|  |  |  | //	   value: "<string>",
 | 
					
						
							|  |  |  | //	   timestamp: <float>
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | func marshalExemplarJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
					
						
							|  |  |  | 	p := *((*exemplar.Exemplar)(ptr)) | 
					
						
							|  |  |  | 	stream.WriteObjectStart() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// "labels" key.
 | 
					
						
							|  |  |  | 	stream.WriteObjectField(`labels`) | 
					
						
							| 
									
										
										
										
											2023-07-13 22:39:54 +08:00
										 |  |  | 	marshalLabelsJSON(p.Labels, stream) | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// "value" key.
 | 
					
						
							|  |  |  | 	stream.WriteMore() | 
					
						
							|  |  |  | 	stream.WriteObjectField(`value`) | 
					
						
							| 
									
										
										
										
											2023-07-04 11:26:13 +08:00
										 |  |  | 	jsonutil.MarshalFloat(p.Value, stream) | 
					
						
							| 
									
										
										
										
											2023-01-31 11:53:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// "timestamp" key.
 | 
					
						
							|  |  |  | 	stream.WriteMore() | 
					
						
							|  |  |  | 	stream.WriteObjectField(`timestamp`) | 
					
						
							|  |  |  | 	jsonutil.MarshalTimestamp(p.Ts, stream) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	stream.WriteObjectEnd() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-05 05:59:43 +08:00
										 |  |  | 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() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-04-29 03:35:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Marshal a Vector as `[sample,sample,...]` - empty Vector is `[]`.
 | 
					
						
							|  |  |  | func unsafeMarshalVectorJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
					
						
							|  |  |  | 	v := *((*promql.Vector)(ptr)) | 
					
						
							|  |  |  | 	stream.WriteArrayStart() | 
					
						
							| 
									
										
										
										
											2024-05-04 01:07:49 +08:00
										 |  |  | 	for i, s := range v { | 
					
						
							| 
									
										
										
										
											2024-04-29 03:35:01 +08:00
										 |  |  | 		marshalSampleJSON(s, stream) | 
					
						
							| 
									
										
										
										
											2024-05-04 01:07:49 +08:00
										 |  |  | 		if i != len(v)-1 { | 
					
						
							|  |  |  | 			stream.WriteMore() | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-04-29 03:35:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	stream.WriteArrayEnd() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Marshal a Matrix as `[series,series,...]` - empty Matrix is `[]`.
 | 
					
						
							|  |  |  | func unsafeMarshalMatrixJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
					
						
							|  |  |  | 	m := *((*promql.Matrix)(ptr)) | 
					
						
							|  |  |  | 	stream.WriteArrayStart() | 
					
						
							| 
									
										
										
										
											2024-05-04 01:07:49 +08:00
										 |  |  | 	for i, s := range m { | 
					
						
							| 
									
										
										
										
											2024-04-29 03:35:01 +08:00
										 |  |  | 		marshalSeriesJSON(s, stream) | 
					
						
							| 
									
										
										
										
											2024-05-04 01:07:49 +08:00
										 |  |  | 		if i != len(m)-1 { | 
					
						
							|  |  |  | 			stream.WriteMore() | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-04-29 03:35:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	stream.WriteArrayEnd() | 
					
						
							|  |  |  | } |