diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62c8935 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/histogram.go b/histogram.go index a576681..5c7a80b 100644 --- a/histogram.go +++ b/histogram.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "math" + "strings" "sync" "time" ) @@ -55,6 +56,8 @@ type Histogram struct { upper uint64 sum float64 + + compatible bool } // Reset resets the given histogram. @@ -149,7 +152,10 @@ func (h *Histogram) VisitNonZeroBuckets(f func(vmrange string, count uint64)) { // // The returned histogram is safe to use from concurrent goroutines. func NewHistogram(name string) *Histogram { - return defaultSet.NewHistogram(name) + return defaultSet.NewHistogram(name, true) +} +func NewHistogramByVM(name string) *Histogram { + return defaultSet.NewHistogram(name, false) } // GetOrCreateHistogram returns registered histogram with the given name @@ -201,6 +207,10 @@ var ( ) func (h *Histogram) marshalTo(prefix string, w io.Writer) { + if h.compatible { + h.marshalToPrometheus(prefix, w) + return + } countTotal := uint64(0) h.VisitNonZeroBuckets(func(vmrange string, count uint64) { tag := fmt.Sprintf("vmrange=%q", vmrange) @@ -221,6 +231,31 @@ func (h *Histogram) marshalTo(prefix string, w io.Writer) { } fmt.Fprintf(w, "%s_count%s %d\n", name, labels, countTotal) } +func (h *Histogram) marshalToPrometheus(prefix string, w io.Writer) { + countTotal := uint64(0) + h.VisitNonZeroBuckets(func(vmrange string, count uint64) { + v := strings.Split(vmrange, "...") + if len(v) != 2 { + return + } + tag := fmt.Sprintf("le=%q", v[1]) + metricName := addTag(prefix, tag) + name, labels := splitMetricName(metricName) + countTotal += count + fmt.Fprintf(w, "%s_bucket%s %d\n", name, labels, countTotal) + }) + if countTotal == 0 { + return + } + name, labels := splitMetricName(prefix) + sum := h.getSum() + if float64(int64(sum)) == sum { + fmt.Fprintf(w, "%s_sum%s %d\n", name, labels, int64(sum)) + } else { + fmt.Fprintf(w, "%s_sum%s %g\n", name, labels, sum) + } + fmt.Fprintf(w, "%s_count%s %d\n", name, labels, countTotal) +} func (h *Histogram) getSum() float64 { h.mu.Lock() diff --git a/set.go b/set.go index 79355ea..43667be 100644 --- a/set.go +++ b/set.go @@ -65,8 +65,8 @@ func (s *Set) WritePrometheus(w io.Writer) { // - foo{bar="baz",aaa="b"} // // The returned histogram is safe to use from concurrent goroutines. -func (s *Set) NewHistogram(name string) *Histogram { - h := &Histogram{} +func (s *Set) NewHistogram(name string, compatible bool) *Histogram { + h := &Histogram{compatible: compatible} s.registerMetric(name, h) return h } diff --git a/set_test.go b/set_test.go index 66ed07a..4ddba29 100644 --- a/set_test.go +++ b/set_test.go @@ -29,7 +29,7 @@ func TestNewSet(t *testing.T) { if sm == nil { t.Fatalf("NewSummary returned nil") } - h := s.NewHistogram(fmt.Sprintf("histogram_%d", j)) + h := s.NewHistogram(fmt.Sprintf("histogram_%d", j), false) if h == nil { t.Fatalf("NewHistogram returned nil") } @@ -71,7 +71,7 @@ func TestSetUnregisterAllMetrics(t *testing.T) { for i := 0; i < 10; i++ { _ = s.NewCounter(fmt.Sprintf("counter_%d", i)) _ = s.NewSummary(fmt.Sprintf("summary_%d", i)) - _ = s.NewHistogram(fmt.Sprintf("histogram_%d", i)) + _ = s.NewHistogram(fmt.Sprintf("histogram_%d", i), false) _ = s.NewGauge(fmt.Sprintf("gauge_%d", i), func() float64 { return 0 }) expectedMetricsCount += 4 }