api: export point marshaling functions (#11323)

Export `marshalTimestamp` and `marshalValue` functions by moving them under their own util package.

Signed-off-by: Miguel Ángel Ortuño <ortuman@gmail.com>
This commit is contained in:
Miguel Ángel Ortuño 2022-09-29 16:46:48 +02:00 committed by GitHub
parent 83d738e263
commit e4b87a7a2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 44 deletions

62
util/jsonutil/marshal.go Normal file
View File

@ -0,0 +1,62 @@
// Copyright 2022 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 jsonutil
import (
"math"
"strconv"
jsoniter "github.com/json-iterator/go"
)
// MarshalTimestamp marshals a point timestamp using the passed jsoniter stream.
func MarshalTimestamp(t int64, stream *jsoniter.Stream) {
// Write out the timestamp as a float divided by 1000.
// This is ~3x faster than converting to a float.
if t < 0 {
stream.WriteRaw(`-`)
t = -t
}
stream.WriteInt64(t / 1000)
fraction := t % 1000
if fraction != 0 {
stream.WriteRaw(`.`)
if fraction < 100 {
stream.WriteRaw(`0`)
}
if fraction < 10 {
stream.WriteRaw(`0`)
}
stream.WriteInt64(fraction)
}
}
// MarshalValue marshals a point value using the passed jsoniter stream.
func MarshalValue(v float64, stream *jsoniter.Stream) {
stream.WriteRaw(`"`)
// Taken from https://github.com/json-iterator/go/blob/master/stream_float.go#L71 as a workaround
// to https://github.com/json-iterator/go/issues/365 (jsoniter, to follow json standard, doesn't allow inf/nan).
buf := stream.Buffer()
abs := math.Abs(v)
fmt := byte('f')
// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
if abs != 0 {
if abs < 1e-6 || abs >= 1e21 {
fmt = 'e'
}
}
buf = strconv.AppendFloat(buf, v, fmt, -1, 64)
stream.SetBuffer(buf)
stream.WriteRaw(`"`)
}

View File

@ -52,6 +52,7 @@ import (
"github.com/prometheus/prometheus/tsdb"
"github.com/prometheus/prometheus/tsdb/index"
"github.com/prometheus/prometheus/util/httputil"
"github.com/prometheus/prometheus/util/jsonutil"
"github.com/prometheus/prometheus/util/stats"
)
@ -1659,9 +1660,9 @@ OUTER:
func marshalPointJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) {
p := *((*promql.Point)(ptr))
stream.WriteArrayStart()
marshalTimestamp(p.T, stream)
jsonutil.MarshalTimestamp(p.T, stream)
stream.WriteMore()
marshalValue(p.V, stream)
jsonutil.MarshalValue(p.V, stream)
stream.WriteArrayEnd()
}
@ -1692,13 +1693,12 @@ func marshalExemplarJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) {
// "value" key.
stream.WriteMore()
stream.WriteObjectField(`value`)
marshalValue(p.Value, stream)
jsonutil.MarshalValue(p.Value, stream)
// "timestamp" key.
stream.WriteMore()
stream.WriteObjectField(`timestamp`)
marshalTimestamp(p.Ts, stream)
// marshalTimestamp(p.Ts, stream)
jsonutil.MarshalTimestamp(p.Ts, stream)
stream.WriteObjectEnd()
}
@ -1706,42 +1706,3 @@ func marshalExemplarJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) {
func marshalExemplarJSONEmpty(ptr unsafe.Pointer) bool {
return false
}
func marshalTimestamp(t int64, stream *jsoniter.Stream) {
// Write out the timestamp as a float divided by 1000.
// This is ~3x faster than converting to a float.
if t < 0 {
stream.WriteRaw(`-`)
t = -t
}
stream.WriteInt64(t / 1000)
fraction := t % 1000
if fraction != 0 {
stream.WriteRaw(`.`)
if fraction < 100 {
stream.WriteRaw(`0`)
}
if fraction < 10 {
stream.WriteRaw(`0`)
}
stream.WriteInt64(fraction)
}
}
func marshalValue(v float64, stream *jsoniter.Stream) {
stream.WriteRaw(`"`)
// Taken from https://github.com/json-iterator/go/blob/master/stream_float.go#L71 as a workaround
// to https://github.com/json-iterator/go/issues/365 (jsoniter, to follow json standard, doesn't allow inf/nan).
buf := stream.Buffer()
abs := math.Abs(v)
fmt := byte('f')
// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
if abs != 0 {
if abs < 1e-6 || abs >= 1e21 {
fmt = 'e'
}
}
buf = strconv.AppendFloat(buf, v, fmt, -1, 64)
stream.SetBuffer(buf)
stream.WriteRaw(`"`)
}