Skip to content

Commit

Permalink
Merge branch 'master' of github.com:stuartcarnie/go-metrics
Browse files Browse the repository at this point in the history
I refactored and renamed for clarity and consistency.  I added WriteJSON
to wrap WriteJSONOnce.
  • Loading branch information
rcrowley committed Jul 26, 2014
2 parents 3be59ce + e93a73c commit 6370c0c
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 12 deletions.
21 changes: 20 additions & 1 deletion json.go
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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 changes: 10 additions & 0 deletions json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
47 changes: 36 additions & 11 deletions writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,47 @@ 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)
time.Sleep(d)
}
}

// 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())
Expand All @@ -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())
Expand All @@ -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())
Expand All @@ -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 changes: 22 additions & 0 deletions writer_test.go
Original file line number Diff line number Diff line change
@@ -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()
}
}
}

0 comments on commit 6370c0c

Please sign in to comment.