Remove rounding error when marshaling histogram ranges
This commit is contained in:
parent
984b12dbb5
commit
577f3b5e99
21
histogram.go
21
histogram.go
@ -132,12 +132,12 @@ func (h *Histogram) marshalBucket(prefix string, w io.Writer, idx int) {
|
|||||||
if v == 0 {
|
if v == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
start := float64(0)
|
start := "0"
|
||||||
if idx > 0 {
|
if idx > 0 {
|
||||||
start = getRangeEndFromBucketIdx(uint(idx - 1))
|
start = getRangeEndFromBucketIdx(uint(idx - 1))
|
||||||
}
|
}
|
||||||
end := getRangeEndFromBucketIdx(uint(idx))
|
end := getRangeEndFromBucketIdx(uint(idx))
|
||||||
tag := fmt.Sprintf(`vmrange="%g...%g"`, start, end)
|
tag := fmt.Sprintf(`vmrange="%s...%s"`, start, end)
|
||||||
prefix = addTag(prefix, tag)
|
prefix = addTag(prefix, tag)
|
||||||
name, filters := splitMetricName(prefix)
|
name, filters := splitMetricName(prefix)
|
||||||
fmt.Fprintf(w, "%s_vmbucket%s %d\n", name, filters, v)
|
fmt.Fprintf(w, "%s_vmbucket%s %d\n", name, filters, v)
|
||||||
@ -180,20 +180,27 @@ func getBucketIdx(v float64) uint {
|
|||||||
return 1 + m + uint(e10-e10Min)*9
|
return 1 + m + uint(e10-e10Min)*9
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRangeEndFromBucketIdx(idx uint) float64 {
|
func getRangeEndFromBucketIdx(idx uint) string {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
return 0
|
return "0"
|
||||||
}
|
}
|
||||||
if idx == 1 {
|
if idx == 1 {
|
||||||
return math.Pow10(e10Min)
|
return fmt.Sprintf("1e%d", e10Min)
|
||||||
}
|
}
|
||||||
if idx >= bucketsCount-1 {
|
if idx >= bucketsCount-1 {
|
||||||
return math.Inf(1)
|
return "+Inf"
|
||||||
}
|
}
|
||||||
idx -= 2
|
idx -= 2
|
||||||
e10 := e10Min + int(idx/9)
|
e10 := e10Min + int(idx/9)
|
||||||
m := 2 + (idx % 9)
|
m := 2 + (idx % 9)
|
||||||
return math.Pow10(e10) * float64(m)
|
if m == 10 {
|
||||||
|
e10++
|
||||||
|
m = 1
|
||||||
|
}
|
||||||
|
if e10 == 0 {
|
||||||
|
return fmt.Sprintf("%d", m)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%de%d", m, e10)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Each range (10^n..10^(n+1)] for e10Min<=n<=e10Max is split into 9 equal sub-ranges, plus 3 additional buckets:
|
// Each range (10^n..10^(n+1)] for e10Min<=n<=e10Max is split into 9 equal sub-ranges, plus 3 additional buckets:
|
||||||
|
@ -66,37 +66,37 @@ func TestGetBucketIdx(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetRangeEndFromBucketIdx(t *testing.T) {
|
func TestGetRangeEndFromBucketIdx(t *testing.T) {
|
||||||
f := func(idx uint, endExpected float64) {
|
f := func(idx uint, endExpected string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
end := getRangeEndFromBucketIdx(idx)
|
end := getRangeEndFromBucketIdx(idx)
|
||||||
if end != endExpected {
|
if end != endExpected {
|
||||||
t.Fatalf("unexpected getRangeEndFromBucketIdx(%d); got %g; want %g", idx, end, endExpected)
|
t.Fatalf("unexpected getRangeEndFromBucketIdx(%d); got %s; want %s", idx, end, endExpected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f(0, 0)
|
f(0, "0")
|
||||||
f(1, math.Pow10(e10Min))
|
f(1, fmt.Sprintf("1e%d", e10Min))
|
||||||
f(2, 2*math.Pow10(e10Min))
|
f(2, fmt.Sprintf("2e%d", e10Min))
|
||||||
f(3, 3*math.Pow10(e10Min))
|
f(3, fmt.Sprintf("3e%d", e10Min))
|
||||||
f(9, 9*math.Pow10(e10Min))
|
f(9, fmt.Sprintf("9e%d", e10Min))
|
||||||
f(10, math.Pow10(e10Min+1))
|
f(10, fmt.Sprintf("1e%d", e10Min+1))
|
||||||
f(11, 2*math.Pow10(e10Min+1))
|
f(11, fmt.Sprintf("2e%d", e10Min+1))
|
||||||
f(16, 7*math.Pow10(e10Min+1))
|
f(16, fmt.Sprintf("7e%d", e10Min+1))
|
||||||
f(17, 8*math.Pow10(e10Min+1))
|
f(17, fmt.Sprintf("8e%d", e10Min+1))
|
||||||
f(18, 9*math.Pow10(e10Min+1))
|
f(18, fmt.Sprintf("9e%d", e10Min+1))
|
||||||
f(19, math.Pow10(e10Min+2))
|
f(19, fmt.Sprintf("1e%d", e10Min+2))
|
||||||
f(20, 2*math.Pow10(e10Min+2))
|
f(20, fmt.Sprintf("2e%d", e10Min+2))
|
||||||
f(21, 3*math.Pow10(e10Min+2))
|
f(21, fmt.Sprintf("3e%d", e10Min+2))
|
||||||
f(bucketsCount-21, 9*math.Pow10(e10Max-2))
|
f(bucketsCount-21, fmt.Sprintf("9e%d", e10Max-2))
|
||||||
f(bucketsCount-20, math.Pow10(e10Max-1))
|
f(bucketsCount-20, fmt.Sprintf("1e%d", e10Max-1))
|
||||||
f(bucketsCount-16, 5*math.Pow10(e10Max-1))
|
f(bucketsCount-16, fmt.Sprintf("5e%d", e10Max-1))
|
||||||
f(bucketsCount-13, 8*math.Pow10(e10Max-1))
|
f(bucketsCount-13, fmt.Sprintf("8e%d", e10Max-1))
|
||||||
f(bucketsCount-12, 9*math.Pow10(e10Max-1))
|
f(bucketsCount-12, fmt.Sprintf("9e%d", e10Max-1))
|
||||||
f(bucketsCount-11, math.Pow10(e10Max))
|
f(bucketsCount-11, fmt.Sprintf("1e%d", e10Max))
|
||||||
f(bucketsCount-10, 2*math.Pow10(e10Max))
|
f(bucketsCount-10, fmt.Sprintf("2e%d", e10Max))
|
||||||
f(bucketsCount-4, 8*math.Pow10(e10Max))
|
f(bucketsCount-4, fmt.Sprintf("8e%d", e10Max))
|
||||||
f(bucketsCount-3, 9*math.Pow10(e10Max))
|
f(bucketsCount-3, fmt.Sprintf("9e%d", e10Max))
|
||||||
f(bucketsCount-2, math.Pow10(e10Max+1))
|
f(bucketsCount-2, fmt.Sprintf("1e%d", e10Max+1))
|
||||||
f(bucketsCount-1, math.Inf(1))
|
f(bucketsCount-1, "+Inf")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHistogramSerial(t *testing.T) {
|
func TestHistogramSerial(t *testing.T) {
|
||||||
@ -117,8 +117,8 @@ func TestHistogramSerial(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the histogram prints <prefix>_xbucket on marshalTo call
|
// Make sure the histogram prints <prefix>_xbucket on marshalTo call
|
||||||
testMarshalTo(t, h, "prefix", "prefix_vmbucket{vmrange=\"80...90\"} 7\nprefix_vmbucket{vmrange=\"90...100\"} 10\nprefix_vmbucket{vmrange=\"100...200\"} 100\nprefix_vmbucket{vmrange=\"200...300\"} 100\nprefix_vmbucket{vmrange=\"300...400\"} 23\nprefix_sum 48840\nprefix_count 240\n")
|
testMarshalTo(t, h, "prefix", "prefix_vmbucket{vmrange=\"8e1...9e1\"} 7\nprefix_vmbucket{vmrange=\"9e1...1e2\"} 10\nprefix_vmbucket{vmrange=\"1e2...2e2\"} 100\nprefix_vmbucket{vmrange=\"2e2...3e2\"} 100\nprefix_vmbucket{vmrange=\"3e2...4e2\"} 23\nprefix_sum 48840\nprefix_count 240\n")
|
||||||
testMarshalTo(t, h, ` m{foo="bar"}`, "\t m_vmbucket{foo=\"bar\",vmrange=\"80...90\"} 7\n\t m_vmbucket{foo=\"bar\",vmrange=\"90...100\"} 10\n\t m_vmbucket{foo=\"bar\",vmrange=\"100...200\"} 100\n\t m_vmbucket{foo=\"bar\",vmrange=\"200...300\"} 100\n\t m_vmbucket{foo=\"bar\",vmrange=\"300...400\"} 23\n\t m_sum{foo=\"bar\"} 48840\n\t m_count{foo=\"bar\"} 240\n")
|
testMarshalTo(t, h, ` m{foo="bar"}`, "\t m_vmbucket{foo=\"bar\",vmrange=\"8e1...9e1\"} 7\n\t m_vmbucket{foo=\"bar\",vmrange=\"9e1...1e2\"} 10\n\t m_vmbucket{foo=\"bar\",vmrange=\"1e2...2e2\"} 100\n\t m_vmbucket{foo=\"bar\",vmrange=\"2e2...3e2\"} 100\n\t m_vmbucket{foo=\"bar\",vmrange=\"3e2...4e2\"} 23\n\t m_sum{foo=\"bar\"} 48840\n\t m_count{foo=\"bar\"} 240\n")
|
||||||
|
|
||||||
// Verify supported ranges
|
// Verify supported ranges
|
||||||
for i := -100; i < 100; i++ {
|
for i := -100; i < 100; i++ {
|
||||||
@ -148,7 +148,7 @@ func TestHistogramConcurrent(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
testMarshalTo(t, h, "prefix", "prefix_vmbucket{vmrange=\"0...0\"} 5\nprefix_vmbucket{vmrange=\"0.9...1\"} 5\nprefix_vmbucket{vmrange=\"1...2\"} 5\nprefix_vmbucket{vmrange=\"2...3\"} 5\nprefix_vmbucket{vmrange=\"3...4\"} 5\nprefix_vmbucket{vmrange=\"4...5\"} 5\nprefix_vmbucket{vmrange=\"5...6\"} 5\nprefix_vmbucket{vmrange=\"6...7\"} 5\nprefix_vmbucket{vmrange=\"7...8\"} 5\nprefix_vmbucket{vmrange=\"8...9\"} 5\nprefix_sum 225\nprefix_count 50\n")
|
testMarshalTo(t, h, "prefix", "prefix_vmbucket{vmrange=\"0...0\"} 5\nprefix_vmbucket{vmrange=\"9e-1...1\"} 5\nprefix_vmbucket{vmrange=\"1...2\"} 5\nprefix_vmbucket{vmrange=\"2...3\"} 5\nprefix_vmbucket{vmrange=\"3...4\"} 5\nprefix_vmbucket{vmrange=\"4...5\"} 5\nprefix_vmbucket{vmrange=\"5...6\"} 5\nprefix_vmbucket{vmrange=\"6...7\"} 5\nprefix_vmbucket{vmrange=\"7...8\"} 5\nprefix_vmbucket{vmrange=\"8...9\"} 5\nprefix_sum 225\nprefix_count 50\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHistogramWithTags(t *testing.T) {
|
func TestHistogramWithTags(t *testing.T) {
|
||||||
@ -159,7 +159,7 @@ func TestHistogramWithTags(t *testing.T) {
|
|||||||
var bb bytes.Buffer
|
var bb bytes.Buffer
|
||||||
WritePrometheus(&bb, false)
|
WritePrometheus(&bb, false)
|
||||||
result := bb.String()
|
result := bb.String()
|
||||||
namePrefixWithTag := `TestHistogram_vmbucket{tag="foo",vmrange="100...200"} 1` + "\n"
|
namePrefixWithTag := `TestHistogram_vmbucket{tag="foo",vmrange="1e2...2e2"} 1` + "\n"
|
||||||
if !strings.Contains(result, namePrefixWithTag) {
|
if !strings.Contains(result, namePrefixWithTag) {
|
||||||
t.Fatalf("missing histogram %s in the WritePrometheus output; got\n%s", namePrefixWithTag, result)
|
t.Fatalf("missing histogram %s in the WritePrometheus output; got\n%s", namePrefixWithTag, result)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user