Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"io"
"time"
"fmt"
)

// MarshalJSON returns a byte slice containing a JSON representation of all
Expand Down Expand Up @@ -68,6 +69,72 @@ func (r *StandardRegistry) MarshalJSON() ([]byte, error) {
return json.Marshal(data)
}


// MarshalJSONStringified returns a byte slice containing a JSON representation of all
// the metrics in the Registry with values stringified.
func (r *StandardRegistry) MarshalJSONStringified(scale time.Duration) ([]byte, error) {
du := float64(scale)
duSuffix := scale.String()[1:]

data := make(map[string]map[string]interface{})
r.Each(func(name string, i interface{}) {
values := make(map[string]interface{})
switch metric := i.(type) {
case Counter:
values["count"] = fmt.Sprintf("%9d", metric.Count())
case Gauge:
values["value"] = fmt.Sprintf("%9d", metric.Value())
case GaugeFloat64:
values["value"] = fmt.Sprintf("%f", metric.Value())
case Healthcheck:
values["error"] = nil
metric.Check()
if err := metric.Error(); nil != err {
values["error"] = metric.Error().Error()
}
case Histogram:
h := metric.Snapshot()
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
values["count"] = fmt.Sprintf("%9d", h.Count())
values["min"] = fmt.Sprintf("%9d", h.Min())
values["max"] = fmt.Sprintf("%9d", h.Max())
values["mean"] = fmt.Sprintf("%12.2f", h.Mean())
values["stddev"] = fmt.Sprintf("%12.2f", h.StdDev())
values["median"] = fmt.Sprintf("%12.2f", ps[0])
values["75%"] = fmt.Sprintf("%12.2f", ps[1])
values["95%"] = fmt.Sprintf("%12.2f", ps[2])
values["99%"] = fmt.Sprintf("%12.2f", ps[3])
values["99.9%"] = fmt.Sprintf("%12.2f", ps[4])
case Meter:
m := metric.Snapshot()
values["count"] = fmt.Sprintf("%9d", m.Count())
values["1m.rate"] = fmt.Sprintf("%12.2f", m.Rate1())
values["5m.rate"] = fmt.Sprintf("%12.2f", m.Rate5())
values["15m.rate"] = fmt.Sprintf("%12.2f", m.Rate15())
values["mean.rate"] = fmt.Sprintf("%12.2f", m.RateMean())
case Timer:
t := metric.Snapshot()
ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
values["count"] = fmt.Sprintf("%9d", t.Count())
values["min"] = fmt.Sprintf("%12.2f%s", float64(t.Min())/du, duSuffix)
values["max"] = fmt.Sprintf("%12.2f%s", float64(t.Max())/du, duSuffix)
values["mean"] = fmt.Sprintf("%12.2f%s", t.Mean()/du, duSuffix)
values["stddev"] = fmt.Sprintf("%12.2f%s", t.StdDev()/du, duSuffix)
values["median"] = fmt.Sprintf("%12.2f%s", ps[0]/du, duSuffix)
values["75%"] = fmt.Sprintf("%12.2f%s", ps[1]/du, duSuffix)
values["95%"] = fmt.Sprintf("%12.2f%s", ps[2]/du, duSuffix)
values["99%"] = fmt.Sprintf("%12.2f%s", ps[3]/du, duSuffix)
values["99.9%"] = fmt.Sprintf("%12.2f%s", ps[4]/du, duSuffix)
values["1m.rate"] = fmt.Sprintf("%12.2f", t.Rate1())
values["5m.rate"] = fmt.Sprintf("%12.2f", t.Rate5())
values["15m.rate"] = fmt.Sprintf("%12.2f", t.Rate15())
values["mean.rate"] = fmt.Sprintf("%12.2f", t.RateMean())
}
data[name] = values
})
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) {
Expand Down
19 changes: 19 additions & 0 deletions log.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ func Log(r Registry, freq time.Duration, l Logger) {
LogScaled(r, freq, time.Nanosecond, l)
}

func LogJSON(r Registry, freq time.Duration, l Logger) {
LogJSONScaled(r, freq, time.Nanosecond, l)
}

// Output each metric in the given registry periodically using the given
// logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos.
func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {
Expand Down Expand Up @@ -78,3 +82,18 @@ func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {
})
}
}

// Output each metric in the given registry periodically, in JSON format using the given logger.
// Timings are converted into `scale` units (eg time.Millisecond) rather than nanos when the JSON is marshaled.
func LogJSONScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {

for _ = range time.Tick(freq) {
sr, ok := r.(*StandardRegistry)
if ok {
jsonMetrics, err := sr.MarshalJSONStringified(scale)
if err == nil {
l.Printf("%s\n", jsonMetrics)
}
}
}
}