diff options
author | Vidhu Kant Sharma <bokuwakanojogahoshii@yahoo.com> | 2020-10-19 11:05:36 +0530 |
---|---|---|
committer | Vidhu Kant Sharma <bokuwakanojogahoshii@yahoo.com> | 2020-10-19 11:05:36 +0530 |
commit | 9c2ad91230d72fe6d661450cc78300ea223ae2bc (patch) | |
tree | 17bd774b3f972359dfbb46248f085bbf1c6dae98 /vendor/github.com/heroku/x/hmetrics |
make it better
Diffstat (limited to 'vendor/github.com/heroku/x/hmetrics')
-rw-r--r-- | vendor/github.com/heroku/x/hmetrics/doc.go | 5 | ||||
-rw-r--r-- | vendor/github.com/heroku/x/hmetrics/hmetrics.go | 169 | ||||
-rw-r--r-- | vendor/github.com/heroku/x/hmetrics/onload/README.md | 7 | ||||
-rw-r--r-- | vendor/github.com/heroku/x/hmetrics/onload/init.go | 25 |
4 files changed, 206 insertions, 0 deletions
diff --git a/vendor/github.com/heroku/x/hmetrics/doc.go b/vendor/github.com/heroku/x/hmetrics/doc.go new file mode 100644 index 0000000..f33757c --- /dev/null +++ b/vendor/github.com/heroku/x/hmetrics/doc.go @@ -0,0 +1,5 @@ +/* +package hmetrics is a self-contained client for heroku Go runtime metrics. +*/ + +package hmetrics diff --git a/vendor/github.com/heroku/x/hmetrics/hmetrics.go b/vendor/github.com/heroku/x/hmetrics/hmetrics.go new file mode 100644 index 0000000..4ae88f6 --- /dev/null +++ b/vendor/github.com/heroku/x/hmetrics/hmetrics.go @@ -0,0 +1,169 @@ +package hmetrics + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "os" + "runtime" + "sync" + "time" +) + +const ( + metricWaitTime = 20 * time.Second +) + +var ( + DefaultEndpoint string +) + +func init() { + DefaultEndpoint = os.Getenv("HEROKU_METRICS_URL") +} + +type AlreadyStarted struct{} + +func (as AlreadyStarted) Error() string { + return "already started" +} + +func (as AlreadyStarted) Fatal() bool { + return false +} + +type HerokuMetricsURLUnset struct{} + +func (e HerokuMetricsURLUnset) Error() string { + return "cannot report metrics because HEROKU_METRICS_URL is unset" +} + +func (e HerokuMetricsURLUnset) Fatal() bool { + return true +} + +var ( + mu sync.Mutex + started bool +) + +// ErrHandler receives any errors encountered during collection or reporting of metrics to Heroku. Processing of metrics +// continues if the ErrHandler returns nil, but aborts if the ErrHandler itself returns an error. +type ErrHandler func(err error) error + +func Report(ctx context.Context, ef ErrHandler) error { + mu.Lock() + defer mu.Unlock() + if started { + return AlreadyStarted{} + } + endpoint := DefaultEndpoint + if endpoint == "" { + return HerokuMetricsURLUnset{} + } + if ef == nil { + ef = func(_ error) error { return nil } + } + go report(ctx, endpoint, ef) + started = true + return nil +} + +// The only thing that should come after an exit() is a return. +// Best to use in a function that can defer it. +func exit() { + mu.Lock() + defer mu.Unlock() + started = false +} + +func report(ctx context.Context, endpoint string, ef ErrHandler) { + defer exit() + + t := time.NewTicker(metricWaitTime) + defer t.Stop() + + for { + select { + case <-t.C: + case <-ctx.Done(): + return + } + + if err := gatherMetrics(); err != nil { + if err := ef(err); err != nil { + return + } + continue + } + if err := submitPayload(ctx, endpoint); err != nil { + if err := ef(err); err != nil { + return + } + continue + } + } +} + +var ( + lastGCPause uint64 + lastNumGC uint32 + buf bytes.Buffer +) + +// TODO: If we ever have high frequency charts HeapIdle minus HeapReleased could be interesting. +func gatherMetrics() error { + var stats runtime.MemStats + runtime.ReadMemStats(&stats) + + // cribbed from https://github.com/codahale/metrics/blob/master/runtime/memstats.go + + pauseNS := stats.PauseTotalNs - lastGCPause + lastGCPause = stats.PauseTotalNs + + numGC := stats.NumGC - lastNumGC + lastNumGC = stats.NumGC + + result := struct { + Counters map[string]float64 `json:"counters"` + Gauges map[string]float64 `json:"gauges"` + }{ + Counters: map[string]float64{ + "go.gc.collections": float64(numGC), + "go.gc.pause.ns": float64(pauseNS), + }, + Gauges: map[string]float64{ + "go.memory.heap.bytes": float64(stats.Alloc), + "go.memory.stack.bytes": float64(stats.StackInuse), + "go.memory.heap.objects": float64(stats.Mallocs - stats.Frees), // Number of "live" objects. + "go.gc.goal": float64(stats.NextGC), // Goal heap size for next GC. + "go.routines": float64(runtime.NumGoroutine()), // Current number of goroutines. + }, + } + + buf.Reset() + return json.NewEncoder(&buf).Encode(result) +} + +func submitPayload(ctx context.Context, where string) error { + req, err := http.NewRequest("POST", where, &buf) + if err != nil { + return err + } + req = req.WithContext(ctx) + req.Header.Add("Content-Type", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("expected %v (http.StatusOK) but got %s", http.StatusOK, resp.Status) + } + + return nil +} diff --git a/vendor/github.com/heroku/x/hmetrics/onload/README.md b/vendor/github.com/heroku/x/hmetrics/onload/README.md new file mode 100644 index 0000000..037068e --- /dev/null +++ b/vendor/github.com/heroku/x/hmetrics/onload/README.md @@ -0,0 +1,7 @@ +runtime-metrics +=============== + +This will only be useful if you are inside the runtime metrics private beta. + +This package, once loaded, will implicitly dump a subset of runtime performace +metrics to the URL denoted by `HEROKU_METRICS_URL` diff --git a/vendor/github.com/heroku/x/hmetrics/onload/init.go b/vendor/github.com/heroku/x/hmetrics/onload/init.go new file mode 100644 index 0000000..d6fb49d --- /dev/null +++ b/vendor/github.com/heroku/x/hmetrics/onload/init.go @@ -0,0 +1,25 @@ +/* +package onload automatically starts up the hmetrics reporting. + +Use this package when you don't care about shutting down them metrics reporting or being notified of any reporting +errors. + +usage: + +import ( + _ "github.com/heroku/x/hmetrics/onload" +) + +*/ + +package onloads + +import ( + "context" + + "github.com/heroku/x/hmetrics" +) + +func init() { + hmetrics.Report(context.Background(), nil) +} |