Created
March 23, 2018 21:19
-
-
Save graphaelli/43ae22d3cff33f71bb3ecca0237d11a4 to your computer and use it in GitHub Desktop.
messing around with the prometheus client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Gopkg.toml example | |
# | |
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md | |
# for detailed Gopkg.toml documentation. | |
# | |
# required = ["github.com/user/thing/cmd/thing"] | |
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] | |
# | |
# [[constraint]] | |
# name = "github.com/user/project" | |
# version = "1.0.0" | |
# | |
# [[constraint]] | |
# name = "github.com/user/project2" | |
# branch = "dev" | |
# source = "github.com/myfork/project2" | |
# | |
# [[override]] | |
# name = "github.com/x/y" | |
# version = "2.4.0" | |
# | |
# [prune] | |
# non-go = false | |
# go-tests = true | |
# unused-packages = true | |
[[constraint]] | |
branch = "master" | |
name = "github.com/rcrowley/go-metrics" | |
[prune] | |
go-tests = true | |
unused-packages = true | |
[[constraint]] | |
name = "github.com/prometheus/client_golang" | |
version = "0.8.0" | |
[[constraint]] | |
branch = "master" | |
name = "github.com/prometheus/common" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"expvar" | |
"flag" | |
"fmt" | |
"log" | |
"math/rand" | |
"net" | |
"net/http" | |
"net/http/pprof" | |
"os" | |
"strconv" | |
"strings" | |
"time" | |
"github.com/prometheus/client_golang/prometheus" | |
"github.com/prometheus/client_golang/prometheus/promhttp" | |
"github.com/prometheus/client_model/go" | |
"github.com/prometheus/common/expfmt" | |
"github.com/prometheus/common/model" | |
"github.com/rcrowley/go-metrics" | |
) | |
type responseWriter struct { | |
http.ResponseWriter | |
code int | |
} | |
func (w *responseWriter) WriteHeader(code int) { | |
w.code = code | |
w.ResponseWriter.WriteHeader(code) | |
} | |
func timeit(f func()) time.Duration { | |
ts := time.Now() | |
f() | |
return time.Now().Sub(ts) | |
} | |
func logHandler(logger *log.Logger, route string, h http.Handler) http.Handler { | |
// prometheus | |
reqprom := prometheus.NewCounter( | |
prometheus.CounterOpts{ | |
Name: "http_request", | |
Help: "http request details", | |
ConstLabels: map[string]string{"route": route}, | |
}, | |
) | |
resprom := prometheus.NewCounterVec( | |
prometheus.CounterOpts{ | |
Name: "http_response", | |
Help: "http response details", | |
ConstLabels: map[string]string{"route": route}, | |
}, | |
[]string{"code", "method", "url"}, | |
) | |
prometheus.MustRegister(reqprom, resprom) | |
// go-metrics | |
reqm := metrics.GetOrRegisterMeter("http.request.count", nil) | |
resm := metrics.GetOrRegisterMeter("http.response.count", nil) | |
t := metrics.GetOrRegisterTimer("http.response.time", nil) | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
// prometheus | |
reqprom.Add(1) | |
// go-metrics | |
reqm.Mark(1) | |
rw := &responseWriter{ | |
ResponseWriter: w, | |
code: http.StatusOK, // WriteHeader not called by default | |
} | |
dur := timeit(func() { | |
h.ServeHTTP(rw, r) | |
}) | |
logger.Println(r.URL, rw.code, dur) | |
// prometheus | |
resprom.WithLabelValues(strconv.Itoa(rw.code), r.Method, r.URL.Path).Add(1) | |
// go-metrics | |
t.Update(dur) | |
resm.Mark(1) | |
c := metrics.GetOrRegisterCounter(fmt.Sprintf("http.response.code.%d", rw.code), nil) | |
c.Inc(1) | |
}) | |
} | |
func handler(w http.ResponseWriter, r *http.Request) { | |
if r.URL.Path == "/" { | |
// work | |
time.Sleep(100*time.Millisecond + time.Duration(rand.Intn(1000)) * time.Millisecond) | |
fmt.Fprint(w, "OK") | |
return | |
} | |
p := strings.Trim(r.URL.Path, "/") | |
if i, err := strconv.Atoi(p); err == nil && i >= 200 && i < 600 { | |
http.Error(w, http.StatusText(i), i) | |
return | |
} | |
http.NotFound(w, r) | |
} | |
func main() { | |
var port = flag.Int("port", 1234, "port") | |
flag.Parse() | |
lis, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", *port)) | |
if err != nil { | |
panic(err) | |
} | |
logger := log.New(os.Stderr, "", log.Ldate|log.Lmicroseconds|log.Lshortfile) | |
// prometheus | |
var pmLogger log.Logger | |
pmLogger = *logger | |
pmLogger.SetPrefix("[prometheus] ") | |
go func() { | |
ticker := time.NewTicker(10 * time.Second) | |
g := prometheus.DefaultGatherer | |
var mfs []*io_prometheus_client.MetricFamily | |
var vec model.Vector | |
for range ticker.C { | |
if mfs, err = g.Gather(); err != nil { | |
pmLogger.Println("while gathering", err) | |
continue | |
} | |
for _, mf := range mfs { | |
pmLogger.Println(strings.ToLower((mf.Type).String()), *mf.Name) | |
if vec, err = expfmt.ExtractSamples(&expfmt.DecodeOptions{}, mf); err != nil { | |
pmLogger.Println("while extracting", err) | |
continue | |
} | |
for _, sample := range vec { | |
pmLogger.Println(" ", sample) | |
} | |
} | |
} | |
}() | |
// go-metrics | |
var gmLogger log.Logger | |
gmLogger = *logger | |
gmLogger.SetPrefix("[go-metrics] ") | |
go metrics.LogScaled(metrics.DefaultRegistry, 10*time.Second, time.Millisecond, &gmLogger) | |
url := fmt.Sprintf("http://%s", lis.Addr()) | |
logger.Printf("listening on %s", url ) | |
go func() { | |
ticker := time.NewTicker(2*time.Second) | |
for range ticker.C{ | |
rsp, _ := http.Get(url) | |
rsp.Body.Close() | |
} | |
}() | |
mux := http.NewServeMux() | |
reg := func(pattern string, handler http.Handler) { | |
mux.Handle(pattern, logHandler(logger, pattern, handler)) | |
} | |
reg("/debug/vars", expvar.Handler()) | |
reg("/debug/pprof/", http.HandlerFunc(pprof.Index)) | |
reg("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline)) | |
reg("/debug/pprof/profile", http.HandlerFunc(pprof.Profile)) | |
reg("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol)) | |
reg("/debug/pprof/trace", http.HandlerFunc(pprof.Trace)) | |
reg("/metrics", promhttp.Handler()) | |
reg("/", http.HandlerFunc(handler)) | |
server := &http.Server{ | |
Handler: mux, | |
} | |
log.Fatal(server.Serve(lis)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment