add debug http server to services
Currently, the debug http server in every service contains just the net/http/pprof handlers. This allows us to get CPU, blocking, and memory profiling remotely. Along the way, remove all the places we use http.DefaultServeMux (which includes use of http.Handle and http.HandlerFunc) and use a NewServeMux for each place. Fixes #457
This commit is contained in:
parent
4a40def0f4
commit
ef54dda46a
|
@ -44,6 +44,9 @@ type Config struct {
|
|||
// The maximum number of subjectAltNames in a single certificate
|
||||
MaxNames int
|
||||
CFSSL cfsslConfig.Config
|
||||
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
// KeyConfig should contain either a File path to a PEM-format private key,
|
||||
|
|
|
@ -148,6 +148,8 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.ActivityMonitor.DebugAddr)
|
||||
|
||||
ch, err := cmd.AmqpChannel(c)
|
||||
|
||||
cmd.FailOnError(err, "Could not connect to AMQP")
|
||||
|
|
|
@ -30,7 +30,10 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.CA.DebugAddr)
|
||||
|
||||
cadb, err := ca.NewCertificateAuthorityDatabaseImpl(c.CA.DBDriver, c.CA.DBConnect)
|
||||
|
||||
cmd.FailOnError(err, "Failed to create CA database")
|
||||
|
||||
if c.SQL.CreateTables {
|
||||
|
|
|
@ -31,6 +31,8 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.RA.DebugAddr)
|
||||
|
||||
rai := ra.NewRegistrationAuthorityImpl()
|
||||
rai.AuthzBase = c.Common.BaseURL + wfe.AuthzPath
|
||||
rai.MaxKeySize = c.Common.MaxKeySize
|
||||
|
|
|
@ -30,7 +30,10 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.SA.DebugAddr)
|
||||
|
||||
sai, err := sa.NewSQLStorageAuthority(c.SA.DBDriver, c.SA.DBConnect)
|
||||
|
||||
cmd.FailOnError(err, "Failed to create SA impl")
|
||||
sai.SetSQLDebug(c.SQL.SQLDebug)
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.VA.DebugAddr)
|
||||
|
||||
go cmd.ProfileCmd("VA", stats)
|
||||
|
||||
vai := va.NewValidationAuthorityImpl(c.CA.TestMode)
|
||||
|
|
|
@ -87,6 +87,8 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.WFE.DebugAddr)
|
||||
|
||||
wfe, err := wfe.NewWebFrontEndImpl()
|
||||
cmd.FailOnError(err, "Unable to create WFE")
|
||||
rac, sac, closeChan := setupWFE(c)
|
||||
|
@ -118,13 +120,13 @@ func main() {
|
|||
|
||||
// Set up paths
|
||||
wfe.BaseURL = c.Common.BaseURL
|
||||
wfe.HandlePaths()
|
||||
h := wfe.Handler()
|
||||
|
||||
auditlogger.Info(app.VersionString())
|
||||
|
||||
// Add HandlerTimer to output resp time + success/failure stats to statsd
|
||||
auditlogger.Info(fmt.Sprintf("Server running, listening on %s...\n", c.WFE.ListenAddress))
|
||||
err = http.ListenAndServe(c.WFE.ListenAddress, HandlerTimer(http.DefaultServeMux, stats))
|
||||
err = http.ListenAndServe(c.WFE.ListenAddress, HandlerTimer(h, stats))
|
||||
cmd.FailOnError(err, "Error starting HTTP server")
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,8 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer("localhost:8080")
|
||||
|
||||
// Run StatsD profiling
|
||||
go cmd.ProfileCmd("Monolith", stats)
|
||||
|
||||
|
@ -120,7 +122,7 @@ func main() {
|
|||
// Set up paths
|
||||
ra.AuthzBase = c.Common.BaseURL + wfe.AuthzPath
|
||||
wfei.BaseURL = c.Common.BaseURL
|
||||
wfei.HandlePaths()
|
||||
h := wfei.Handler()
|
||||
|
||||
ra.MaxKeySize = c.Common.MaxKeySize
|
||||
ca.MaxKeySize = c.Common.MaxKeySize
|
||||
|
@ -128,7 +130,7 @@ func main() {
|
|||
auditlogger.Info(app.VersionString())
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Server running, listening on %s...\n", c.WFE.ListenAddress)
|
||||
err = http.ListenAndServe(c.WFE.ListenAddress, HandlerTimer(http.DefaultServeMux, stats))
|
||||
err = http.ListenAndServe(c.WFE.ListenAddress, HandlerTimer(h, stats))
|
||||
cmd.FailOnError(err, "Error starting HTTP server")
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,8 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.OCSPResponder.DebugAddr)
|
||||
|
||||
go cmd.ProfileCmd("OCSP", stats)
|
||||
|
||||
auditlogger.Info(app.VersionString())
|
||||
|
@ -148,11 +150,12 @@ func main() {
|
|||
cmd.FailOnError(err, "Could not connect to OCSP database")
|
||||
|
||||
// Configure HTTP
|
||||
http.Handle(c.OCSPResponder.Path, cfocsp.Responder{Source: src})
|
||||
m := http.NewServeMux()
|
||||
m.Handle(c.OCSPResponder.Path, cfocsp.Responder{Source: src})
|
||||
|
||||
// Add HandlerTimer to output resp time + success/failure stats to statsd
|
||||
auditlogger.Info(fmt.Sprintf("Server running, listening on %s...\n", c.OCSPResponder.ListenAddress))
|
||||
err = http.ListenAndServe(c.OCSPResponder.ListenAddress, HandlerTimer(http.DefaultServeMux, stats))
|
||||
err = http.ListenAndServe(c.OCSPResponder.ListenAddress, HandlerTimer(m, stats))
|
||||
cmd.FailOnError(err, "Error starting HTTP server")
|
||||
}
|
||||
|
||||
|
|
|
@ -214,6 +214,8 @@ func main() {
|
|||
|
||||
blog.SetAuditLogger(auditlogger)
|
||||
|
||||
go cmd.DebugServer(c.OCSPUpdater.DebugAddr)
|
||||
|
||||
// Configure DB
|
||||
dbMap, err := sa.NewDbMap(c.OCSPUpdater.DBDriver, c.OCSPUpdater.DBConnect)
|
||||
cmd.FailOnError(err, "Could not connect to database")
|
||||
|
|
41
cmd/shell.go
41
cmd/shell.go
|
@ -29,6 +29,10 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
@ -49,6 +53,11 @@ import (
|
|||
//
|
||||
// Note: NO DEFAULTS are provided.
|
||||
type Config struct {
|
||||
ActivityMonitor struct {
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
// General
|
||||
AMQP struct {
|
||||
Server string
|
||||
|
@ -63,19 +72,33 @@ type Config struct {
|
|||
WFE struct {
|
||||
BaseURL string
|
||||
ListenAddress string
|
||||
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
CA ca.Config
|
||||
|
||||
RA struct {
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
SA struct {
|
||||
DBDriver string
|
||||
DBConnect string
|
||||
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
VA struct {
|
||||
DNSResolver string
|
||||
DNSTimeout string
|
||||
UserAgent string
|
||||
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
SQL struct {
|
||||
|
@ -111,6 +134,9 @@ type Config struct {
|
|||
DBConnect string
|
||||
Path string
|
||||
ListenAddress string
|
||||
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
OCSPUpdater struct {
|
||||
|
@ -118,6 +144,9 @@ type Config struct {
|
|||
DBConnect string
|
||||
MinTimeToExpiry string
|
||||
ResponseLimit int
|
||||
|
||||
// DebugAddr is the address to run the /debug handlers on.
|
||||
DebugAddr string
|
||||
}
|
||||
|
||||
Common struct {
|
||||
|
@ -335,3 +364,15 @@ func LoadCert(path string) (cert []byte, err error) {
|
|||
cert = block.Bytes
|
||||
return
|
||||
}
|
||||
|
||||
func DebugServer(addr string) {
|
||||
if addr == "" {
|
||||
log.Fatalf("unable to boot debug server because no address was given for it. Set debugAddr.")
|
||||
}
|
||||
ln, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to boot debug server on %#v", addr)
|
||||
}
|
||||
log.Printf("booting debug server at %#v", addr)
|
||||
log.Println(http.Serve(ln, nil))
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
},
|
||||
|
||||
"wfe": {
|
||||
"listenAddress": "127.0.0.1:4000"
|
||||
"listenAddress": "127.0.0.1:4000",
|
||||
"debugAddr": "localhost:8000"
|
||||
},
|
||||
|
||||
"ca": {
|
||||
|
@ -44,6 +45,7 @@
|
|||
"profile": "ee",
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:",
|
||||
"debugAddr": "localhost:8001",
|
||||
"testMode": true,
|
||||
"_comment": "This should only be present in testMode. In prod use an HSM.",
|
||||
"Key": {
|
||||
|
@ -103,15 +105,21 @@
|
|||
}
|
||||
},
|
||||
|
||||
"ra": {
|
||||
"debugAddr": "localhost:8002"
|
||||
},
|
||||
|
||||
"sa": {
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:"
|
||||
"dbConnect": ":memory:",
|
||||
"debugAddr": "localhost:8003"
|
||||
},
|
||||
|
||||
"va": {
|
||||
"dnsResolver": "8.8.8.8:53",
|
||||
"dnsTimeout": "10s",
|
||||
"userAgent": "boulder"
|
||||
"userAgent": "boulder",
|
||||
"debugAddr": "localhost:8004"
|
||||
},
|
||||
|
||||
"sql": {
|
||||
|
@ -128,13 +136,15 @@
|
|||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:",
|
||||
"path": "/",
|
||||
"listenAddress": "localhost:4001"
|
||||
"listenAddress": "localhost:4001",
|
||||
"debugAddr": "localhost:8005"
|
||||
},
|
||||
|
||||
"ocspUpdater": {
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:",
|
||||
"minTimeToExpiry": "72h"
|
||||
"minTimeToExpiry": "72h",
|
||||
"debugAddr": "localhost:8006"
|
||||
},
|
||||
|
||||
"mail": {
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
},
|
||||
|
||||
"wfe": {
|
||||
"listenAddress": "127.0.0.1:4000"
|
||||
"listenAddress": "127.0.0.1:4000",
|
||||
"debugAddr": "localhost:8000"
|
||||
},
|
||||
|
||||
"ca": {
|
||||
|
@ -39,6 +40,7 @@
|
|||
"profile": "ee",
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:",
|
||||
"debugAddr": "localhost:8001",
|
||||
"testMode": true,
|
||||
"_comment": "This should only be present in testMode. In prod use an HSM.",
|
||||
"expiry": "2160h",
|
||||
|
@ -94,9 +96,14 @@
|
|||
}
|
||||
},
|
||||
|
||||
"ra": {
|
||||
"debugAddr": "localhost:8002"
|
||||
},
|
||||
|
||||
"sa": {
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:"
|
||||
"dbConnect": ":memory:",
|
||||
"debugAddr": "localhost:8003"
|
||||
},
|
||||
|
||||
"sql": {
|
||||
|
@ -112,6 +119,7 @@
|
|||
"ocspResponder": {
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:",
|
||||
"debugAddr": "localhost:8004",
|
||||
"path": "/",
|
||||
"listenAddress": "localhost:4001"
|
||||
},
|
||||
|
@ -119,6 +127,7 @@
|
|||
"ocspUpdater": {
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:",
|
||||
"debugAddr": "localhost:8005",
|
||||
"minTimeToExpiry": "72h"
|
||||
},
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
},
|
||||
|
||||
"wfe": {
|
||||
"listenAddress": "127.0.0.1:4300"
|
||||
"listenAddress": "127.0.0.1:4300",
|
||||
"debugAddr": "localhost:8000"
|
||||
},
|
||||
|
||||
"ca": {
|
||||
|
@ -39,6 +40,7 @@
|
|||
"profile": "ee",
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:",
|
||||
"debugAddr": "localhost:8001",
|
||||
"testMode": true,
|
||||
"_comment": "This should only be present in testMode. In prod use an HSM.",
|
||||
"Key": {
|
||||
|
@ -98,15 +100,21 @@
|
|||
}
|
||||
},
|
||||
|
||||
"ra": {
|
||||
"debugAddr": "localhost:8002"
|
||||
},
|
||||
|
||||
"sa": {
|
||||
"dbDriver": "sqlite3",
|
||||
"dbConnect": ":memory:"
|
||||
"dbConnect": ":memory:",
|
||||
"debugAddr": "localhost:8003"
|
||||
},
|
||||
|
||||
"va": {
|
||||
"dnsResolver": "8.8.8.8:53",
|
||||
"dnsTimeout": "10s",
|
||||
"userAgent": "boulder"
|
||||
"userAgent": "boulder",
|
||||
"debugAddr": "localhost:8004"
|
||||
},
|
||||
|
||||
"sql": {
|
||||
|
|
|
@ -56,10 +56,9 @@ const pathWrongToken = "wrongtoken"
|
|||
const path404 = "404"
|
||||
|
||||
func simpleSrv(t *testing.T, token string, stopChan, waitChan chan bool, enableTLS bool) {
|
||||
// Reset any existing handlers
|
||||
http.DefaultServeMux = http.NewServeMux()
|
||||
m := http.NewServeMux()
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasSuffix(r.URL.Path, path404) {
|
||||
t.Logf("SIMPLESRV: Got a 404 req\n")
|
||||
http.NotFound(w, r)
|
||||
|
@ -78,7 +77,7 @@ func simpleSrv(t *testing.T, token string, stopChan, waitChan chan bool, enableT
|
|||
}
|
||||
})
|
||||
|
||||
server := &http.Server{Addr: "localhost:5001"}
|
||||
server := &http.Server{Addr: "localhost:5001", Handler: m}
|
||||
conn, err := net.Listen("tcp", server.Addr)
|
||||
if err != nil {
|
||||
waitChan <- true
|
||||
|
|
|
@ -123,7 +123,7 @@ func NewWebFrontEndImpl() (WebFrontEndImpl, error) {
|
|||
|
||||
// HandlePaths configures the HTTP engine to use various functions
|
||||
// as methods for various ACME-specified paths.
|
||||
func (wfe *WebFrontEndImpl) HandlePaths() {
|
||||
func (wfe *WebFrontEndImpl) Handler() http.Handler {
|
||||
wfe.NewReg = wfe.BaseURL + NewRegPath
|
||||
wfe.RegBase = wfe.BaseURL + RegPath
|
||||
wfe.NewAuthz = wfe.BaseURL + NewAuthzPath
|
||||
|
@ -131,17 +131,19 @@ func (wfe *WebFrontEndImpl) HandlePaths() {
|
|||
wfe.NewCert = wfe.BaseURL + NewCertPath
|
||||
wfe.CertBase = wfe.BaseURL + CertPath
|
||||
|
||||
http.HandleFunc("/", wfe.Index)
|
||||
http.HandleFunc(NewRegPath, wfe.NewRegistration)
|
||||
http.HandleFunc(NewAuthzPath, wfe.NewAuthorization)
|
||||
http.HandleFunc(NewCertPath, wfe.NewCertificate)
|
||||
http.HandleFunc(RegPath, wfe.Registration)
|
||||
http.HandleFunc(AuthzPath, wfe.Authorization)
|
||||
http.HandleFunc(CertPath, wfe.Certificate)
|
||||
http.HandleFunc(RevokeCertPath, wfe.RevokeCertificate)
|
||||
http.HandleFunc(TermsPath, wfe.Terms)
|
||||
http.HandleFunc(IssuerPath, wfe.Issuer)
|
||||
http.HandleFunc(BuildIDPath, wfe.BuildID)
|
||||
m := http.NewServeMux()
|
||||
m.HandleFunc("/", wfe.Index)
|
||||
m.HandleFunc(NewRegPath, wfe.NewRegistration)
|
||||
m.HandleFunc(NewAuthzPath, wfe.NewAuthorization)
|
||||
m.HandleFunc(NewCertPath, wfe.NewCertificate)
|
||||
m.HandleFunc(RegPath, wfe.Registration)
|
||||
m.HandleFunc(AuthzPath, wfe.Authorization)
|
||||
m.HandleFunc(CertPath, wfe.Certificate)
|
||||
m.HandleFunc(RevokeCertPath, wfe.RevokeCertificate)
|
||||
m.HandleFunc(TermsPath, wfe.Terms)
|
||||
m.HandleFunc(IssuerPath, wfe.Issuer)
|
||||
m.HandleFunc(BuildIDPath, wfe.BuildID)
|
||||
return m
|
||||
}
|
||||
|
||||
// Method implementations
|
||||
|
|
Loading…
Reference in New Issue