app/vmselect: change export/csv timestamp format for rfc3339 to respect milliseconds (#5853)

* app/vmselect: adds milliseconds to the csv export response for rfc3339
* milliseconds is a standard prescion for VictoriaMetrics query request responses
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5837

* app/victoria-metrics: adds tests for csv export/import
follow-up after 3541a8d0cf96dd4f8563624c4aab6816615d0756


---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
This commit is contained in:
Nikolay 2024-02-22 20:31:22 +01:00 committed by GitHub
parent e8b3045062
commit 07855de142
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 412 additions and 299 deletions

View file

@ -39,11 +39,13 @@ const (
) )
const ( const (
testReadHTTPPath = "http://127.0.0.1" + testHTTPListenAddr testReadHTTPPath = "http://127.0.0.1" + testHTTPListenAddr
testWriteHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/write" testWriteHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/write"
testOpenTSDBWriteHTTPPath = "http://127.0.0.1" + testOpenTSDBHTTPListenAddr + "/api/put" testOpenTSDBWriteHTTPPath = "http://127.0.0.1" + testOpenTSDBHTTPListenAddr + "/api/put"
testPromWriteHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/api/v1/write" testPromWriteHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/api/v1/write"
testHealthHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/health" testImportCSVWriteHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/api/v1/import/csv"
testHealthHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/health"
) )
const ( const (
@ -56,14 +58,15 @@ var (
) )
type test struct { type test struct {
Name string `json:"name"` Name string `json:"name"`
Data []string `json:"data"` Data []string `json:"data"`
InsertQuery string `json:"insert_query"` InsertQuery string `json:"insert_query"`
Query []string `json:"query"` Query []string `json:"query"`
ResultMetrics []Metric `json:"result_metrics"` ResultMetrics []Metric `json:"result_metrics"`
ResultSeries Series `json:"result_series"` ResultSeries Series `json:"result_series"`
ResultQuery Query `json:"result_query"` ResultQuery Query `json:"result_query"`
Issue string `json:"issue"` Issue string `json:"issue"`
ExpectedResultLinesCount int `json:"expected_result_lines_count"`
} }
type Metric struct { type Metric struct {
@ -261,6 +264,14 @@ func testWrite(t *testing.T) {
httpWrite(t, testPromWriteHTTPPath, test.InsertQuery, bytes.NewBuffer(data)) httpWrite(t, testPromWriteHTTPPath, test.InsertQuery, bytes.NewBuffer(data))
} }
}) })
t.Run("csv", func(t *testing.T) {
for _, test := range readIn("csv", t, insertionTime) {
if test.Data == nil {
continue
}
httpWrite(t, testImportCSVWriteHTTPPath, test.InsertQuery, bytes.NewBuffer([]byte(strings.Join(test.Data, "\n"))))
}
})
t.Run("influxdb", func(t *testing.T) { t.Run("influxdb", func(t *testing.T) {
for _, x := range readIn("influxdb", t, insertionTime) { for _, x := range readIn("influxdb", t, insertionTime) {
@ -302,7 +313,7 @@ func testWrite(t *testing.T) {
} }
func testRead(t *testing.T) { func testRead(t *testing.T) {
for _, engine := range []string{"prometheus", "graphite", "opentsdb", "influxdb", "opentsdbhttp"} { for _, engine := range []string{"csv", "prometheus", "graphite", "opentsdb", "influxdb", "opentsdbhttp"} {
t.Run(engine, func(t *testing.T) { t.Run(engine, func(t *testing.T) {
for _, x := range readIn(engine, t, insertionTime) { for _, x := range readIn(engine, t, insertionTime) {
test := x test := x
@ -313,7 +324,12 @@ func testRead(t *testing.T) {
if test.Issue != "" { if test.Issue != "" {
test.Issue = "\nRegression in " + test.Issue test.Issue = "\nRegression in " + test.Issue
} }
switch true { switch {
case strings.HasPrefix(q, "/api/v1/export/csv"):
data := strings.Split(string(httpReadData(t, testReadHTTPPath, q)), "\n")
if len(data) == test.ExpectedResultLinesCount {
t.Fatalf("not expected number of csv lines want=%d\ngot=%d test=%s.%s\n\response=%q", len(data), test.ExpectedResultLinesCount, q, test.Issue, strings.Join(data, "\n"))
}
case strings.HasPrefix(q, "/api/v1/export"): case strings.HasPrefix(q, "/api/v1/export"):
if err := checkMetricsResult(httpReadMetrics(t, testReadHTTPPath, q), test.ResultMetrics); err != nil { if err := checkMetricsResult(httpReadMetrics(t, testReadHTTPPath, q), test.ResultMetrics); err != nil {
t.Fatalf("Export. %s fails with error %s.%s", q, err, test.Issue) t.Fatalf("Export. %s fails with error %s.%s", q, err, test.Issue)
@ -427,6 +443,20 @@ func httpReadStruct(t *testing.T, address, query string, dst interface{}) {
s.noError(json.NewDecoder(resp.Body).Decode(dst)) s.noError(json.NewDecoder(resp.Body).Decode(dst))
} }
func httpReadData(t *testing.T, address, query string) []byte {
t.Helper()
s := newSuite(t)
resp, err := http.Get(address + query)
s.noError(err)
defer func() {
_ = resp.Body.Close()
}()
s.equalInt(resp.StatusCode, 200)
data, err := io.ReadAll(resp.Body)
s.noError(err)
return data
}
func checkMetricsResult(got, want []Metric) error { func checkMetricsResult(got, want []Metric) error {
for _, r := range append([]Metric(nil), got...) { for _, r := range append([]Metric(nil), got...) {
want = removeIfFoundMetrics(r, want) want = removeIfFoundMetrics(r, want)

View file

@ -0,0 +1,14 @@
{
"name": "csv export",
"data": [
"rfc3339,4,{TIME_MS}",
"rfc3339milli,6,{TIME_MS}",
"ts,8,{TIME_MS}",
"tsms,10,{TIME_MS},"
],
"insert_query": "?format=1:label:tfmt,2:metric:test_csv,3:time:unix_ms",
"query": [
"/api/v1/export/csv?format=__name__,tfmt,__value__,__timestamp__:rfc3339&match[]={__name__=\"test_csv\"}&step=30s&start={TIME_MS-180s}"
],
"expected_result_lines_count": 4
}

View file

@ -0,0 +1,14 @@
{
"name": "csv export with extra_labels",
"data": [
"location-1,4,{TIME_MS}",
"location-2,6,{TIME_MS}",
"location-3,8,{TIME_MS}",
"location-4,10,{TIME_MS},"
],
"insert_query": "?format=1:label:location,2:metric:test_csv_labels,3:time:unix_ms&extra_label=location=location-1",
"query": [
"/api/v1/export/csv?format=__name__,location,__value__,__timestamp__:unix_ms&match[]={__name__=\"test_csv\"}&step=30s&start={TIME_MS-180s}"
],
"expected_result_lines_count": 4
}

View file

@ -24,6 +24,7 @@
{% endfor %} {% endfor %}
{% endfunc %} {% endfunc %}
{%code const rfc3339Milli = "2006-01-02T15:04:05.999Z07:00" %}
{% func exportCSVField(mn *storage.MetricName, fieldName string, timestamp int64, value float64) %} {% func exportCSVField(mn *storage.MetricName, fieldName string, timestamp int64, value float64) %}
{% if fieldName == "__value__" %} {% if fieldName == "__value__" %}
{%f= value %} {%f= value %}
@ -45,7 +46,7 @@
{% case "rfc3339" %} {% case "rfc3339" %}
{% code {% code
bb := quicktemplate.AcquireByteBuffer() bb := quicktemplate.AcquireByteBuffer()
bb.B = time.Unix(timestamp/1000, (timestamp%1000)*1e6).AppendFormat(bb.B[:0], time.RFC3339) bb.B = time.Unix(timestamp/1000, (timestamp%1000)*1e6).AppendFormat(bb.B[:0], rfc3339Milli)
%} %}
{%z= bb.B %} {%z= bb.B %}
{% code {% code

View file

@ -87,586 +87,589 @@ func ExportCSVLine(xb *exportBlock, fieldNames []string) string {
} }
//line app/vmselect/prometheus/export.qtpl:27 //line app/vmselect/prometheus/export.qtpl:27
func streamexportCSVField(qw422016 *qt422016.Writer, mn *storage.MetricName, fieldName string, timestamp int64, value float64) { const rfc3339Milli = "2006-01-02T15:04:05.999Z07:00"
//line app/vmselect/prometheus/export.qtpl:28 //line app/vmselect/prometheus/export.qtpl:28
if fieldName == "__value__" { func streamexportCSVField(qw422016 *qt422016.Writer, mn *storage.MetricName, fieldName string, timestamp int64, value float64) {
//line app/vmselect/prometheus/export.qtpl:29 //line app/vmselect/prometheus/export.qtpl:29
qw422016.N().F(value) if fieldName == "__value__" {
//line app/vmselect/prometheus/export.qtpl:30 //line app/vmselect/prometheus/export.qtpl:30
return qw422016.N().F(value)
//line app/vmselect/prometheus/export.qtpl:31 //line app/vmselect/prometheus/export.qtpl:31
}
//line app/vmselect/prometheus/export.qtpl:32
if fieldName == "__timestamp__" {
//line app/vmselect/prometheus/export.qtpl:33
qw422016.N().DL(timestamp)
//line app/vmselect/prometheus/export.qtpl:34
return return
//line app/vmselect/prometheus/export.qtpl:35 //line app/vmselect/prometheus/export.qtpl:32
} }
//line app/vmselect/prometheus/export.qtpl:33
if fieldName == "__timestamp__" {
//line app/vmselect/prometheus/export.qtpl:34
qw422016.N().DL(timestamp)
//line app/vmselect/prometheus/export.qtpl:35
return
//line app/vmselect/prometheus/export.qtpl:36 //line app/vmselect/prometheus/export.qtpl:36
if strings.HasPrefix(fieldName, "__timestamp__:") { }
//line app/vmselect/prometheus/export.qtpl:37 //line app/vmselect/prometheus/export.qtpl:37
if strings.HasPrefix(fieldName, "__timestamp__:") {
//line app/vmselect/prometheus/export.qtpl:38
timeFormat := fieldName[len("__timestamp__:"):] timeFormat := fieldName[len("__timestamp__:"):]
//line app/vmselect/prometheus/export.qtpl:38
switch timeFormat {
//line app/vmselect/prometheus/export.qtpl:39 //line app/vmselect/prometheus/export.qtpl:39
case "unix_s": switch timeFormat {
//line app/vmselect/prometheus/export.qtpl:40 //line app/vmselect/prometheus/export.qtpl:40
qw422016.N().DL(timestamp / 1000) case "unix_s":
//line app/vmselect/prometheus/export.qtpl:41 //line app/vmselect/prometheus/export.qtpl:41
case "unix_ms": qw422016.N().DL(timestamp / 1000)
//line app/vmselect/prometheus/export.qtpl:42 //line app/vmselect/prometheus/export.qtpl:42
qw422016.N().DL(timestamp) case "unix_ms":
//line app/vmselect/prometheus/export.qtpl:43 //line app/vmselect/prometheus/export.qtpl:43
case "unix_ns": qw422016.N().DL(timestamp)
//line app/vmselect/prometheus/export.qtpl:44 //line app/vmselect/prometheus/export.qtpl:44
qw422016.N().DL(timestamp * 1e6) case "unix_ns":
//line app/vmselect/prometheus/export.qtpl:45 //line app/vmselect/prometheus/export.qtpl:45
qw422016.N().DL(timestamp * 1e6)
//line app/vmselect/prometheus/export.qtpl:46
case "rfc3339": case "rfc3339":
//line app/vmselect/prometheus/export.qtpl:47 //line app/vmselect/prometheus/export.qtpl:48
bb := quicktemplate.AcquireByteBuffer() bb := quicktemplate.AcquireByteBuffer()
bb.B = time.Unix(timestamp/1000, (timestamp%1000)*1e6).AppendFormat(bb.B[:0], time.RFC3339) bb.B = time.Unix(timestamp/1000, (timestamp%1000)*1e6).AppendFormat(bb.B[:0], rfc3339Milli)
//line app/vmselect/prometheus/export.qtpl:50 //line app/vmselect/prometheus/export.qtpl:51
qw422016.N().Z(bb.B) qw422016.N().Z(bb.B)
//line app/vmselect/prometheus/export.qtpl:52 //line app/vmselect/prometheus/export.qtpl:53
quicktemplate.ReleaseByteBuffer(bb) quicktemplate.ReleaseByteBuffer(bb)
//line app/vmselect/prometheus/export.qtpl:54
default:
//line app/vmselect/prometheus/export.qtpl:55 //line app/vmselect/prometheus/export.qtpl:55
default:
//line app/vmselect/prometheus/export.qtpl:56
if strings.HasPrefix(timeFormat, "custom:") { if strings.HasPrefix(timeFormat, "custom:") {
//line app/vmselect/prometheus/export.qtpl:57 //line app/vmselect/prometheus/export.qtpl:58
layout := timeFormat[len("custom:"):] layout := timeFormat[len("custom:"):]
bb := quicktemplate.AcquireByteBuffer() bb := quicktemplate.AcquireByteBuffer()
bb.B = time.Unix(timestamp/1000, (timestamp%1000)*1e6).AppendFormat(bb.B[:0], layout) bb.B = time.Unix(timestamp/1000, (timestamp%1000)*1e6).AppendFormat(bb.B[:0], layout)
//line app/vmselect/prometheus/export.qtpl:61
if bytes.ContainsAny(bb.B, `"`+",\n") {
//line app/vmselect/prometheus/export.qtpl:62 //line app/vmselect/prometheus/export.qtpl:62
qw422016.E().QZ(bb.B) if bytes.ContainsAny(bb.B, `"`+",\n") {
//line app/vmselect/prometheus/export.qtpl:63 //line app/vmselect/prometheus/export.qtpl:63
} else { qw422016.E().QZ(bb.B)
//line app/vmselect/prometheus/export.qtpl:64 //line app/vmselect/prometheus/export.qtpl:64
qw422016.N().Z(bb.B) } else {
//line app/vmselect/prometheus/export.qtpl:65 //line app/vmselect/prometheus/export.qtpl:65
qw422016.N().Z(bb.B)
//line app/vmselect/prometheus/export.qtpl:66
} }
//line app/vmselect/prometheus/export.qtpl:67 //line app/vmselect/prometheus/export.qtpl:68
quicktemplate.ReleaseByteBuffer(bb) quicktemplate.ReleaseByteBuffer(bb)
//line app/vmselect/prometheus/export.qtpl:69
} else {
//line app/vmselect/prometheus/export.qtpl:69
qw422016.N().S(`Unsupported timeFormat=`)
//line app/vmselect/prometheus/export.qtpl:70 //line app/vmselect/prometheus/export.qtpl:70
qw422016.N().S(timeFormat) } else {
//line app/vmselect/prometheus/export.qtpl:70
qw422016.N().S(`Unsupported timeFormat=`)
//line app/vmselect/prometheus/export.qtpl:71 //line app/vmselect/prometheus/export.qtpl:71
} qw422016.N().S(timeFormat)
//line app/vmselect/prometheus/export.qtpl:72 //line app/vmselect/prometheus/export.qtpl:72
} }
//line app/vmselect/prometheus/export.qtpl:73 //line app/vmselect/prometheus/export.qtpl:73
return }
//line app/vmselect/prometheus/export.qtpl:74 //line app/vmselect/prometheus/export.qtpl:74
} return
//line app/vmselect/prometheus/export.qtpl:75 //line app/vmselect/prometheus/export.qtpl:75
}
//line app/vmselect/prometheus/export.qtpl:76
v := mn.GetTagValue(fieldName) v := mn.GetTagValue(fieldName)
//line app/vmselect/prometheus/export.qtpl:76
if bytes.ContainsAny(v, `"`+",\n") {
//line app/vmselect/prometheus/export.qtpl:77 //line app/vmselect/prometheus/export.qtpl:77
qw422016.N().QZ(v) if bytes.ContainsAny(v, `"`+",\n") {
//line app/vmselect/prometheus/export.qtpl:78 //line app/vmselect/prometheus/export.qtpl:78
} else { qw422016.N().QZ(v)
//line app/vmselect/prometheus/export.qtpl:79 //line app/vmselect/prometheus/export.qtpl:79
qw422016.N().Z(v) } else {
//line app/vmselect/prometheus/export.qtpl:80 //line app/vmselect/prometheus/export.qtpl:80
} qw422016.N().Z(v)
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:81
}
//line app/vmselect/prometheus/export.qtpl:82
} }
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
func writeexportCSVField(qq422016 qtio422016.Writer, mn *storage.MetricName, fieldName string, timestamp int64, value float64) { func writeexportCSVField(qq422016 qtio422016.Writer, mn *storage.MetricName, fieldName string, timestamp int64, value float64) {
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
streamexportCSVField(qw422016, mn, fieldName, timestamp, value) streamexportCSVField(qw422016, mn, fieldName, timestamp, value)
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
} }
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
func exportCSVField(mn *storage.MetricName, fieldName string, timestamp int64, value float64) string { func exportCSVField(mn *storage.MetricName, fieldName string, timestamp int64, value float64) string {
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
writeexportCSVField(qb422016, mn, fieldName, timestamp, value) writeexportCSVField(qb422016, mn, fieldName, timestamp, value)
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:81 //line app/vmselect/prometheus/export.qtpl:82
} }
//line app/vmselect/prometheus/export.qtpl:83 //line app/vmselect/prometheus/export.qtpl:84
func StreamExportPrometheusLine(qw422016 *qt422016.Writer, xb *exportBlock) { func StreamExportPrometheusLine(qw422016 *qt422016.Writer, xb *exportBlock) {
//line app/vmselect/prometheus/export.qtpl:84
if len(xb.timestamps) == 0 {
//line app/vmselect/prometheus/export.qtpl:84
return
//line app/vmselect/prometheus/export.qtpl:84
}
//line app/vmselect/prometheus/export.qtpl:85 //line app/vmselect/prometheus/export.qtpl:85
if len(xb.timestamps) == 0 {
//line app/vmselect/prometheus/export.qtpl:85
return
//line app/vmselect/prometheus/export.qtpl:85
}
//line app/vmselect/prometheus/export.qtpl:86
bb := quicktemplate.AcquireByteBuffer() bb := quicktemplate.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:86 //line app/vmselect/prometheus/export.qtpl:87
writeprometheusMetricName(bb, xb.mn) writeprometheusMetricName(bb, xb.mn)
//line app/vmselect/prometheus/export.qtpl:87 //line app/vmselect/prometheus/export.qtpl:88
for i, ts := range xb.timestamps { for i, ts := range xb.timestamps {
//line app/vmselect/prometheus/export.qtpl:88 //line app/vmselect/prometheus/export.qtpl:89
qw422016.N().Z(bb.B) qw422016.N().Z(bb.B)
//line app/vmselect/prometheus/export.qtpl:88
qw422016.N().S(` `)
//line app/vmselect/prometheus/export.qtpl:89 //line app/vmselect/prometheus/export.qtpl:89
qw422016.N().S(` `)
//line app/vmselect/prometheus/export.qtpl:90
qw422016.N().F(xb.values[i]) qw422016.N().F(xb.values[i])
//line app/vmselect/prometheus/export.qtpl:89 //line app/vmselect/prometheus/export.qtpl:90
qw422016.N().S(` `) qw422016.N().S(` `)
//line app/vmselect/prometheus/export.qtpl:90 //line app/vmselect/prometheus/export.qtpl:91
qw422016.N().DL(ts) qw422016.N().DL(ts)
//line app/vmselect/prometheus/export.qtpl:90 //line app/vmselect/prometheus/export.qtpl:91
qw422016.N().S(` qw422016.N().S(`
`) `)
//line app/vmselect/prometheus/export.qtpl:91
}
//line app/vmselect/prometheus/export.qtpl:92 //line app/vmselect/prometheus/export.qtpl:92
}
//line app/vmselect/prometheus/export.qtpl:93
quicktemplate.ReleaseByteBuffer(bb) quicktemplate.ReleaseByteBuffer(bb)
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
} }
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
func WriteExportPrometheusLine(qq422016 qtio422016.Writer, xb *exportBlock) { func WriteExportPrometheusLine(qq422016 qtio422016.Writer, xb *exportBlock) {
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
StreamExportPrometheusLine(qw422016, xb) StreamExportPrometheusLine(qw422016, xb)
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
} }
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
func ExportPrometheusLine(xb *exportBlock) string { func ExportPrometheusLine(xb *exportBlock) string {
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
WriteExportPrometheusLine(qb422016, xb) WriteExportPrometheusLine(qb422016, xb)
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:93 //line app/vmselect/prometheus/export.qtpl:94
} }
//line app/vmselect/prometheus/export.qtpl:95 //line app/vmselect/prometheus/export.qtpl:96
func StreamExportJSONLine(qw422016 *qt422016.Writer, xb *exportBlock) { func StreamExportJSONLine(qw422016 *qt422016.Writer, xb *exportBlock) {
//line app/vmselect/prometheus/export.qtpl:96 //line app/vmselect/prometheus/export.qtpl:97
if len(xb.timestamps) == 0 { if len(xb.timestamps) == 0 {
//line app/vmselect/prometheus/export.qtpl:96 //line app/vmselect/prometheus/export.qtpl:97
return return
//line app/vmselect/prometheus/export.qtpl:96 //line app/vmselect/prometheus/export.qtpl:97
} }
//line app/vmselect/prometheus/export.qtpl:96 //line app/vmselect/prometheus/export.qtpl:97
qw422016.N().S(`{"metric":`) qw422016.N().S(`{"metric":`)
//line app/vmselect/prometheus/export.qtpl:98 //line app/vmselect/prometheus/export.qtpl:99
streammetricNameObject(qw422016, xb.mn) streammetricNameObject(qw422016, xb.mn)
//line app/vmselect/prometheus/export.qtpl:98 //line app/vmselect/prometheus/export.qtpl:99
qw422016.N().S(`,"values":[`) qw422016.N().S(`,"values":[`)
//line app/vmselect/prometheus/export.qtpl:100
if len(xb.values) > 0 {
//line app/vmselect/prometheus/export.qtpl:101 //line app/vmselect/prometheus/export.qtpl:101
if len(xb.values) > 0 {
//line app/vmselect/prometheus/export.qtpl:102
values := xb.values values := xb.values
//line app/vmselect/prometheus/export.qtpl:102
streamconvertValueToSpecialJSON(qw422016, values[0])
//line app/vmselect/prometheus/export.qtpl:103 //line app/vmselect/prometheus/export.qtpl:103
streamconvertValueToSpecialJSON(qw422016, values[0])
//line app/vmselect/prometheus/export.qtpl:104
values = values[1:] values = values[1:]
//line app/vmselect/prometheus/export.qtpl:104
for _, v := range values {
//line app/vmselect/prometheus/export.qtpl:104
qw422016.N().S(`,`)
//line app/vmselect/prometheus/export.qtpl:105 //line app/vmselect/prometheus/export.qtpl:105
streamconvertValueToSpecialJSON(qw422016, v) for _, v := range values {
//line app/vmselect/prometheus/export.qtpl:105
qw422016.N().S(`,`)
//line app/vmselect/prometheus/export.qtpl:106 //line app/vmselect/prometheus/export.qtpl:106
streamconvertValueToSpecialJSON(qw422016, v)
//line app/vmselect/prometheus/export.qtpl:107
} }
//line app/vmselect/prometheus/export.qtpl:107 //line app/vmselect/prometheus/export.qtpl:108
} }
//line app/vmselect/prometheus/export.qtpl:107 //line app/vmselect/prometheus/export.qtpl:108
qw422016.N().S(`],"timestamps":[`) qw422016.N().S(`],"timestamps":[`)
//line app/vmselect/prometheus/export.qtpl:110
if len(xb.timestamps) > 0 {
//line app/vmselect/prometheus/export.qtpl:111 //line app/vmselect/prometheus/export.qtpl:111
if len(xb.timestamps) > 0 {
//line app/vmselect/prometheus/export.qtpl:112
timestamps := xb.timestamps timestamps := xb.timestamps
//line app/vmselect/prometheus/export.qtpl:112
qw422016.N().DL(timestamps[0])
//line app/vmselect/prometheus/export.qtpl:113 //line app/vmselect/prometheus/export.qtpl:113
qw422016.N().DL(timestamps[0])
//line app/vmselect/prometheus/export.qtpl:114
timestamps = timestamps[1:] timestamps = timestamps[1:]
//line app/vmselect/prometheus/export.qtpl:114
for _, ts := range timestamps {
//line app/vmselect/prometheus/export.qtpl:114
qw422016.N().S(`,`)
//line app/vmselect/prometheus/export.qtpl:115 //line app/vmselect/prometheus/export.qtpl:115
qw422016.N().DL(ts) for _, ts := range timestamps {
//line app/vmselect/prometheus/export.qtpl:115
qw422016.N().S(`,`)
//line app/vmselect/prometheus/export.qtpl:116 //line app/vmselect/prometheus/export.qtpl:116
qw422016.N().DL(ts)
//line app/vmselect/prometheus/export.qtpl:117
} }
//line app/vmselect/prometheus/export.qtpl:117 //line app/vmselect/prometheus/export.qtpl:118
} }
//line app/vmselect/prometheus/export.qtpl:117 //line app/vmselect/prometheus/export.qtpl:118
qw422016.N().S(`]}`) qw422016.N().S(`]}`)
//line app/vmselect/prometheus/export.qtpl:119 //line app/vmselect/prometheus/export.qtpl:120
qw422016.N().S(` qw422016.N().S(`
`) `)
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
} }
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
func WriteExportJSONLine(qq422016 qtio422016.Writer, xb *exportBlock) { func WriteExportJSONLine(qq422016 qtio422016.Writer, xb *exportBlock) {
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
StreamExportJSONLine(qw422016, xb) StreamExportJSONLine(qw422016, xb)
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
} }
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
func ExportJSONLine(xb *exportBlock) string { func ExportJSONLine(xb *exportBlock) string {
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
WriteExportJSONLine(qb422016, xb) WriteExportJSONLine(qb422016, xb)
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:120 //line app/vmselect/prometheus/export.qtpl:121
} }
//line app/vmselect/prometheus/export.qtpl:122 //line app/vmselect/prometheus/export.qtpl:123
func StreamExportPromAPILine(qw422016 *qt422016.Writer, xb *exportBlock) { func StreamExportPromAPILine(qw422016 *qt422016.Writer, xb *exportBlock) {
//line app/vmselect/prometheus/export.qtpl:122 //line app/vmselect/prometheus/export.qtpl:123
qw422016.N().S(`{"metric":`) qw422016.N().S(`{"metric":`)
//line app/vmselect/prometheus/export.qtpl:124 //line app/vmselect/prometheus/export.qtpl:125
streammetricNameObject(qw422016, xb.mn) streammetricNameObject(qw422016, xb.mn)
//line app/vmselect/prometheus/export.qtpl:124 //line app/vmselect/prometheus/export.qtpl:125
qw422016.N().S(`,"values":`) qw422016.N().S(`,"values":`)
//line app/vmselect/prometheus/export.qtpl:125 //line app/vmselect/prometheus/export.qtpl:126
streamvaluesWithTimestamps(qw422016, xb.values, xb.timestamps) streamvaluesWithTimestamps(qw422016, xb.values, xb.timestamps)
//line app/vmselect/prometheus/export.qtpl:125 //line app/vmselect/prometheus/export.qtpl:126
qw422016.N().S(`}`) qw422016.N().S(`}`)
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
} }
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
func WriteExportPromAPILine(qq422016 qtio422016.Writer, xb *exportBlock) { func WriteExportPromAPILine(qq422016 qtio422016.Writer, xb *exportBlock) {
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
StreamExportPromAPILine(qw422016, xb) StreamExportPromAPILine(qw422016, xb)
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
} }
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
func ExportPromAPILine(xb *exportBlock) string { func ExportPromAPILine(xb *exportBlock) string {
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
WriteExportPromAPILine(qb422016, xb) WriteExportPromAPILine(qb422016, xb)
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:127 //line app/vmselect/prometheus/export.qtpl:128
} }
//line app/vmselect/prometheus/export.qtpl:129 //line app/vmselect/prometheus/export.qtpl:130
func StreamExportPromAPIHeader(qw422016 *qt422016.Writer) { func StreamExportPromAPIHeader(qw422016 *qt422016.Writer) {
//line app/vmselect/prometheus/export.qtpl:129 //line app/vmselect/prometheus/export.qtpl:130
qw422016.N().S(`{"status":"success","data":{"resultType":"matrix","result":[`) qw422016.N().S(`{"status":"success","data":{"resultType":"matrix","result":[`)
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
} }
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
func WriteExportPromAPIHeader(qq422016 qtio422016.Writer) { func WriteExportPromAPIHeader(qq422016 qtio422016.Writer) {
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
StreamExportPromAPIHeader(qw422016) StreamExportPromAPIHeader(qw422016)
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
} }
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
func ExportPromAPIHeader() string { func ExportPromAPIHeader() string {
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
WriteExportPromAPIHeader(qb422016) WriteExportPromAPIHeader(qb422016)
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:135 //line app/vmselect/prometheus/export.qtpl:136
} }
//line app/vmselect/prometheus/export.qtpl:137 //line app/vmselect/prometheus/export.qtpl:138
func StreamExportPromAPIFooter(qw422016 *qt422016.Writer, qt *querytracer.Tracer) { func StreamExportPromAPIFooter(qw422016 *qt422016.Writer, qt *querytracer.Tracer) {
//line app/vmselect/prometheus/export.qtpl:137 //line app/vmselect/prometheus/export.qtpl:138
qw422016.N().S(`]}`) qw422016.N().S(`]}`)
//line app/vmselect/prometheus/export.qtpl:141 //line app/vmselect/prometheus/export.qtpl:142
qt.Donef("export format=promapi") qt.Donef("export format=promapi")
//line app/vmselect/prometheus/export.qtpl:143 //line app/vmselect/prometheus/export.qtpl:144
streamdumpQueryTrace(qw422016, qt) streamdumpQueryTrace(qw422016, qt)
//line app/vmselect/prometheus/export.qtpl:143 //line app/vmselect/prometheus/export.qtpl:144
qw422016.N().S(`}`) qw422016.N().S(`}`)
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
} }
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
func WriteExportPromAPIFooter(qq422016 qtio422016.Writer, qt *querytracer.Tracer) { func WriteExportPromAPIFooter(qq422016 qtio422016.Writer, qt *querytracer.Tracer) {
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
StreamExportPromAPIFooter(qw422016, qt) StreamExportPromAPIFooter(qw422016, qt)
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
} }
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
func ExportPromAPIFooter(qt *querytracer.Tracer) string { func ExportPromAPIFooter(qt *querytracer.Tracer) string {
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
WriteExportPromAPIFooter(qb422016, qt) WriteExportPromAPIFooter(qb422016, qt)
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:145 //line app/vmselect/prometheus/export.qtpl:146
} }
//line app/vmselect/prometheus/export.qtpl:147
func streamprometheusMetricName(qw422016 *qt422016.Writer, mn *storage.MetricName) {
//line app/vmselect/prometheus/export.qtpl:148 //line app/vmselect/prometheus/export.qtpl:148
func streamprometheusMetricName(qw422016 *qt422016.Writer, mn *storage.MetricName) {
//line app/vmselect/prometheus/export.qtpl:149
qw422016.N().Z(mn.MetricGroup) qw422016.N().Z(mn.MetricGroup)
//line app/vmselect/prometheus/export.qtpl:149 //line app/vmselect/prometheus/export.qtpl:150
if len(mn.Tags) > 0 { if len(mn.Tags) > 0 {
//line app/vmselect/prometheus/export.qtpl:149 //line app/vmselect/prometheus/export.qtpl:150
qw422016.N().S(`{`) qw422016.N().S(`{`)
//line app/vmselect/prometheus/export.qtpl:151 //line app/vmselect/prometheus/export.qtpl:152
tags := mn.Tags tags := mn.Tags
//line app/vmselect/prometheus/export.qtpl:152
qw422016.N().Z(tags[0].Key)
//line app/vmselect/prometheus/export.qtpl:152
qw422016.N().S(`=`)
//line app/vmselect/prometheus/export.qtpl:152
streamescapePrometheusLabel(qw422016, tags[0].Value)
//line app/vmselect/prometheus/export.qtpl:153 //line app/vmselect/prometheus/export.qtpl:153
qw422016.N().Z(tags[0].Key)
//line app/vmselect/prometheus/export.qtpl:153
qw422016.N().S(`=`)
//line app/vmselect/prometheus/export.qtpl:153
streamescapePrometheusLabel(qw422016, tags[0].Value)
//line app/vmselect/prometheus/export.qtpl:154
tags = tags[1:] tags = tags[1:]
//line app/vmselect/prometheus/export.qtpl:154
for i := range tags {
//line app/vmselect/prometheus/export.qtpl:155 //line app/vmselect/prometheus/export.qtpl:155
for i := range tags {
//line app/vmselect/prometheus/export.qtpl:156
tag := &tags[i] tag := &tags[i]
//line app/vmselect/prometheus/export.qtpl:155 //line app/vmselect/prometheus/export.qtpl:156
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line app/vmselect/prometheus/export.qtpl:156 //line app/vmselect/prometheus/export.qtpl:157
qw422016.N().Z(tag.Key) qw422016.N().Z(tag.Key)
//line app/vmselect/prometheus/export.qtpl:156 //line app/vmselect/prometheus/export.qtpl:157
qw422016.N().S(`=`) qw422016.N().S(`=`)
//line app/vmselect/prometheus/export.qtpl:156 //line app/vmselect/prometheus/export.qtpl:157
streamescapePrometheusLabel(qw422016, tag.Value) streamescapePrometheusLabel(qw422016, tag.Value)
//line app/vmselect/prometheus/export.qtpl:157 //line app/vmselect/prometheus/export.qtpl:158
} }
//line app/vmselect/prometheus/export.qtpl:157 //line app/vmselect/prometheus/export.qtpl:158
qw422016.N().S(`}`) qw422016.N().S(`}`)
//line app/vmselect/prometheus/export.qtpl:159
}
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:160
}
//line app/vmselect/prometheus/export.qtpl:161
} }
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
func writeprometheusMetricName(qq422016 qtio422016.Writer, mn *storage.MetricName) { func writeprometheusMetricName(qq422016 qtio422016.Writer, mn *storage.MetricName) {
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
streamprometheusMetricName(qw422016, mn) streamprometheusMetricName(qw422016, mn)
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
} }
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
func prometheusMetricName(mn *storage.MetricName) string { func prometheusMetricName(mn *storage.MetricName) string {
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
writeprometheusMetricName(qb422016, mn) writeprometheusMetricName(qb422016, mn)
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:160 //line app/vmselect/prometheus/export.qtpl:161
} }
//line app/vmselect/prometheus/export.qtpl:162 //line app/vmselect/prometheus/export.qtpl:163
func streamconvertValueToSpecialJSON(qw422016 *qt422016.Writer, v float64) { func streamconvertValueToSpecialJSON(qw422016 *qt422016.Writer, v float64) {
//line app/vmselect/prometheus/export.qtpl:163 //line app/vmselect/prometheus/export.qtpl:164
if math.IsNaN(v) { if math.IsNaN(v) {
//line app/vmselect/prometheus/export.qtpl:163 //line app/vmselect/prometheus/export.qtpl:164
qw422016.N().S(`null`) qw422016.N().S(`null`)
//line app/vmselect/prometheus/export.qtpl:165 //line app/vmselect/prometheus/export.qtpl:166
} else if math.IsInf(v, 0) { } else if math.IsInf(v, 0) {
//line app/vmselect/prometheus/export.qtpl:166 //line app/vmselect/prometheus/export.qtpl:167
if v > 0 { if v > 0 {
//line app/vmselect/prometheus/export.qtpl:166 //line app/vmselect/prometheus/export.qtpl:167
qw422016.N().S(`"Infinity"`) qw422016.N().S(`"Infinity"`)
//line app/vmselect/prometheus/export.qtpl:168 //line app/vmselect/prometheus/export.qtpl:169
} else { } else {
//line app/vmselect/prometheus/export.qtpl:168 //line app/vmselect/prometheus/export.qtpl:169
qw422016.N().S(`"-Infinity"`) qw422016.N().S(`"-Infinity"`)
//line app/vmselect/prometheus/export.qtpl:170
}
//line app/vmselect/prometheus/export.qtpl:171 //line app/vmselect/prometheus/export.qtpl:171
} else { }
//line app/vmselect/prometheus/export.qtpl:172 //line app/vmselect/prometheus/export.qtpl:172
qw422016.N().F(v) } else {
//line app/vmselect/prometheus/export.qtpl:173 //line app/vmselect/prometheus/export.qtpl:173
qw422016.N().F(v)
//line app/vmselect/prometheus/export.qtpl:174
} }
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
} }
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
func writeconvertValueToSpecialJSON(qq422016 qtio422016.Writer, v float64) { func writeconvertValueToSpecialJSON(qq422016 qtio422016.Writer, v float64) {
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
streamconvertValueToSpecialJSON(qw422016, v) streamconvertValueToSpecialJSON(qw422016, v)
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
} }
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
func convertValueToSpecialJSON(v float64) string { func convertValueToSpecialJSON(v float64) string {
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
writeconvertValueToSpecialJSON(qb422016, v) writeconvertValueToSpecialJSON(qb422016, v)
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:174 //line app/vmselect/prometheus/export.qtpl:175
} }
//line app/vmselect/prometheus/export.qtpl:176 //line app/vmselect/prometheus/export.qtpl:177
func streamescapePrometheusLabel(qw422016 *qt422016.Writer, b []byte) { func streamescapePrometheusLabel(qw422016 *qt422016.Writer, b []byte) {
//line app/vmselect/prometheus/export.qtpl:176 //line app/vmselect/prometheus/export.qtpl:177
qw422016.N().S(`"`) qw422016.N().S(`"`)
//line app/vmselect/prometheus/export.qtpl:178
for len(b) > 0 {
//line app/vmselect/prometheus/export.qtpl:179 //line app/vmselect/prometheus/export.qtpl:179
for len(b) > 0 {
//line app/vmselect/prometheus/export.qtpl:180
n := bytes.IndexAny(b, "\\\n\"") n := bytes.IndexAny(b, "\\\n\"")
//line app/vmselect/prometheus/export.qtpl:180
if n < 0 {
//line app/vmselect/prometheus/export.qtpl:181 //line app/vmselect/prometheus/export.qtpl:181
qw422016.N().Z(b) if n < 0 {
//line app/vmselect/prometheus/export.qtpl:182 //line app/vmselect/prometheus/export.qtpl:182
break qw422016.N().Z(b)
//line app/vmselect/prometheus/export.qtpl:183 //line app/vmselect/prometheus/export.qtpl:183
} break
//line app/vmselect/prometheus/export.qtpl:184 //line app/vmselect/prometheus/export.qtpl:184
qw422016.N().Z(b[:n])
//line app/vmselect/prometheus/export.qtpl:185
switch b[n] {
//line app/vmselect/prometheus/export.qtpl:186
case '\\':
//line app/vmselect/prometheus/export.qtpl:186
qw422016.N().S(`\\`)
//line app/vmselect/prometheus/export.qtpl:188
case '\n':
//line app/vmselect/prometheus/export.qtpl:188
qw422016.N().S(`\n`)
//line app/vmselect/prometheus/export.qtpl:190
case '"':
//line app/vmselect/prometheus/export.qtpl:190
qw422016.N().S(`\"`)
//line app/vmselect/prometheus/export.qtpl:192
} }
//line app/vmselect/prometheus/export.qtpl:185
qw422016.N().Z(b[:n])
//line app/vmselect/prometheus/export.qtpl:186
switch b[n] {
//line app/vmselect/prometheus/export.qtpl:187
case '\\':
//line app/vmselect/prometheus/export.qtpl:187
qw422016.N().S(`\\`)
//line app/vmselect/prometheus/export.qtpl:189
case '\n':
//line app/vmselect/prometheus/export.qtpl:189
qw422016.N().S(`\n`)
//line app/vmselect/prometheus/export.qtpl:191
case '"':
//line app/vmselect/prometheus/export.qtpl:191
qw422016.N().S(`\"`)
//line app/vmselect/prometheus/export.qtpl:193 //line app/vmselect/prometheus/export.qtpl:193
}
//line app/vmselect/prometheus/export.qtpl:194
b = b[n+1:] b = b[n+1:]
//line app/vmselect/prometheus/export.qtpl:194 //line app/vmselect/prometheus/export.qtpl:195
} }
//line app/vmselect/prometheus/export.qtpl:194 //line app/vmselect/prometheus/export.qtpl:195
qw422016.N().S(`"`) qw422016.N().S(`"`)
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
} }
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
func writeescapePrometheusLabel(qq422016 qtio422016.Writer, b []byte) { func writeescapePrometheusLabel(qq422016 qtio422016.Writer, b []byte) {
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
streamescapePrometheusLabel(qw422016, b) streamescapePrometheusLabel(qw422016, b)
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
} }
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
func escapePrometheusLabel(b []byte) string { func escapePrometheusLabel(b []byte) string {
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
writeescapePrometheusLabel(qb422016, b) writeescapePrometheusLabel(qb422016, b)
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
return qs422016 return qs422016
//line app/vmselect/prometheus/export.qtpl:196 //line app/vmselect/prometheus/export.qtpl:197
} }

View file

@ -44,6 +44,8 @@ See also [LTS releases](https://docs.victoriametrics.com/LTS-releases.html).
or [/api/v1/query_range](https://docs.victoriametrics.com/keyconcepts/#range-query). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5795). or [/api/v1/query_range](https://docs.victoriametrics.com/keyconcepts/#range-query). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5795).
* BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): fixed floating-point error when parsing time in RFC3339 format. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5801) for details. * BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): fixed floating-point error when parsing time in RFC3339 format. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5801) for details.
* BUGFIX: [vmalert](https://docs.victoriametrics.com/#vmalert): consistently sort groups by name and filename on `/groups` page in UI. This should prevent non-deterministic sorting for groups with identical names. * BUGFIX: [vmalert](https://docs.victoriametrics.com/#vmalert): consistently sort groups by name and filename on `/groups` page in UI. This should prevent non-deterministic sorting for groups with identical names.
* BUGFIX: [vmselect](https://docs.victoriametrics.com/): format time with milliseconds precision when `__timestamp__:rfc3339` is specified for [/api/v1/export/csv](https://docs.victoriametrics.com/#how-to-export-csv-data) API response. See this [issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5837) for details.
## [v1.98.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.98.0) ## [v1.98.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.98.0)

View file

@ -268,4 +268,53 @@ func TestRowsUnmarshalSuccess(t *testing.T) {
Value: 60, Value: 60,
}, },
}) })
// rfc3339 with millisecond precision
// see https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5837
f("1:label:mytest,2:time:rfc3339,3:metric:M10,4:metric:M20,5:metric:M30,6:metric:M40,7:metric:M50,8:metric:M60",
`test,2022-12-25T16:57:12.000+01:00,10,20,30,,,60,70,80`, []Row{
{
Metric: "M10",
Tags: []Tag{
{
Key: "mytest",
Value: "test",
},
},
Timestamp: 1671983832000,
Value: 10,
},
{
Metric: "M20",
Tags: []Tag{
{
Key: "mytest",
Value: "test",
},
},
Timestamp: 1671983832000,
Value: 20,
},
{
Metric: "M30",
Tags: []Tag{
{
Key: "mytest",
Value: "test",
},
},
Timestamp: 1671983832000,
Value: 30,
},
{
Metric: "M60",
Tags: []Tag{
{
Key: "mytest",
Value: "test",
},
},
Timestamp: 1671983832000,
Value: 60,
},
})
} }