Skip to content

Commit

Permalink
Replace logrus with zerolog
Browse files Browse the repository at this point in the history
Setup initilization part to create logger instance.
Update Proxy logger to use zerologer.
Add HTTP middleware to log all HTTP requests.
  • Loading branch information
miry committed Aug 27, 2022
1 parent d10a921 commit f7da982
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 119 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

* Support go 1.18, 1.19. (@miry)
* `toxiproxy.NewProxy` now accepts `name`, `listen addr` and `upstream addr`. (#418, @miry)
* Replace logrus with zerolog. (#413, @miry)
* Log HTTP requests to API server. (#413, @miry)

# [2.4.0] - 2022-03-07

Expand Down
131 changes: 71 additions & 60 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,65 +3,52 @@ package toxiproxy
import (
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"os"
"strings"

"github.com/Shopify/toxiproxy/v2/toxics"
"github.com/gorilla/mux"
"github.com/rs/zerolog"
"github.com/sirupsen/logrus"

"github.com/Shopify/toxiproxy/v2/toxics"
)

type ApiServer struct {
Collection *ProxyCollection
Metrics *metricsContainer
Logger *zerolog.Logger
}

func NewServer(m *metricsContainer) *ApiServer {
func NewServer(m *metricsContainer, logger zerolog.Logger) *ApiServer {
return &ApiServer{
Collection: NewProxyCollection(),
Metrics: m,
Logger: &logger,
}
}

func (server *ApiServer) PopulateConfig(filename string) {
file, err := os.Open(filename)
logger := server.Logger
if err != nil {
logrus.WithFields(logrus.Fields{
"config": filename,
"error": err,
}).Error("Error reading config file")
logger.Err(err).Str("config", filename).Msg("Error reading config file")
return
}

proxies, err := server.Collection.PopulateJson(server, file)
if err != nil {
logrus.WithFields(logrus.Fields{
"config": filename,
"error": err,
}).Error("Failed to populate proxies from file")
logger.Err(err).Msg("Failed to populate proxies from file")
} else {
logrus.WithFields(logrus.Fields{
"config": filename,
"proxies": len(proxies),
}).Info("Populated proxies from file")
logger.Info().Int("proxies", len(proxies)).Msg("Populated proxies from file")
}
}

func StopBrowsersMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.UserAgent(), "Mozilla/") {
http.Error(w, "User agent not allowed", 403)
} else {
h.ServeHTTP(w, r)
}
})
}

func (server *ApiServer) Listen(host string, port string) {
r := mux.NewRouter()
r.Use(server.loggingMiddleware)

r.HandleFunc("/reset", server.ResetState).Methods("POST")
r.HandleFunc("/proxies", server.ProxyIndex).Methods("GET")
r.HandleFunc("/proxies", server.ProxyCreate).Methods("POST")
Expand All @@ -83,18 +70,42 @@ func (server *ApiServer) Listen(host string, port string) {

http.Handle("/", StopBrowsersMiddleware(r))

logrus.WithFields(logrus.Fields{
"host": host,
"port": port,
"version": Version,
}).Infof("Starting HTTP server on endpoint %s:%s", host, port)
server.Logger.
Info().
Str("host", host).
Str("port", port).
Str("version", Version).
Msgf("Starting HTTP server on endpoint %s:%s", host, port)

err := http.ListenAndServe(net.JoinHostPort(host, port), nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
server.Logger.Fatal().Err(err).Msg("ListenAndServe finished with error")
}
}

func StopBrowsersMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.UserAgent(), "Mozilla/") {
http.Error(w, "User agent not allowed", 403)
} else {
h.ServeHTTP(w, r)
}
})
}

func (server *ApiServer) loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
server.
Logger.
Debug().
Str("client", r.RemoteAddr).
Str("method", r.Method).
Str("uri", r.RequestURI).
Msg("")
next.ServeHTTP(w, r)
})
}

