mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-15 08:23:34 +01:00
lib/protoparser/prometheus: properly parse OpenMetrics timestamps
OpenMetrics timestamps are floating-point numbers, that represent Unix timestamp in seconds. This differs from Prometheus exposition format, where timestamps are integer numbers representing Unix timestamp in milliseconds.
This commit is contained in:
parent
2c0b1d5454
commit
2ed721e457
@ -2,6 +2,9 @@
|
||||
|
||||
# tip
|
||||
|
||||
* BUGFIX: properly parse timestamps in OpenMetrics format - they are exposed as floating-point number in seconds instead of integer milliseconds
|
||||
unlike in Prometheus exposition format. See [the docs](https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md#timestamps).
|
||||
|
||||
|
||||
# [v1.48.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.48.0)
|
||||
|
||||
|
@ -166,11 +166,18 @@ func (r *Row) unmarshal(s string, tagsPool []Tag, noEscapes bool) ([]Tag, error)
|
||||
// There is no timestamp - just a whitespace after the value.
|
||||
return tagsPool, nil
|
||||
}
|
||||
ts, err := fastfloat.ParseInt64(s)
|
||||
ts, err := fastfloat.Parse(s)
|
||||
if err != nil {
|
||||
return tagsPool, fmt.Errorf("cannot parse timestamp %q: %w", s, err)
|
||||
}
|
||||
r.Timestamp = ts
|
||||
if ts >= -1<<31 && ts < 1<<31 {
|
||||
// This looks like OpenMetrics timestamp in Unix seconds.
|
||||
// Convert it to milliseconds.
|
||||
//
|
||||
// See https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md#timestamps
|
||||
ts *= 1000
|
||||
}
|
||||
r.Timestamp = int64(ts)
|
||||
return tagsPool, nil
|
||||
}
|
||||
|
||||
|
@ -178,14 +178,14 @@ func TestRowsUnmarshalSuccess(t *testing.T) {
|
||||
Rows: []Row{{
|
||||
Metric: "foobar",
|
||||
Value: 123.456,
|
||||
Timestamp: 789,
|
||||
Timestamp: 789000,
|
||||
}},
|
||||
})
|
||||
f("foobar{} 123.456 789\n", &Rows{
|
||||
f("foobar{} 123.456 789.4354\n", &Rows{
|
||||
Rows: []Row{{
|
||||
Metric: "foobar",
|
||||
Value: 123.456,
|
||||
Timestamp: 789,
|
||||
Timestamp: 789435,
|
||||
}},
|
||||
})
|
||||
f(`# _ _
|
||||
@ -225,7 +225,7 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
{
|
||||
Metric: "abc",
|
||||
Value: 123,
|
||||
Timestamp: 456,
|
||||
Timestamp: 456000,
|
||||
},
|
||||
{
|
||||
Metric: "foo",
|
||||
@ -274,7 +274,8 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
},
|
||||
})
|
||||
|
||||
// Timestamp bigger than 1<<31
|
||||
// Timestamp bigger than 1<<31.
|
||||
// It should be parsed in milliseconds.
|
||||
f("aaa 1123 429496729600", &Rows{
|
||||
Rows: []Row{{
|
||||
Metric: "aaa",
|
||||
@ -283,6 +284,15 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
}},
|
||||
})
|
||||
|
||||
// Floating-point timestamps in OpenMetric format.
|
||||
f("aaa 1123 42949.567", &Rows{
|
||||
Rows: []Row{{
|
||||
Metric: "aaa",
|
||||
Value: 1123,
|
||||
Timestamp: 42949567,
|
||||
}},
|
||||
})
|
||||
|
||||
// Tags
|
||||
f(`foo{bar="baz"} 1 2`, &Rows{
|
||||
Rows: []Row{{
|
||||
@ -292,7 +302,7 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
Value: "baz",
|
||||
}},
|
||||
Value: 1,
|
||||
Timestamp: 2,
|
||||
Timestamp: 2000,
|
||||
}},
|
||||
})
|
||||
f(`foo{bar="b\"a\\z"} -1.2`, &Rows{
|
||||
@ -324,7 +334,7 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
},
|
||||
},
|
||||
Value: 1,
|
||||
Timestamp: 2,
|
||||
Timestamp: 2000,
|
||||
}},
|
||||
})
|
||||
|
||||
@ -338,7 +348,7 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
Value: "baz",
|
||||
}},
|
||||
Value: 1,
|
||||
Timestamp: 2,
|
||||
Timestamp: 2000,
|
||||
}},
|
||||
})
|
||||
|
||||
@ -348,7 +358,7 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
{
|
||||
Metric: "foo",
|
||||
Value: 0.3,
|
||||
Timestamp: 2,
|
||||
Timestamp: 2000,
|
||||
},
|
||||
{
|
||||
Metric: "aaa",
|
||||
@ -357,7 +367,7 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
{
|
||||
Metric: "bar.baz",
|
||||
Value: 0.34,
|
||||
Timestamp: 43,
|
||||
Timestamp: 43000,
|
||||
},
|
||||
},
|
||||
})
|
||||
@ -368,12 +378,12 @@ cassandra_token_ownership_ratio 78.9`, &Rows{
|
||||
{
|
||||
Metric: "foo",
|
||||
Value: 0.3,
|
||||
Timestamp: 2,
|
||||
Timestamp: 2000,
|
||||
},
|
||||
{
|
||||
Metric: "bar.baz",
|
||||
Value: 0.34,
|
||||
Timestamp: 43,
|
||||
Timestamp: 43000,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -82,13 +82,13 @@ func TestParseStream(t *testing.T) {
|
||||
f("foo 123 456", []Row{{
|
||||
Metric: "foo",
|
||||
Value: 123,
|
||||
Timestamp: 456,
|
||||
Timestamp: 456000,
|
||||
}})
|
||||
f(`foo{bar="baz"} 1 2`+"\n"+`aaa{} 3 4`, []Row{
|
||||
{
|
||||
Metric: "aaa",
|
||||
Value: 3,
|
||||
Timestamp: 4,
|
||||
Timestamp: 4000,
|
||||
},
|
||||
{
|
||||
Metric: "foo",
|
||||
@ -97,7 +97,7 @@ func TestParseStream(t *testing.T) {
|
||||
Value: "baz",
|
||||
}},
|
||||
Value: 1,
|
||||
Timestamp: 2,
|
||||
Timestamp: 2000,
|
||||
},
|
||||
})
|
||||
f("foo 23", []Row{{
|
||||
|
Loading…
Reference in New Issue
Block a user