Skip to content

Commit

Permalink
Not crazy about the design, but this works. Adding pprof's handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
Dynom committed Jul 7, 2018
1 parent 1252bda commit 8daee0b
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 9 deletions.
10 changes: 10 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
client:
# The maximum amount of references the client can send to test against (@todo)
referencesMax: 100
# The maximum length (in bytes) of the "input" field, to accept to the finder.
inputLengthMax: 50

CORS:
Expand All @@ -9,8 +11,16 @@ CORS:
# - https://api.example.com

server:
# The interface and port to listen on, "0.0.0.0" means all interfaces
listenOn: "0.0.0.0:1337"
log:
# The minimum logging level
level: "info"
profiler:
enable: false
prefix: "debug"

# The list of references
references:
domains:
- gmail.com
Expand Down
37 changes: 31 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"net/http"
"os"

"github.com/Dynom/TySug/server"
"github.com/Dynom/TySug/server/service"
Expand All @@ -11,6 +10,8 @@ import (
"fmt"
"io/ioutil"

"os"

"gopkg.in/yaml.v2"
)

Expand All @@ -26,6 +27,13 @@ type Config struct {
} `yaml:"CORS"`
Server struct {
ListenOn string `yaml:"listenOn"`
Log struct {
Level string `yaml:"level"`
} `yaml:"log"`
Profiler struct {
Enable bool `yaml:"enable"`
Prefix string `yaml:"prefix"`
} `yaml:"profiler"`
} `yaml:"server"`
}

Expand All @@ -42,9 +50,18 @@ func main() {

logger := logrus.New()
logger.Formatter = &logrus.JSONFormatter{}
logger.Info("Starting up...")
logger.Level = logrus.DebugLevel
logger.Out = os.Stdout
logger.Level, err = logrus.ParseLevel(config.Server.Log.Level)

if err != nil {
panic(err)
}

logger.WithFields(logrus.Fields{
"client": config.Client,
"server": config.Server,
"CORS": config.CORS,
}).Info("Starting up...")

sr := server.NewServiceRegistry()
for label, references := range config.References {
Expand All @@ -58,13 +75,21 @@ func main() {
sr.Register(label, svc)
}

s := server.NewHTTP(
sr,
http.NewServeMux(),
options := []server.Option{
server.WithLogger(logger),
server.WithCORS(config.CORS.AllowedOrigins),
server.WithInputLimitValidator(config.Client.InputLengthMax),
server.WithGzipHandler(),
}

if config.Server.Profiler.Enable {
options = append(options, server.WithPProf(config.Server.Profiler.Prefix))
}

s := server.NewHTTP(
sr,
*http.NewServeMux(),
options...,
)

err = s.ListenOnAndServe(config.Server.ListenOn)
Expand Down
36 changes: 33 additions & 3 deletions server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (

"errors"

"net/http/pprof"

"github.com/sirupsen/logrus"
"gopkg.in/tomb.v2"
)
Expand Down Expand Up @@ -40,6 +42,11 @@ type tySugResponse struct {
Score float64 `json:"score"`
}

type pprofConfig struct {
Enable bool
Prefix string
}

// Validator is a type to validate a client request, returning a nil errors means all went well.
type Validator func(TSRequest tySugRequest) error

Expand All @@ -48,6 +55,7 @@ type TySugServer struct {
server *http.Server
handlers []func(h http.Handler) http.Handler
validators []Validator
profConfig pprofConfig

Logger *logrus.Logger
}
Expand All @@ -60,7 +68,7 @@ func (tss *TySugServer) ListenOnAndServe(addr string) error {
}

// NewHTTP constructs a new TySugServer
func NewHTTP(sr ServiceRegistry, mux *http.ServeMux, options ...Option) TySugServer {
func NewHTTP(sr ServiceRegistry, mux http.ServeMux, options ...Option) TySugServer {
tySug := TySugServer{
Logger: logrus.StandardLogger(),
}
Expand All @@ -69,7 +77,7 @@ func NewHTTP(sr ServiceRegistry, mux *http.ServeMux, options ...Option) TySugSer
opt(&tySug)
}

var handler http.Handler = defaultHeaderHandler(createRequestIDHandler(mux))
var handler http.Handler = defaultHeaderHandler(createRequestIDHandler(&mux))
for _, h := range tySug.handlers {
handler = h(handler)
}
Expand Down Expand Up @@ -102,15 +110,37 @@ func NewHTTP(sr ServiceRegistry, mux *http.ServeMux, options ...Option) TySugSer
tySug.server = &http.Server{
ReadHeaderTimeout: 2 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second, // Is overridden, when the profiler is enabled.
IdleTimeout: 60 * time.Second,
MaxHeaderBytes: 1 << 19, // 512 kb
Handler: handler,
}

if tySug.profConfig.Enable {
configureProfiler(tySug, &mux, tySug.profConfig)
}

return tySug
}

func configureProfiler(s TySugServer, mux *http.ServeMux, c pprofConfig) {
var prefix string
if s.profConfig.Prefix != "" {
prefix = s.profConfig.Prefix
} else {
prefix = "debug"
}

mux.HandleFunc(`/`+prefix+`/pprof/`, pprof.Index)
mux.HandleFunc(`/`+prefix+`/pprof/cmdline`, pprof.Cmdline)
mux.HandleFunc(`/`+prefix+`/pprof/profile`, pprof.Profile)
mux.HandleFunc(`/`+prefix+`/pprof/symbol`, pprof.Symbol)
mux.HandleFunc(`/`+prefix+`/pprof/trace`, pprof.Trace)

// The profiler needs at least 30 seconds to use /prefix/pprof/profile
s.server.WriteTimeout = 31 * time.Second
}

func createRequestHandler(logger *logrus.Logger, svc Service, validators []Validator) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
t, ctx := tomb.WithContext(r.Context())
Expand Down
8 changes: 8 additions & 0 deletions server/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,11 @@ func WithGzipHandler() Option {
server.handlers = append(server.handlers, gziphandler.GzipHandler)
}
}

// WithPProf enables pprof
func WithPProf(prefix string) Option {
return func(server *TySugServer) {
server.profConfig.Enable = true
server.profConfig.Prefix = prefix
}
}

0 comments on commit 8daee0b

Please sign in to comment.