func (server *ApiServer) ProxyIndex(response http.ResponseWriter, request *http.Request) {
proxies := server.Collection.Proxies()
marshalData := make(map[string]interface{}, len(proxies))
Expand All @@ -104,7 +115,7 @@ func (server *ApiServer) ProxyIndex(response http.ResponseWriter, request *http.
}

data, err := json.Marshal(marshalData)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -120,7 +131,7 @@ func (server *ApiServer) ResetState(response http.ResponseWriter, request *http.

for _, proxy := range proxies {
err := proxy.Start()
if err != ErrProxyAlreadyStarted && apiError(response, err) {
if err != ErrProxyAlreadyStarted && server.apiError(response, err) {
return
}

Expand All @@ -138,28 +149,28 @@ func (server *ApiServer) ProxyCreate(response http.ResponseWriter, request *http
// Default fields to enable the proxy right away
input := Proxy{Enabled: true}
err := json.NewDecoder(request.Body).Decode(&input)
if apiError(response, joinError(err, ErrBadRequestBody)) {
if server.apiError(response, joinError(err, ErrBadRequestBody)) {
return
}

if len(input.Name) < 1 {
apiError(response, joinError(fmt.Errorf("name"), ErrMissingField))
server.apiError(response, joinError(fmt.Errorf("name"), ErrMissingField))
return
}
if len(input.Upstream) < 1 {
apiError(response, joinError(fmt.Errorf("upstream"), ErrMissingField))
server.apiError(response, joinError(fmt.Errorf("upstream"), ErrMissingField))
return
}

proxy := NewProxy(server, input.Name, input.Listen, input.Upstream)

err = server.Collection.Add(proxy, input.Enabled)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

data, err := json.Marshal(proxyWithToxics(proxy))
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -184,7 +195,7 @@ func (server *ApiServer) Populate(response http.ResponseWriter, request *http.Re
*ApiError `json:",omitempty"`
Proxies []proxyToxics `json:"proxies"`
}{apiErr, proxiesWithToxics(proxies)})
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -205,12 +216,12 @@ func (server *ApiServer) ProxyShow(response http.ResponseWriter, request *http.R
vars := mux.Vars(request)

proxy, err := server.Collection.Get(vars["proxy"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

data, err := json.Marshal(proxyWithToxics(proxy))
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -225,24 +236,24 @@ func (server *ApiServer) ProxyUpdate(response http.ResponseWriter, request *http
vars := mux.Vars(request)

proxy, err := server.Collection.Get(vars["proxy"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

// Default fields are the same as existing proxy
input := Proxy{Listen: proxy.Listen, Upstream: proxy.Upstream, Enabled: proxy.Enabled}
err = json.NewDecoder(request.Body).Decode(&input)
if apiError(response, joinError(err, ErrBadRequestBody)) {
if server.apiError(response, joinError(err, ErrBadRequestBody)) {
return
}

err = proxy.Update(&input)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

data, err := json.Marshal(proxyWithToxics(proxy))
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -257,7 +268,7 @@ func (server *ApiServer) ProxyDelete(response http.ResponseWriter, request *http
vars := mux.Vars(request)

err := server.Collection.Remove(vars["proxy"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -272,13 +283,13 @@ func (server *ApiServer) ToxicIndex(response http.ResponseWriter, request *http.
vars := mux.Vars(request)

proxy, err := server.Collection.Get(vars["proxy"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

toxics := proxy.Toxics.GetToxicArray()
data, err := json.Marshal(toxics)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -293,17 +304,17 @@ func (server *ApiServer) ToxicCreate(response http.ResponseWriter, request *http
vars := mux.Vars(request)

proxy, err := server.Collection.Get(vars["proxy"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

toxic, err := proxy.Toxics.AddToxicJson(request.Body)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

data, err := json.Marshal(toxic)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -318,18 +329,18 @@ func (server *ApiServer) ToxicShow(response http.ResponseWriter, request *http.R
vars := mux.Vars(request)

proxy, err := server.Collection.Get(vars["proxy"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

toxic := proxy.Toxics.GetToxic(vars["toxic"])
if toxic == nil {
apiError(response, ErrToxicNotFound)
server.apiError(response, ErrToxicNotFound)
return
}

data, err := json.Marshal(toxic)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -344,17 +355,17 @@ func (server *ApiServer) ToxicUpdate(response http.ResponseWriter, request *http
vars := mux.Vars(request)

proxy, err := server.Collection.Get(vars["proxy"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

toxic, err := proxy.Toxics.UpdateToxicJson(vars["toxic"], request.Body)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

data, err := json.Marshal(toxic)
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand All @@ -369,12 +380,12 @@ func (server *ApiServer) ToxicDelete(response http.ResponseWriter, request *http
vars := mux.Vars(request)

proxy, err := server.Collection.Get(vars["proxy"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

err = proxy.Toxics.RemoveToxic(vars["toxic"])
if apiError(response, err) {
if server.apiError(response, err) {
return
}

Expand Down Expand Up @@ -427,7 +438,7 @@ var (
ErrToxicNotFound = newError("toxic not found", http.StatusNotFound)
)

func apiError(resp http.ResponseWriter, err error) bool {
func (server *ApiServer) apiError(resp http.ResponseWriter, err error) bool {
obj, ok := err.(*ApiError)
if !ok && err != nil {
logrus.Warn("Error did not include status code: ", err)
Expand Down
9 changes: 7 additions & 2 deletions api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"testing"
"time"

"github.com/prometheus/client_golang/prometheus"
"github.com/rs/zerolog"

"github.com/Shopify/toxiproxy/v2"
tclient "github.com/Shopify/toxiproxy/v2/client"
"github.com/prometheus/client_golang/prometheus"
)

var testServer *toxiproxy.ApiServer
Expand All @@ -20,7 +22,10 @@ func WithServer(t *testing.T, f func(string)) {
// Make sure only one server is running at a time. Apparently there's no clean
// way to shut it down between each test run.
if testServer == nil {
testServer = toxiproxy.NewServer(toxiproxy.NewMetricsContainer(prometheus.NewRegistry()))
testServer = toxiproxy.NewServer(
toxiproxy.NewMetricsContainer(prometheus.NewRegistry()),
zerolog.Nop(),
)

go testServer.Listen("localhost", "8475")

Expand Down
Loading

0 comments on commit f7da982

Please sign in to comment.