Parcourir la source

Merge branch 'master' of github.com:stuartcarnie/go-metrics

I refactored and renamed for clarity and consistency.  I added WriteJSON
to wrap WriteJSONOnce.
Richard Crowley il y a 11 ans
Parent
commit
6370c0ca61
4 fichiers modifiés avec 88 ajouts et 12 suppressions
  1. 20 1
      json.go
  2. 10 0
      json_test.go
  3. 36 11
      writer.go
  4. 22 0
      writer_test.go

+ 20 - 1
json.go

@@ -1,6 +1,10 @@
 package metrics
 
-import "encoding/json"
+import (
+	"encoding/json"
+	"io"
+	"time"
+)
 
 // MarshalJSON returns a byte slice containing a JSON representation of all
 // the metrics in the Registry.
@@ -63,3 +67,18 @@ func (r StandardRegistry) MarshalJSON() ([]byte, error) {
 	})
 	return json.Marshal(data)
 }
+
+// WriteJSON writes metrics from the given registry  periodically to the
+// specified io.Writer as JSON.
+func WriteJSON(r Registry, d time.Duration, w io.Writer) {
+	for {
+		WriteJSONOnce(r, w)
+		time.Sleep(d)
+	}
+}
+
+// WriteJSONOnce writes metrics from the given registry to the specified
+// io.Writer as JSON.
+func WriteJSONOnce(r Registry, w io.Writer) {
+	json.NewEncoder(w).Encode(r)
+}

+ 10 - 0
json_test.go

@@ -16,3 +16,13 @@ func TestRegistryMarshallJSON(t *testing.T) {
 		t.Fatalf(s)
 	}
 }
+
+func TestRegistryWriteJSONOnce(t *testing.T) {
+	r := NewRegistry()
+	r.Register("counter", NewCounter())
+	b := &bytes.Buffer{}
+	WriteJSONOnce(r, b)
+	if s := b.String(); s != "{\"counter\":{\"count\":0}}\n" {
+		t.Fail()
+	}
+}

+ 36 - 11
writer.go

@@ -3,11 +3,12 @@ package metrics
 import (
 	"fmt"
 	"io"
+	"sort"
 	"time"
 )
 
-// Output each metric in the given registry periodically using the given
-// io.Writer.
+// Write sorts writes each metric in the given registry periodically to the
+// given io.Writer.
 func Write(r Registry, d time.Duration, w io.Writer) {
 	for {
 		WriteOnce(r, w)
@@ -15,26 +16,34 @@ func Write(r Registry, d time.Duration, w io.Writer) {
 	}
 }
 
+// WriteOnce sorts and writes metrics in the given registry to the given
+// io.Writer.
 func WriteOnce(r Registry, w io.Writer) {
+	var namedMetrics namedMetricSlice
 	r.Each(func(name string, i interface{}) {
-		switch metric := i.(type) {
+		namedMetrics = append(namedMetrics, namedMetric{name, i})
+	})
+
+	sort.Sort(namedMetrics)
+	for _, namedMetric := range namedMetrics {
+		switch metric := namedMetric.m.(type) {
 		case Counter:
-			fmt.Fprintf(w, "counter %s\n", name)
+			fmt.Fprintf(w, "counter %s\n", namedMetric.name)
 			fmt.Fprintf(w, "  count:       %9d\n", metric.Count())
 		case Gauge:
-			fmt.Fprintf(w, "gauge %s\n", name)
+			fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
 			fmt.Fprintf(w, "  value:       %9d\n", metric.Value())
 		case GaugeFloat64:
-			fmt.Fprintf(w, "gauge %s\n", name)
+			fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
 			fmt.Fprintf(w, "  value:       %f\n", metric.Value())
 		case Healthcheck:
 			metric.Check()
-			fmt.Fprintf(w, "healthcheck %s\n", name)
+			fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name)
 			fmt.Fprintf(w, "  error:       %v\n", metric.Error())
 		case Histogram:
 			h := metric.Snapshot()
 			ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
-			fmt.Fprintf(w, "histogram %s\n", name)
+			fmt.Fprintf(w, "histogram %s\n", namedMetric.name)
 			fmt.Fprintf(w, "  count:       %9d\n", h.Count())
 			fmt.Fprintf(w, "  min:         %9d\n", h.Min())
 			fmt.Fprintf(w, "  max:         %9d\n", h.Max())
@@ -47,7 +56,7 @@ func WriteOnce(r Registry, w io.Writer) {
 			fmt.Fprintf(w, "  99.9%%:       %12.2f\n", ps[4])
 		case Meter:
 			m := metric.Snapshot()
-			fmt.Fprintf(w, "meter %s\n", name)
+			fmt.Fprintf(w, "meter %s\n", namedMetric.name)
 			fmt.Fprintf(w, "  count:       %9d\n", m.Count())
 			fmt.Fprintf(w, "  1-min rate:  %12.2f\n", m.Rate1())
 			fmt.Fprintf(w, "  5-min rate:  %12.2f\n", m.Rate5())
@@ -56,7 +65,7 @@ func WriteOnce(r Registry, w io.Writer) {
 		case Timer:
 			t := metric.Snapshot()
 			ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
-			fmt.Fprintf(w, "timer %s\n", name)
+			fmt.Fprintf(w, "timer %s\n", namedMetric.name)
 			fmt.Fprintf(w, "  count:       %9d\n", t.Count())
 			fmt.Fprintf(w, "  min:         %9d\n", t.Min())
 			fmt.Fprintf(w, "  max:         %9d\n", t.Max())
@@ -72,5 +81,21 @@ func WriteOnce(r Registry, w io.Writer) {
 			fmt.Fprintf(w, "  15-min rate: %12.2f\n", t.Rate15())
 			fmt.Fprintf(w, "  mean rate:   %12.2f\n", t.RateMean())
 		}
-	})
+	}
+}
+
+type namedMetric struct {
+	name string
+	m    interface{}
+}
+
+// namedMetricSlice is a slice of namedMetrics that implements sort.Interface.
+type namedMetricSlice []namedMetric
+
+func (nms namedMetricSlice) Len() int { return len(nms) }
+
+func (nms namedMetricSlice) Swap(i, j int) { nms[i], nms[j] = nms[j], nms[i] }
+
+func (nms namedMetricSlice) Less(i, j int) bool {
+	return nms[i].name < nms[j].name
 }

+ 22 - 0
writer_test.go

@@ -0,0 +1,22 @@
+package metrics
+
+import (
+	"sort"
+	"testing"
+)
+
+func TestMetricsSorting(t *testing.T) {
+	var namedMetrics = namedMetricSlice{
+		{name: "zzz"},
+		{name: "bbb"},
+		{name: "fff"},
+		{name: "ggg"},
+	}
+
+	sort.Sort(namedMetrics)
+	for i, name := range []string{"bbb", "fff", "ggg", "zzz"} {
+		if namedMetrics[i].name != name {
+			t.Fail()
+		}
+	}
+}