Better debug logging + unit tests

This commit is contained in:
Manu Mtz-Almeida 2015-05-09 03:34:43 +02:00
parent c391520654
commit b690611c38
5 changed files with 99 additions and 16 deletions

View File

@ -15,7 +15,7 @@ func IsDebugging() bool {
return ginMode == debugCode return ginMode == debugCode
} }
func debugRoute(httpMethod, absolutePath string, handlers HandlersChain) { func debugPrintRoute(httpMethod, absolutePath string, handlers HandlersChain) {
if IsDebugging() { if IsDebugging() {
nuHandlers := len(handlers) nuHandlers := len(handlers)
handlerName := nameOfFunction(handlers[nuHandlers-1]) handlerName := nameOfFunction(handlers[nuHandlers-1])
@ -28,3 +28,13 @@ func debugPrint(format string, values ...interface{}) {
debugLogger.Printf(format, values...) debugLogger.Printf(format, values...)
} }
} }
func debugPrintWARNING() {
debugPrint("[WARNING] Running in DEBUG mode! Disable it before going production\n")
}
func debugPrintError(err error) {
if err != nil {
debugPrint("[ERROR] %v\n", err)
}
}

View File

@ -5,11 +5,17 @@
package gin package gin
import ( import (
"bytes"
"errors"
"io"
"log"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
var cachedDebugLogger *log.Logger = nil
// TODO // TODO
// func debugRoute(httpMethod, absolutePath string, handlers HandlersChain) { // func debugRoute(httpMethod, absolutePath string, handlers HandlersChain) {
// func debugPrint(format string, values ...interface{}) { // func debugPrint(format string, values ...interface{}) {
@ -22,3 +28,52 @@ func TestIsDebugging(t *testing.T) {
SetMode(TestMode) SetMode(TestMode)
assert.False(t, IsDebugging()) assert.False(t, IsDebugging())
} }
func TestDebugPrint(t *testing.T) {
var w bytes.Buffer
setup(&w)
defer teardown()
SetMode(ReleaseMode)
debugPrint("DEBUG this!")
SetMode(TestMode)
debugPrint("DEBUG this!")
assert.Empty(t, w.String())
SetMode(DebugMode)
debugPrint("these are %d %s\n", 2, "error messages")
assert.Equal(t, w.String(), "[GIN-debug] these are 2 error messages\n")
}
func TestDebugPrintError(t *testing.T) {
var w bytes.Buffer
setup(&w)
defer teardown()
SetMode(DebugMode)
debugPrintError(nil)
assert.Empty(t, w.String())
debugPrintError(errors.New("this is an error"))
assert.Equal(t, w.String(), "[GIN-debug] [ERROR] this is an error\n")
}
func setup(w io.Writer) {
SetMode(DebugMode)
if cachedDebugLogger == nil {
cachedDebugLogger = debugLogger
debugLogger = log.New(w, debugLogger.Prefix(), 0)
} else {
panic("setup failed")
}
}
func teardown() {
SetMode(TestMode)
if cachedDebugLogger != nil {
debugLogger = cachedDebugLogger
cachedDebugLogger = nil
} else {
panic("teardown failed")
}
}

View File

@ -10,14 +10,17 @@ import (
) )
const ( const (
ErrorTypeInternal = 1 << iota ErrorTypePrivate = 1 << iota
ErrorTypeExternal = 1 << iota ErrorTypePublic = 1 << iota
ErrorTypeAll = 0xffffffff )
const (
ErrorMaskAny = 0xffffffff
) )
// Used internally to collect errors that occurred during an http request. // Used internally to collect errors that occurred during an http request.
type errorMsg struct { type errorMsg struct {
Err string `json:"error"` Error error `json:"error"`
Type int `json:"-"` Type int `json:"-"`
Meta interface{} `json:"meta"` Meta interface{} `json:"meta"`
} }
@ -37,14 +40,24 @@ func (a errorMsgs) ByType(typ int) errorMsgs {
return result return result
} }
func (a errorMsgs) Errors() []string {
if len(a) == 0 {
return []string{}
}
errors := make([]string, len(a))
for i, err := range a {
errors[i] = err.Error.Error()
}
return errors
}
func (a errorMsgs) String() string { func (a errorMsgs) String() string {
if len(a) == 0 { if len(a) == 0 {
return "" return ""
} }
var buffer bytes.Buffer var buffer bytes.Buffer
for i, msg := range a { for i, msg := range a {
text := fmt.Sprintf("Error #%02d: %s\n Meta: %v\n", (i + 1), msg.Err, msg.Meta) fmt.Fprintf(&buffer, "Error #%02d: %s\n Meta: %v\n", (i + 1), msg.Error, msg.Meta)
buffer.WriteString(text)
} }
return buffer.String() return buffer.String()
} }

17
gin.go
View File

@ -62,6 +62,7 @@ type (
// Returns a new blank Engine instance without any middleware attached. // Returns a new blank Engine instance without any middleware attached.
// The most basic configuration // The most basic configuration
func New() *Engine { func New() *Engine {
debugPrintWARNING()
engine := &Engine{ engine := &Engine{
RouterGroup: RouterGroup{ RouterGroup: RouterGroup{
Handlers: nil, Handlers: nil,
@ -156,16 +157,20 @@ func (engine *Engine) handle(method, path string, handlers HandlersChain) {
root.addRoute(path, handlers) root.addRoute(path, handlers)
} }
func (engine *Engine) Run(addr string) error { func (engine *Engine) Run(addr string) (err error) {
debugPrint("[WARNING] Running in DEBUG mode! Disable it before going production")
debugPrint("Listening and serving HTTP on %s\n", addr) debugPrint("Listening and serving HTTP on %s\n", addr)
return http.ListenAndServe(addr, engine) defer debugPrintError(err)
err = http.ListenAndServe(addr, engine)
return
} }
func (engine *Engine) RunTLS(addr string, cert string, key string) error { func (engine *Engine) RunTLS(addr string, cert string, key string) (err error) {
debugPrint("[WARNING] Running in DEBUG mode! Disable it before going production")
debugPrint("Listening and serving HTTPS on %s\n", addr) debugPrint("Listening and serving HTTPS on %s\n", addr)
return http.ListenAndServeTLS(addr, cert, key, engine) defer debugPrintError(err)
err = http.ListenAndServe(addr, engine)
return
} }
// ServeHTTP makes the router implement the http.Handler interface. // ServeHTTP makes the router implement the http.Handler interface.

View File

@ -45,7 +45,7 @@ func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *R
func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers HandlersChain) { func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers HandlersChain) {
absolutePath := group.calculateAbsolutePath(relativePath) absolutePath := group.calculateAbsolutePath(relativePath)
handlers = group.combineHandlers(handlers) handlers = group.combineHandlers(handlers)
debugRoute(httpMethod, absolutePath, handlers) debugPrintRoute(httpMethod, absolutePath, handlers)
group.engine.handle(httpMethod, absolutePath, handlers) group.engine.handle(httpMethod, absolutePath, handlers)
} }