mirror of
https://github.com/prometheus/prometheus.git
synced 2026-06-09 00:22:19 -04:00
Fix bug with counter reset header
Signed-off-by: Carrie Edwards <edwrdscarrie@gmail.com>
This commit is contained in:
parent
3c2620823b
commit
28e9e3f237
6 changed files with 154 additions and 16 deletions
|
|
@ -170,6 +170,8 @@ func (c *FloatHistogramChunk) Iterator(it Iterator) Iterator {
|
|||
type FloatHistogramAppender struct {
|
||||
b *bstream
|
||||
|
||||
headerLayout histogramHeaderLayout
|
||||
|
||||
// Layout:
|
||||
schema int32
|
||||
zThreshold float64
|
||||
|
|
@ -181,16 +183,32 @@ type FloatHistogramAppender struct {
|
|||
pBuckets, nBuckets []xorValue
|
||||
}
|
||||
|
||||
func (a *FloatHistogramAppender) counterResetHeaderPos() int {
|
||||
if a.headerLayout == histogramHeaderST {
|
||||
return 0
|
||||
}
|
||||
return histogramFlagPos
|
||||
}
|
||||
|
||||
func (a *FloatHistogramAppender) sampleCountMask() uint16 {
|
||||
if a.headerLayout == histogramHeaderST {
|
||||
return 0x3FFF
|
||||
}
|
||||
return 0xFFFF
|
||||
}
|
||||
|
||||
func (a *FloatHistogramAppender) GetCounterResetHeader() CounterResetHeader {
|
||||
return CounterResetHeader(a.b.bytes()[histogramFlagPos] & CounterResetHeaderMask)
|
||||
return CounterResetHeader(a.b.bytes()[a.counterResetHeaderPos()] & CounterResetHeaderMask)
|
||||
}
|
||||
|
||||
func (a *FloatHistogramAppender) setCounterResetHeader(cr CounterResetHeader) {
|
||||
a.b.bytes()[histogramFlagPos] = (a.b.bytes()[histogramFlagPos] & (^CounterResetHeaderMask)) | (byte(cr) & CounterResetHeaderMask)
|
||||
b := a.b.bytes()
|
||||
pos := a.counterResetHeaderPos()
|
||||
b[pos] = (b[pos] &^ CounterResetHeaderMask) | (byte(cr) & CounterResetHeaderMask)
|
||||
}
|
||||
|
||||
func (a *FloatHistogramAppender) NumSamples() int {
|
||||
return int(binary.BigEndian.Uint16(a.b.bytes()))
|
||||
return int(binary.BigEndian.Uint16(a.b.bytes()) & a.sampleCountMask())
|
||||
}
|
||||
|
||||
// Append implements Appender. This implementation panics because normal float
|
||||
|
|
|
|||
|
|
@ -79,11 +79,12 @@ func (c *FloatHistogramSTChunk) Appender() (Appender, error) {
|
|||
if len(c.b.stream) == histogramHeaderSize {
|
||||
return &FloatHistogramSTAppender{
|
||||
FloatHistogramAppender: FloatHistogramAppender{
|
||||
b: &c.b,
|
||||
t: math.MinInt64,
|
||||
sum: xorValue{leading: 0xff},
|
||||
cnt: xorValue{leading: 0xff},
|
||||
zCnt: xorValue{leading: 0xff},
|
||||
b: &c.b,
|
||||
headerLayout: histogramHeaderST,
|
||||
t: math.MinInt64,
|
||||
sum: xorValue{leading: 0xff},
|
||||
cnt: xorValue{leading: 0xff},
|
||||
zCnt: xorValue{leading: 0xff},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -118,7 +119,8 @@ func (c *FloatHistogramSTChunk) Appender() (Appender, error) {
|
|||
|
||||
a := &FloatHistogramSTAppender{
|
||||
FloatHistogramAppender: FloatHistogramAppender{
|
||||
b: &c.b,
|
||||
b: &c.b,
|
||||
headerLayout: histogramHeaderST,
|
||||
|
||||
schema: it.schema,
|
||||
zThreshold: it.zThreshold,
|
||||
|
|
|
|||
|
|
@ -531,3 +531,49 @@ func TestFloatHistogramSTChunkGaugeRecodePreservesST(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, 3, stChunk.NumSamples())
|
||||
}
|
||||
|
||||
func TestFloatHistogramSTChunk_CounterResetHeader(t *testing.T) {
|
||||
c := NewFloatHistogramSTChunk()
|
||||
require.Len(t, c.Bytes(), 3)
|
||||
|
||||
app, err := c.Appender()
|
||||
require.NoError(t, err)
|
||||
happ := app.(*FloatHistogramSTAppender)
|
||||
|
||||
fh := tsdbutil.GenerateTestFloatHistograms(1)[0]
|
||||
_, _, _, err = happ.AppendFloatHistogram(nil, 100, 1000, fh, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
byte2Before := c.Bytes()[2]
|
||||
for _, cr := range []CounterResetHeader{UnknownCounterReset, CounterReset, NotCounterReset, GaugeType} {
|
||||
happ.setCounterResetHeader(cr)
|
||||
require.Equal(t, cr, c.GetCounterResetHeader())
|
||||
require.Equal(t, cr, happ.FloatHistogramAppender.GetCounterResetHeader())
|
||||
require.Equal(t, 1, c.NumSamples(), "NumSamples must not include CR bits")
|
||||
require.Equal(t, 1, happ.FloatHistogramAppender.NumSamples(), "NumSamples must not include CR bits")
|
||||
require.Equal(t, byte2Before, c.Bytes()[2], "setting CR must not disturb byte 2 (ST header)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloatHistogramSTAppenderPreviousEmbeddedAppenderUsesSTHeader(t *testing.T) {
|
||||
prevChunk := NewFloatHistogramSTChunk()
|
||||
prevApp, err := prevChunk.Appender()
|
||||
require.NoError(t, err)
|
||||
|
||||
fh1 := tsdbutil.GenerateTestFloatHistogram(10)
|
||||
_, _, prevApp, err = prevApp.AppendFloatHistogram(nil, 100, 1000, fh1, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
prevSTApp := prevApp.(*FloatHistogramSTAppender)
|
||||
prevSTApp.setCounterResetHeader(NotCounterReset)
|
||||
prevChunk.Bytes()[2] = byte(GaugeType)
|
||||
|
||||
nextChunk := NewFloatHistogramSTChunk()
|
||||
nextApp, err := nextChunk.Appender()
|
||||
require.NoError(t, err)
|
||||
|
||||
fh2 := tsdbutil.GenerateTestFloatHistogram(0)
|
||||
_, _, _, err = nextApp.AppendFloatHistogram(&prevSTApp.FloatHistogramAppender, 200, 2000, fh2, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, CounterReset, nextChunk.GetCounterResetHeader())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,10 +178,18 @@ func (c *HistogramChunk) Iterator(it Iterator) Iterator {
|
|||
return c.iterator(it)
|
||||
}
|
||||
|
||||
type histogramHeaderLayout uint8
|
||||
|
||||
const (
|
||||
histogramHeaderST histogramHeaderLayout = 1
|
||||
)
|
||||
|
||||
// HistogramAppender is an Appender implementation for sparse histograms.
|
||||
type HistogramAppender struct {
|
||||
b *bstream
|
||||
|
||||
headerLayout histogramHeaderLayout
|
||||
|
||||
// Layout:
|
||||
schema int32
|
||||
zThreshold float64
|
||||
|
|
@ -205,16 +213,32 @@ type HistogramAppender struct {
|
|||
trailing uint8
|
||||
}
|
||||
|
||||
func (a *HistogramAppender) counterResetHeaderPos() int {
|
||||
if a.headerLayout == histogramHeaderST {
|
||||
return 0
|
||||
}
|
||||
return histogramFlagPos
|
||||
}
|
||||
|
||||
func (a *HistogramAppender) sampleCountMask() uint16 {
|
||||
if a.headerLayout == histogramHeaderST {
|
||||
return 0x3FFF
|
||||
}
|
||||
return 0xFFFF
|
||||
}
|
||||
|
||||
func (a *HistogramAppender) GetCounterResetHeader() CounterResetHeader {
|
||||
return CounterResetHeader(a.b.bytes()[histogramFlagPos] & CounterResetHeaderMask)
|
||||
return CounterResetHeader(a.b.bytes()[a.counterResetHeaderPos()] & CounterResetHeaderMask)
|
||||
}
|
||||
|
||||
func (a *HistogramAppender) setCounterResetHeader(cr CounterResetHeader) {
|
||||
a.b.bytes()[histogramFlagPos] = (a.b.bytes()[histogramFlagPos] & (^CounterResetHeaderMask)) | (byte(cr) & CounterResetHeaderMask)
|
||||
b := a.b.bytes()
|
||||
pos := a.counterResetHeaderPos()
|
||||
b[pos] = (b[pos] &^ CounterResetHeaderMask) | (byte(cr) & CounterResetHeaderMask)
|
||||
}
|
||||
|
||||
func (a *HistogramAppender) NumSamples() int {
|
||||
return int(binary.BigEndian.Uint16(a.b.bytes()))
|
||||
return int(binary.BigEndian.Uint16(a.b.bytes()) & a.sampleCountMask())
|
||||
}
|
||||
|
||||
// Append implements Appender. This implementation panics because normal float
|
||||
|
|
|
|||
|
|
@ -78,9 +78,10 @@ func (c *HistogramSTChunk) Appender() (Appender, error) {
|
|||
if len(c.b.stream) == histogramHeaderSize {
|
||||
return &HistogramSTAppender{
|
||||
HistogramAppender: HistogramAppender{
|
||||
b: &c.b,
|
||||
t: math.MinInt64,
|
||||
leading: 0xff,
|
||||
b: &c.b,
|
||||
headerLayout: histogramHeaderST,
|
||||
t: math.MinInt64,
|
||||
leading: 0xff,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -99,7 +100,8 @@ func (c *HistogramSTChunk) Appender() (Appender, error) {
|
|||
|
||||
a := &HistogramSTAppender{
|
||||
HistogramAppender: HistogramAppender{
|
||||
b: &c.b,
|
||||
b: &c.b,
|
||||
headerLayout: histogramHeaderST,
|
||||
|
||||
schema: it.schema,
|
||||
zThreshold: it.zThreshold,
|
||||
|
|
|
|||
|
|
@ -528,3 +528,49 @@ func TestHistogramSTChunkGauge(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t, 3, stChunk.NumSamples())
|
||||
}
|
||||
|
||||
func TestHistogramSTChunk_CounterResetHeader(t *testing.T) {
|
||||
c := NewHistogramSTChunk()
|
||||
require.Len(t, c.Bytes(), 3)
|
||||
|
||||
app, err := c.Appender()
|
||||
require.NoError(t, err)
|
||||
happ := app.(*HistogramSTAppender)
|
||||
|
||||
h := tsdbutil.GenerateTestHistograms(1)[0]
|
||||
_, _, _, err = happ.AppendHistogram(nil, 100, 1000, h, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
byte2Before := c.Bytes()[2]
|
||||
for _, cr := range []CounterResetHeader{UnknownCounterReset, CounterReset, NotCounterReset, GaugeType} {
|
||||
happ.setCounterResetHeader(cr)
|
||||
require.Equal(t, cr, c.GetCounterResetHeader())
|
||||
require.Equal(t, cr, happ.HistogramAppender.GetCounterResetHeader())
|
||||
require.Equal(t, 1, c.NumSamples())
|
||||
require.Equal(t, 1, happ.HistogramAppender.NumSamples())
|
||||
require.Equal(t, byte2Before, c.Bytes()[2])
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistogramSTAppenderPreviousEmbeddedAppenderUsesSTHeader(t *testing.T) {
|
||||
prevChunk := NewHistogramSTChunk()
|
||||
prevApp, err := prevChunk.Appender()
|
||||
require.NoError(t, err)
|
||||
|
||||
h1 := tsdbutil.GenerateTestHistogram(10)
|
||||
_, _, prevApp, err = prevApp.AppendHistogram(nil, 100, 1000, h1, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
prevSTApp := prevApp.(*HistogramSTAppender)
|
||||
prevSTApp.setCounterResetHeader(NotCounterReset)
|
||||
prevChunk.Bytes()[2] = byte(GaugeType)
|
||||
|
||||
nextChunk := NewHistogramSTChunk()
|
||||
nextApp, err := nextChunk.Appender()
|
||||
require.NoError(t, err)
|
||||
|
||||
h2 := tsdbutil.GenerateTestHistogram(0)
|
||||
_, _, _, err = nextApp.AppendHistogram(&prevSTApp.HistogramAppender, 200, 2000, h2, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, CounterReset, nextChunk.GetCounterResetHeader())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue