Golang port of the java sampling library patan that provides:
- counters; keeping track of how many times something has taken place
- sampling; collecting samples and describing their distribution
- durations; measuring the duration of a task as a special case of sampling
The API is not identical to the java version, some methods are named differently.
When serializing a snapshot to JSON, it should produce the same output as the java version.
Start with:
go get gopkg.in/toefel18/go-patan.v1/metrics
Documentation: godoc.org/github.com/toefel18/go-patan/metrics
Usage:
package main
import (
"github.com/toefel18/go-patan/metrics"
"time"
"fmt"
"encoding/json"
)
func main() {
stopwatch := metrics.StartStopwatch()
time.Sleep(2 * time.Second)
metrics.AddSample("mem.allocations", 167.0334)
metrics.AddSample("mem.allocations", 111.9216)
metrics.AddSample("mem.allocations", 133.4686)
metrics.AddSample("mem.collects", 2)
metrics.AddToCounter("active.sessions", 132)
metrics.DecrementCounter("active.sessions")
metrics.RecordElapsedTime("my.heavy.operation", stopwatch)
snapshot := metrics.Snapshot()
duration, exists := snapshot.Durations()["my.heavy.operation"]
if exists {
fmt.Print("duration has sample count of ", duration.SampleCount()) // samplecount = 1
} else {
fmt.Print("duration does not exist")
}
// JSONizing a snapshot that can be published through REST
if json, err := json.MarshalIndent(snapshot, "", " "); err == nil {
fmt.Println(string(json))
}
}
The output will be:
{
"timestampStarted": 1480792554683,
"timestampTaken": 1480792556683,
"durations": {
"my.heavy.operation": {
"sampleCount": 1,
"minimum": 2000.129942,
"maximum": 2000.129942,
"mean": 2000.129942,
"stdDeviation": 0
}
},
"counters": {
"active.sessions": 131
},
"samples": {
"mem.allocations": {
"sampleCount": 3,
"minimum": 111.9216,
"maximum": 167.0334,
"mean": 137.47453333333334,
"stdDeviation": 27.77342707001304
},
"mem.collects": {
"sampleCount": 1,
"minimum": 2,
"maximum": 2,
"mean": 2,
"stdDeviation": 0
}
}
}
metrics
is the default metrics instance, which is always and directly available when using patan. It's also possible to create multiple
instances of metrics
, which could be useful to separate detailed and global measurements or public/private measurements.
package main
import (
"github.com/toefel18/go-patan/metrics"
"net/http"
"fmt"
"html"
)
func main() {
apiMetrics := metrics.New()
dbMetrics := metrics.New()
http.HandleFunc("/music/songs", func(w http.ResponseWriter, r *http.Request) {
apiMetrics.MeasureFunc("api.music.songs", func () {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
})
// or
http.HandleFunc("/music/albums", func(w http.ResponseWriter, r *http.Request) {
stopwatch := metrics.StartStopwatch()
data := "some database operation"
dbMetrics.RecordElapsedTime("db.music.albums", stopwatch) // stopwatch is not bound to a specific instance!
fmt.Fprintf(w, "Hello, %q " + data, html.EscapeString(r.URL.Path))
apiMetrics.RecordElapsedTime("api.music.albums", stopwatch)
})
}