textparse: Optimize CreatedTimestamp; It returns int64 value now. (#16072)

..instead of *int64. This is as an optimization and ease of use. We already
accepted in many places (proto histograms, PRW) that CT (or any timestamp really) 0
means not set.

Signed-off-by: bwplotka <bwplotka@gmail.com>
This commit is contained in:
Bartlomiej Plotka 2025-03-07 13:43:13 +01:00 committed by GitHub
parent 71cb219eb6
commit dc85d677d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 180 additions and 107 deletions

View file

@ -262,3 +262,77 @@ func readTestdataFile(tb testing.TB, file string) []byte {
require.NoError(tb, err)
return buf
}
/*
export bench=v1 && go test ./model/textparse/... \
-run '^$' -bench '^BenchmarkCreatedTimestampPromProto' \
-benchtime 2s -count 6 -cpu 2 -benchmem -timeout 999m \
| tee ${bench}.txt
*/
func BenchmarkCreatedTimestampPromProto(b *testing.B) {
data := createTestProtoBuf(b).Bytes()
st := labels.NewSymbolTable()
p := NewProtobufParser(data, true, st)
found := false
Inner:
for {
t, err := p.Next()
switch t {
case EntryInvalid:
b.Fatal(err)
case EntryType:
m, _ := p.Type()
if string(m) == "go_memstats_alloc_bytes_total" {
found = true
break Inner
}
// Parser impl requires this (bug?)
case EntryHistogram:
_, _, _, _ = p.Histogram()
case EntrySeries:
_, _, _ = p.Series()
}
}
require.True(b, found)
b.Run("case=no-ct", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if p.CreatedTimestamp() != 0 {
b.Fatal("should be nil")
}
}
})
found = false
Inner2:
for {
t, err := p.Next()
switch t {
case EntryInvalid:
b.Fatal(err)
case EntryType:
m, _ := p.Type()
if string(m) == "test_counter_with_createdtimestamp" {
found = true
break Inner2
}
case EntryHistogram:
_, _, _, _ = p.Histogram()
case EntrySeries:
_, _, _ = p.Series()
}
}
require.True(b, found)
b.Run("case=ct", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if p.CreatedTimestamp() == 0 {
b.Fatal("should be not nil")
}
}
})
}

View file

@ -29,12 +29,18 @@ import (
type Parser interface {
// Series returns the bytes of a series with a simple float64 as a
// value, the timestamp if set, and the value of the current sample.
// TODO(bwplotka): Similar to CreatedTimestamp, have ts == 0 meaning no timestamp provided.
// We already accepted in many places (PRW, proto parsing histograms) that 0 timestamp is not a
// a valid timestamp. If needed it can be represented as 0+1ms.
Series() ([]byte, *int64, float64)
// Histogram returns the bytes of a series with a sparse histogram as a
// value, the timestamp if set, and the histogram in the current sample.
// Depending on the parsed input, the function returns an (integer) Histogram
// or a FloatHistogram, with the respective other return value being nil.
// TODO(bwplotka): Similar to CreatedTimestamp, have ts == 0 meaning no timestamp provided.
// We already accepted in many places (PRW, proto parsing histograms) that 0 timestamp is not a
// a valid timestamp. If needed it can be represented as 0+1ms.
Histogram() ([]byte, *int64, *histogram.Histogram, *histogram.FloatHistogram)
// Help returns the metric name and help text in the current entry.
@ -69,11 +75,9 @@ type Parser interface {
Exemplar(l *exemplar.Exemplar) bool
// CreatedTimestamp returns the created timestamp (in milliseconds) for the
// current sample. It returns nil if it is unknown e.g. if it wasn't set,
// current sample. It returns 0 if it is unknown e.g. if it wasn't set or
// if the scrape protocol or metric type does not support created timestamps.
// Assume the CreatedTimestamp returned pointer is only valid until
// the Next iteration.
CreatedTimestamp() *int64
CreatedTimestamp() int64
// Next advances the parser to the next sample.
// It returns (EntryInvalid, io.EOF) if no samples were read.

View file

@ -195,7 +195,7 @@ type parsedEntry struct {
lset labels.Labels
t *int64
es []exemplar.Exemplar
ct *int64
ct int64
// In EntryType.
typ model.MetricType
@ -255,11 +255,8 @@ func testParse(t *testing.T, p Parser) (ret []parsedEntry) {
}
got.m = string(m)
p.Labels(&got.lset)
got.ct = p.CreatedTimestamp()
// Parser reuses int pointer.
if ct := p.CreatedTimestamp(); ct != nil {
got.ct = int64p(*ct)
}
for e := (exemplar.Exemplar{}); p.Exemplar(&e); {
got.es = append(got.es, e)
}

View file

@ -83,7 +83,7 @@ type NHCBParser struct {
fhNHCB *histogram.FloatHistogram
lsetNHCB labels.Labels
exemplars []exemplar.Exemplar
ctNHCB *int64
ctNHCB int64
metricStringNHCB string
// Collates values from the classic histogram series to build
@ -92,7 +92,7 @@ type NHCBParser struct {
tempNHCB convertnhcb.TempHistogram
tempExemplars []exemplar.Exemplar
tempExemplarCount int
tempCT *int64
tempCT int64
// Remembers the last base histogram metric name (assuming it's
// a classic histogram) so we can tell if the next float series
@ -160,7 +160,7 @@ func (p *NHCBParser) Exemplar(ex *exemplar.Exemplar) bool {
return p.parser.Exemplar(ex)
}
func (p *NHCBParser) CreatedTimestamp() *int64 {
func (p *NHCBParser) CreatedTimestamp() int64 {
switch p.state {
case stateStart:
if p.entry == EntrySeries || p.entry == EntryHistogram {
@ -171,7 +171,7 @@ func (p *NHCBParser) CreatedTimestamp() *int64 {
case stateEmitting:
return p.ctNHCB
}
return nil
return 0
}
func (p *NHCBParser) Next() (Entry, error) {
@ -375,6 +375,6 @@ func (p *NHCBParser) processNHCB() bool {
}
p.tempNHCB.Reset()
p.tempExemplarCount = 0
p.tempCT = nil
p.tempCT = 0
return err == nil
}

View file

@ -293,14 +293,14 @@ foobar{quantile="0.99"} 150.1`
lset: labels.FromStrings("__name__", "foo_total"),
t: int64p(1520879607789),
es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}},
ct: int64p(1520872607123),
ct: 1520872607123,
}, {
m: `foo_total{a="b"}`,
v: 17.0,
lset: labels.FromStrings("__name__", "foo_total", "a", "b"),
t: int64p(1520879607789),
es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}},
ct: int64p(1520872607123),
ct: 1520872607123,
}, {
m: "bar",
help: "Summary with CT at the end, making sure we find CT even if it's multiple lines a far",
@ -311,22 +311,22 @@ foobar{quantile="0.99"} 150.1`
m: "bar_count",
v: 17.0,
lset: labels.FromStrings("__name__", "bar_count"),
ct: int64p(1520872608124),
ct: 1520872608124,
}, {
m: "bar_sum",
v: 324789.3,
lset: labels.FromStrings("__name__", "bar_sum"),
ct: int64p(1520872608124),
ct: 1520872608124,
}, {
m: `bar{quantile="0.95"}`,
v: 123.7,
lset: labels.FromStrings("__name__", "bar", "quantile", "0.95"),
ct: int64p(1520872608124),
ct: 1520872608124,
}, {
m: `bar{quantile="0.99"}`,
v: 150.0,
lset: labels.FromStrings("__name__", "bar", "quantile", "0.99"),
ct: int64p(1520872608124),
ct: 1520872608124,
}, {
m: "baz",
help: "Histogram with the same objective as above's summary",
@ -344,7 +344,7 @@ foobar{quantile="0.99"} 150.1`
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "baz"),
ct: int64p(1520872609125),
ct: 1520872609125,
}, {
m: "fizz_created",
help: "Gauge which shouldn't be parsed as CT",
@ -372,7 +372,7 @@ foobar{quantile="0.99"} 150.1`
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "something"),
ct: int64p(1520430001000),
ct: 1520430001000,
}, {
m: `something{a="b"}`,
shs: &histogram.Histogram{
@ -384,7 +384,7 @@ foobar{quantile="0.99"} 150.1`
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "something", "a", "b"),
ct: int64p(1520430002000),
ct: 1520430002000,
}, {
m: "yum",
help: "Summary with _created between sum and quantiles",
@ -395,22 +395,22 @@ foobar{quantile="0.99"} 150.1`
m: `yum_count`,
v: 20,
lset: labels.FromStrings("__name__", "yum_count"),
ct: int64p(1520430003000),
ct: 1520430003000,
}, {
m: `yum_sum`,
v: 324789.5,
lset: labels.FromStrings("__name__", "yum_sum"),
ct: int64p(1520430003000),
ct: 1520430003000,
}, {
m: `yum{quantile="0.95"}`,
v: 123.7,
lset: labels.FromStrings("__name__", "yum", "quantile", "0.95"),
ct: int64p(1520430003000),
ct: 1520430003000,
}, {
m: `yum{quantile="0.99"}`,
v: 150.0,
lset: labels.FromStrings("__name__", "yum", "quantile", "0.99"),
ct: int64p(1520430003000),
ct: 1520430003000,
}, {
m: "foobar",
help: "Summary with _created as the first line",
@ -421,22 +421,22 @@ foobar{quantile="0.99"} 150.1`
m: `foobar_count`,
v: 21,
lset: labels.FromStrings("__name__", "foobar_count"),
ct: int64p(1520430004000),
ct: 1520430004000,
}, {
m: `foobar_sum`,
v: 324789.6,
lset: labels.FromStrings("__name__", "foobar_sum"),
ct: int64p(1520430004000),
ct: 1520430004000,
}, {
m: `foobar{quantile="0.95"}`,
v: 123.8,
lset: labels.FromStrings("__name__", "foobar", "quantile", "0.95"),
ct: int64p(1520430004000),
ct: 1520430004000,
}, {
m: `foobar{quantile="0.99"}`,
v: 150.1,
lset: labels.FromStrings("__name__", "foobar", "quantile", "0.99"),
ct: int64p(1520430004000),
ct: 1520430004000,
}, {
m: "metric",
help: "foo\x00bar",
@ -646,9 +646,9 @@ func TestNHCBParser_NoNHCBWhenExponential(t *testing.T) {
typ: model.MetricTypeHistogram,
})
var ct *int64
var ct int64
if options.hasCreatedTimeStamp {
ct = int64p(1000)
ct = 1000
}
var bucketForMetric func(string) string
@ -973,7 +973,7 @@ something_bucket{a="b",le="+Inf"} 9
CustomValues: []float64{0.0}, // We do not store the +Inf boundary.
},
lset: labels.FromStrings("__name__", "something", "a", "b"),
ct: int64p(1520430002000),
ct: 1520430002000,
},
}

View file

@ -259,11 +259,11 @@ func (p *OpenMetricsParser) Exemplar(e *exemplar.Exemplar) bool {
// CreatedTimestamp returns the created timestamp for a current Metric if exists or nil.
// NOTE(Maniktherana): Might use additional CPU/mem resources due to deep copy of parser required for peeking given 1.0 OM specification on _created series.
func (p *OpenMetricsParser) CreatedTimestamp() *int64 {
func (p *OpenMetricsParser) CreatedTimestamp() int64 {
if !typeRequiresCT(p.mtype) {
// Not a CT supported metric type, fast path.
p.ctHashSet = 0 // Use ctHashSet as a single way of telling "empty cache"
return nil
return 0
}
var (
@ -280,7 +280,7 @@ func (p *OpenMetricsParser) CreatedTimestamp() *int64 {
currHash := p.seriesHash(&buf, currName)
// Check cache, perhaps we fetched something already.
if currHash == p.ctHashSet && p.ct > 0 {
return &p.ct
return p.ct
}
// Create a new lexer to reset the parser once this function is done executing.
@ -310,12 +310,12 @@ func (p *OpenMetricsParser) CreatedTimestamp() *int64 {
// spec improvement would help.
// TODO: Make sure OM 1.1/2.0 pass CT via metadata or exemplar-like to avoid this.
p.resetCTParseValues()
return nil
return 0
}
if eType != EntrySeries {
// Assume we hit different family, no CT line found.
p.resetCTParseValues()
return nil
return 0
}
peekedName := p.series[p.offsets[0]-p.start : p.offsets[1]-p.start]
@ -329,14 +329,14 @@ func (p *OpenMetricsParser) CreatedTimestamp() *int64 {
if peekedHash != currHash {
// Found CT line for a different series, for our series no CT.
p.resetCTParseValues()
return nil
return 0
}
// All timestamps in OpenMetrics are Unix Epoch in seconds. Convert to milliseconds.
// https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#timestamps
ct := int64(p.val * 1000.0)
p.setCTParseValues(ct, currHash, currName, true)
return &ct
return ct
}
}

View file

@ -289,7 +289,7 @@ foobar{quantile="0.99"} 150.1`
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("id", "counter-test"), Value: 5},
},
ct: int64p(1520872607123),
ct: 1520872607123,
}, {
m: `foo_total{a="b"}`,
v: 17.0,
@ -298,12 +298,12 @@ foobar{quantile="0.99"} 150.1`
es: []exemplar.Exemplar{
{Labels: labels.FromStrings("id", "counter-test"), Value: 5},
},
ct: int64p(1520872607123),
ct: 1520872607123,
}, {
m: `foo_total{le="c"}`,
v: 21.0,
lset: labels.FromStrings("__name__", "foo_total", "le", "c"),
ct: int64p(1520872621123),
ct: 1520872621123,
}, {
m: `foo_total{le="1"}`,
v: 10.0,
@ -318,22 +318,22 @@ foobar{quantile="0.99"} 150.1`
m: "bar_count",
v: 17.0,
lset: labels.FromStrings("__name__", "bar_count"),
ct: int64p(1520872608124),
ct: 1520872608124,
}, {
m: "bar_sum",
v: 324789.3,
lset: labels.FromStrings("__name__", "bar_sum"),
ct: int64p(1520872608124),
ct: 1520872608124,
}, {
m: `bar{quantile="0.95"}`,
v: 123.7,
lset: labels.FromStrings("__name__", "bar", "quantile", "0.95"),
ct: int64p(1520872608124),
ct: 1520872608124,
}, {
m: `bar{quantile="0.99"}`,
v: 150.0,
lset: labels.FromStrings("__name__", "bar", "quantile", "0.99"),
ct: int64p(1520872608124),
ct: 1520872608124,
}, {
m: "baz",
help: "Histogram with the same objective as above's summary",
@ -344,22 +344,22 @@ foobar{quantile="0.99"} 150.1`
m: `baz_bucket{le="0.0"}`,
v: 0,
lset: labels.FromStrings("__name__", "baz_bucket", "le", "0.0"),
ct: int64p(1520872609125),
ct: 1520872609125,
}, {
m: `baz_bucket{le="+Inf"}`,
v: 17,
lset: labels.FromStrings("__name__", "baz_bucket", "le", "+Inf"),
ct: int64p(1520872609125),
ct: 1520872609125,
}, {
m: `baz_count`,
v: 17,
lset: labels.FromStrings("__name__", "baz_count"),
ct: int64p(1520872609125),
ct: 1520872609125,
}, {
m: `baz_sum`,
v: 324789.3,
lset: labels.FromStrings("__name__", "baz_sum"),
ct: int64p(1520872609125),
ct: 1520872609125,
}, {
m: "fizz_created",
help: "Gauge which shouldn't be parsed as CT",
@ -380,27 +380,27 @@ foobar{quantile="0.99"} 150.1`
m: `something_count`,
v: 18,
lset: labels.FromStrings("__name__", "something_count"),
ct: int64p(1520430001000),
ct: 1520430001000,
}, {
m: `something_sum`,
v: 324789.4,
lset: labels.FromStrings("__name__", "something_sum"),
ct: int64p(1520430001000),
ct: 1520430001000,
}, {
m: `something_bucket{le="0.0"}`,
v: 1,
lset: labels.FromStrings("__name__", "something_bucket", "le", "0.0"),
ct: int64p(1520430001000),
ct: 1520430001000,
}, {
m: `something_bucket{le="1"}`,
v: 2,
lset: labels.FromStrings("__name__", "something_bucket", "le", "1.0"),
ct: int64p(1520430001000),
ct: 1520430001000,
}, {
m: `something_bucket{le="+Inf"}`,
v: 18,
lset: labels.FromStrings("__name__", "something_bucket", "le", "+Inf"),
ct: int64p(1520430001000),
ct: 1520430001000,
}, {
m: "yum",
help: "Summary with _created between sum and quantiles",
@ -411,22 +411,22 @@ foobar{quantile="0.99"} 150.1`
m: `yum_count`,
v: 20,
lset: labels.FromStrings("__name__", "yum_count"),
ct: int64p(1520430003000),
ct: 1520430003000,
}, {
m: `yum_sum`,
v: 324789.5,
lset: labels.FromStrings("__name__", "yum_sum"),
ct: int64p(1520430003000),
ct: 1520430003000,
}, {
m: `yum{quantile="0.95"}`,
v: 123.7,
lset: labels.FromStrings("__name__", "yum", "quantile", "0.95"),
ct: int64p(1520430003000),
ct: 1520430003000,
}, {
m: `yum{quantile="0.99"}`,
v: 150.0,
lset: labels.FromStrings("__name__", "yum", "quantile", "0.99"),
ct: int64p(1520430003000),
ct: 1520430003000,
}, {
m: "foobar",
help: "Summary with _created as the first line",
@ -437,22 +437,22 @@ foobar{quantile="0.99"} 150.1`
m: `foobar_count`,
v: 21,
lset: labels.FromStrings("__name__", "foobar_count"),
ct: int64p(1520430004000),
ct: 1520430004000,
}, {
m: `foobar_sum`,
v: 324789.6,
lset: labels.FromStrings("__name__", "foobar_sum"),
ct: int64p(1520430004000),
ct: 1520430004000,
}, {
m: `foobar{quantile="0.95"}`,
v: 123.8,
lset: labels.FromStrings("__name__", "foobar", "quantile", "0.95"),
ct: int64p(1520430004000),
ct: 1520430004000,
}, {
m: `foobar{quantile="0.99"}`,
v: 150.1,
lset: labels.FromStrings("__name__", "foobar", "quantile", "0.99"),
ct: int64p(1520430004000),
ct: 1520430004000,
}, {
m: "metric",
help: "foo\x00bar",
@ -507,12 +507,12 @@ quotedexemplar2_count 1 # {"id.thing"="histogram-count-test",other="hello"} 4
m: `{"go.gc_duration_seconds",quantile="0"}`,
v: 4.9351e-05,
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.0"),
ct: int64p(1520872607123),
ct: 1520872607123,
}, {
m: `{"go.gc_duration_seconds",quantile="0.25"}`,
v: 7.424100000000001e-05,
lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.25"),
ct: int64p(1520872607123),
ct: 1520872607123,
}, {
m: `{"go.gc_duration_seconds",quantile="0.5",a="b"}`,
v: 8.3835e-05,
@ -966,19 +966,19 @@ thing_c_total 14123.232
},
{
m: `thing_count`,
ct: nil, // Should be int64p(1520872607123).
ct: 0, // Should be int64p(1520872607123).
},
{
m: `thing_sum`,
ct: nil, // Should be int64p(1520872607123).
ct: 0, // Should be int64p(1520872607123).
},
{
m: `thing_bucket{le="0.0"}`,
ct: nil, // Should be int64p(1520872607123).
ct: 0, // Should be int64p(1520872607123).
},
{
m: `thing_bucket{le="+Inf"}`,
ct: nil, // Should be int64p(1520872607123),
ct: 0, // Should be int64p(1520872607123),
},
{
m: "thing_c",
@ -990,7 +990,7 @@ thing_c_total 14123.232
},
{
m: `thing_c_total`,
ct: nil, // Should be int64p(1520872607123).
ct: 0, // Should be int64p(1520872607123).
},
},
},

View file

@ -253,10 +253,10 @@ func (p *PromParser) Exemplar(*exemplar.Exemplar) bool {
return false
}
// CreatedTimestamp returns nil as it's not implemented yet.
// CreatedTimestamp returns 0 as it's not implemented yet.
// TODO(bwplotka): https://github.com/prometheus/prometheus/issues/12980
func (p *PromParser) CreatedTimestamp() *int64 {
return nil
func (p *PromParser) CreatedTimestamp() int64 {
return 0
}
// nextToken returns the next token from the promlexer. It skips over tabs

View file

@ -379,9 +379,8 @@ func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool {
return true
}
// CreatedTimestamp returns CT or nil if CT is not present or
// invalid (as timestamp e.g. negative value) on counters, summaries or histograms.
func (p *ProtobufParser) CreatedTimestamp() *int64 {
// CreatedTimestamp returns CT or 0 if CT is not present on counters, summaries or histograms.
func (p *ProtobufParser) CreatedTimestamp() int64 {
var ct *types.Timestamp
switch p.dec.GetType() {
case dto.MetricType_COUNTER:
@ -392,13 +391,12 @@ func (p *ProtobufParser) CreatedTimestamp() *int64 {
ct = p.dec.GetHistogram().GetCreatedTimestamp()
default:
}
ctAsTime, err := types.TimestampFromProto(ct)
if err != nil {
// Errors means ct == nil or invalid timestamp, which we silently ignore.
return nil
if ct == nil {
return 0
}
ctMilis := ctAsTime.UnixMilli()
return &ctMilis
// Same as the gogo proto types.TimestampFromProto but straight to integer.
// and without validation.
return ct.GetSeconds()*1e3 + int64(ct.GetNanos())/1e6
}
// Next advances the parser to the next "sample" (emulating the behavior of a

View file

@ -582,8 +582,8 @@ metric: <
counter: <
value: 42
created_timestamp: <
seconds: 1
nanos: 1
seconds: 1625851153
nanos: 146848499
>
>
>
@ -597,8 +597,8 @@ metric: <
sample_count: 42
sample_sum: 1.234
created_timestamp: <
seconds: 1
nanos: 1
seconds: 1625851153
nanos: 146848499
>
>
>
@ -610,8 +610,8 @@ type: HISTOGRAM
metric: <
histogram: <
created_timestamp: <
seconds: 1
nanos: 1
seconds: 1625851153
nanos: 146848499
>
positive_span: <
offset: 0
@ -627,8 +627,8 @@ type: GAUGE_HISTOGRAM
metric: <
histogram: <
created_timestamp: <
seconds: 1
nanos: 1
seconds: 1625851153
nanos: 146848499
>
positive_span: <
offset: 0
@ -1324,7 +1324,7 @@ func TestProtobufParse(t *testing.T) {
{
m: "test_counter_with_createdtimestamp",
v: 42,
ct: int64p(1000),
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_counter_with_createdtimestamp",
),
@ -1340,7 +1340,7 @@ func TestProtobufParse(t *testing.T) {
{
m: "test_summary_with_createdtimestamp_count",
v: 42,
ct: int64p(1000),
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_count",
),
@ -1348,7 +1348,7 @@ func TestProtobufParse(t *testing.T) {
{
m: "test_summary_with_createdtimestamp_sum",
v: 1.234,
ct: int64p(1000),
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_sum",
),
@ -1363,7 +1363,7 @@ func TestProtobufParse(t *testing.T) {
},
{
m: "test_histogram_with_createdtimestamp",
ct: int64p(1000),
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
@ -1383,7 +1383,7 @@ func TestProtobufParse(t *testing.T) {
},
{
m: "test_gaugehistogram_with_createdtimestamp",
ct: int64p(1000),
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.GaugeType,
PositiveSpans: []histogram.Span{},
@ -2277,7 +2277,7 @@ func TestProtobufParse(t *testing.T) {
{
m: "test_counter_with_createdtimestamp",
v: 42,
ct: int64p(1000),
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_counter_with_createdtimestamp",
),
@ -2293,7 +2293,7 @@ func TestProtobufParse(t *testing.T) {
{
m: "test_summary_with_createdtimestamp_count",
v: 42,
ct: int64p(1000),
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_count",
),
@ -2301,7 +2301,7 @@ func TestProtobufParse(t *testing.T) {
{
m: "test_summary_with_createdtimestamp_sum",
v: 1.234,
ct: int64p(1000),
ct: 1625851153146,
lset: labels.FromStrings(
"__name__", "test_summary_with_createdtimestamp_sum",
),
@ -2316,7 +2316,7 @@ func TestProtobufParse(t *testing.T) {
},
{
m: "test_histogram_with_createdtimestamp",
ct: int64p(1000),
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.UnknownCounterReset,
PositiveSpans: []histogram.Span{},
@ -2336,7 +2336,7 @@ func TestProtobufParse(t *testing.T) {
},
{
m: "test_gaugehistogram_with_createdtimestamp",
ct: int64p(1000),
ct: 1625851153146,
shs: &histogram.Histogram{
CounterResetHint: histogram.GaugeType,
PositiveSpans: []histogram.Span{},

View file

@ -1747,20 +1747,20 @@ loop:
err = storage.ErrDuplicateSampleForTimestamp
} else {
if sl.enableCTZeroIngestion {
if ctMs := p.CreatedTimestamp(); ctMs != nil {
if ctMs := p.CreatedTimestamp(); ctMs != 0 {
if isHistogram && sl.enableNativeHistogramIngestion {
if h != nil {
ref, err = app.AppendHistogramCTZeroSample(ref, lset, t, *ctMs, h, nil)
ref, err = app.AppendHistogramCTZeroSample(ref, lset, t, ctMs, h, nil)
} else {
ref, err = app.AppendHistogramCTZeroSample(ref, lset, t, *ctMs, nil, fh)
ref, err = app.AppendHistogramCTZeroSample(ref, lset, t, ctMs, nil, fh)
}
} else {
ref, err = app.AppendCTZeroSample(ref, lset, t, *ctMs)
ref, err = app.AppendCTZeroSample(ref, lset, t, ctMs)
}
if err != nil && !errors.Is(err, storage.ErrOutOfOrderCT) { // OOO is a common case, ignoring completely for now.
// CT is an experimental feature. For now, we don't need to fail the
// scrape on errors updating the created timestamp, log debug.
sl.l.Debug("Error when appending CT in scrape loop", "series", string(met), "ct", *ctMs, "t", t, "err", err)
sl.l.Debug("Error when appending CT in scrape loop", "series", string(met), "ct", ctMs, "t", t, "err", err)
}
}
}