Add a facebookgo/stats client that sends StatsD metrics for facebookgo/httpdown

This commit is contained in:
Roland Shoemaker 2015-09-26 18:01:03 -07:00
parent 1de62e6697
commit 081b81d170
3 changed files with 55 additions and 25 deletions

View File

@ -126,14 +126,14 @@ func main() {
auditlogger.Info(fmt.Sprintf("Server running, listening on %s...\n", c.WFE.ListenAddress))
srv := &http.Server{
Addr: c.WFE.ListenAddress,
ConnState: httpMonitor.ConnectionMonitor,
Handler: httpMonitor.Handle(),
Addr: c.WFE.ListenAddress,
Handler: httpMonitor.Handle(),
}
hd := &httpdown.HTTP{
StopTimeout: wfe.ShutdownStopTimeout,
KillTimeout: wfe.ShutdownKillTimeout,
Stats: metrics.NewFBAdapter(stats, "WFE"),
}
err = httpdown.ListenAndServe(srv, hd)
cmd.FailOnError(err, "Error starting HTTP server")

View File

@ -174,14 +174,14 @@ func main() {
httpMonitor := metrics.NewHTTPMonitor(stats, m, "OCSP")
srv := &http.Server{
Addr: c.OCSPResponder.ListenAddress,
ConnState: httpMonitor.ConnectionMonitor,
Handler: httpMonitor.Handle(),
Addr: c.OCSPResponder.ListenAddress,
Handler: httpMonitor.Handle(),
}
hd := &httpdown.HTTP{
StopTimeout: stopTimeout,
KillTimeout: killTimeout,
Stats: metrics.NewFBAdapter(stats, "OCSP"),
}
err = httpdown.ListenAndServe(srv, hd)
cmd.FailOnError(err, "Error starting HTTP server")

View File

@ -7,7 +7,6 @@ package metrics
import (
"fmt"
"net"
"net/http"
"strings"
"sync/atomic"
@ -22,7 +21,6 @@ type HTTPMonitor struct {
statsPrefix string
handler http.Handler
connectionsInFlight int64
openConnections int64
}
// NewHTTPMonitor returns a new initialized HTTPMonitor
@ -32,26 +30,9 @@ func NewHTTPMonitor(stats statsd.Statter, handler http.Handler, prefix string) H
handler: handler,
statsPrefix: prefix,
connectionsInFlight: 0,
openConnections: 0,
}
}
// ConnectionMonitor provides states on open connection state
func (h *HTTPMonitor) ConnectionMonitor(_ net.Conn, state http.ConnState) {
var open int64
switch state {
case http.StateNew:
open = atomic.AddInt64(&h.openConnections, 1)
case http.StateHijacked:
fallthrough
case http.StateClosed:
open = atomic.AddInt64(&h.openConnections, -1)
default:
return
}
h.stats.Gauge(fmt.Sprintf("%s.HTTP.OpenConnections", h.statsPrefix), open, 1.0)
}
// Handle wraps handlers and records various metrics about requests to these handlers
// and sends them to StatsD
func (h *HTTPMonitor) Handle() http.Handler {
@ -85,3 +66,52 @@ func (h *HTTPMonitor) watchAndServe(w http.ResponseWriter, r *http.Request) {
}
h.stats.TimingDuration(fmt.Sprintf("%s.HTTP.ResponseTime.%s", h.statsPrefix, endpoint), cClosed, 1.0)
}
// FBAdapter provides a facebookgo/stats client interface that sends metrics via
// a StatsD client
type FBAdapter struct {
stats statsd.Statter
prefix string
}
// NewFBAdapter returns a new adapter
func NewFBAdapter(stats statsd.Statter, prefix string) FBAdapter {
return FBAdapter{stats: stats, prefix: prefix}
}
// BumpAvg is essentially statsd.Statter.Gauge
func (fba FBAdapter) BumpAvg(key string, val float64) {
fba.stats.Gauge(fmt.Sprintf("%s.%s", fba.prefix, key), int64(val), 1.0)
}
// BumpSum is essentially statsd.Statter.Inc (httpdown only ever uses positive
// deltas)
func (fba FBAdapter) BumpSum(key string, val float64) {
fba.stats.Inc(fmt.Sprintf("%s.%s", fba.prefix, key), int64(val), 1.0)
}
type btHolder struct {
key string
stats statsd.Statter
started time.Time
}
func (bth btHolder) End() {
bth.stats.TimingDuration(bth.key, time.Since(bth.started), 1.0)
}
// BumpTime is essentially a (much better) statsd.Statter.TimingDuration
func (fba FBAdapter) BumpTime(key string) interface {
End()
} {
return btHolder{
key: fmt.Sprintf("%s.%s", fba.prefix, key),
started: time.Now(),
stats: fba.stats,
}
}
// BumpHistogram isn't used by facebookgo/httpdown
func (fba FBAdapter) BumpHistogram(_ string, _ float64) {
return
}