Как использовать связующее программное обеспечение
Ниже приведена точка входа в мое веб-приложение, написанное на Go с использованием Echo Labstack:
package main
import (
"github.com/labstack/echo"
mw "github.com/labstack/echo/middleware"
)
func main() {
controller := controllers.NewUserController(getSession())
app := echo.New()
app.Use(mw.Logger())
app.Use(mw.Recover())
app.SetDebug(true)
app.Post("/users", controller.CreateUser)
app.Get("/users", controller.ListUsers)
app.Get("/users/:id", controller.GetUser)
app.Patch("/users/:id", controller.UpdateUser)
app.Delete("/users/:id", controller.DeleteUser)
app.Run(":8000")
}
Как повторно использовать промежуточное программное обеспечение для ведения журналов, созданное в Echo
приложение? Я пробовал это:
контроллеры пакетов
import (
"net/http"
"github.com/labstack/echo"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
type (
UserController struct {
session *mgo.Session
}
)
func NewUserController(s *mgo.Session) *UserController {
return &UserController{s}
}
func (userController UserController) CreateUser(context *echo.Context) error {
user := &models.User{}
if err := context.Bind(user); err != nil {
context.Echo().Logger().Error("Error creating user")
return err
}
user.Id = bson.NewObjectId()
userController.session.DB("test").C("users").Insert(user)
context.Echo().Logger().Debug("Created user", id)
return context.JSON(http.StatusCreated, user)
}
Даже если код выше компилируется, оператор
context.Echo().Logger().Debug("Created user", id)
не производит никакого вывода... в то время как следующий оператор делает:
context.Echo().Logger().Info("Created user", id)
Я что-то пропустил?
4 ответа
Я только начал использовать Echo и не знаю, изменилось ли что-нибудь с тех пор, как это было опубликовано, но я обнаружил, что вы можете просто импортировать регистратор labstack:
import "github.com/labstack/gommon/log"
Тогда используйте это:
log.Debug("Created user", id)
По умолчанию echo использует уровень журнала "INFO". Таким образом, отображается все, что ниже уровня "ИНФОРМАЦИЯ".
Если вы хотите также видеть журналы "DEBUG", вам необходимо установить уровень "DEBUG":
import "github.com/labstack/gommon/log"
e.Logger.SetLevel(log.DEBUG)
Иерархия:
DEBUG
INFO
WARN
ERROR
OFF
вы можете использовать стороннее промежуточное ПО для ведения журналов, например https://github.com/sirupsen/logrus.
import log "github.com/sirupsen/logrus"
пример
создать функцию записи журнала:
func makeLogEntry(c echo.Context) *log.Entry {
if c == nil {
return log.WithFields(log.Fields{
"at": time.Now().Format("2006-01-02 15:04:05"),
})
}
return log.WithFields(log.Fields{
"at": time.Now().Format("2006-01-02 15:04:05"),
"method": c.Request().Method,
"uri": c.Request().URL.String(),
"ip": c.Request().RemoteAddr,
})
}
тогда:
func middlewareLogging(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
makeLogEntry(c).Info("incoming request")
return next(c)
}
}
func errorHandler(err error, c echo.Context) {
report, ok := err.(*echo.HTTPError)
if ok {
report.Message = fmt.Sprintf("http error %d - %v", report.Code, report.Message)
} else {
report = echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
makeLogEntry(c).Error(report.Message)
c.HTML(report.Code, report.Message.(string))
}
а затем в функции main():
func main() {
e := echo.New()
e.Use(middlewareLogging)
e.HTTPErrorHandler = errorHandler
e.GET("/index", func(c echo.Context) error {
return c.JSON(http.StatusOK, true)
})
lock := make(chan error)
go func(lock chan error) {
lock <- e.Start(":9000")
}(lock)
time.Sleep(1 * time.Millisecond)
makeLogEntry(nil).Warning("application started without ssl/tls enabled")
err := <-lock
if err != nil {
makeLogEntry(nil).Panic("failed to start application")
}
}
Ну технически я вижу 2 варианта
1) Добавьте логгер в контекст
func NewRestServer(...
logger := "initialize your logger as you like"
> e.Use(mw.AddContextLogger(logger)) // attach everywher
or
> ctxLog := mw.AddContextLogger(logger)
> e.GET("/endpoint", Handler, ctxLog) // single attachment
Реализация этого регистратора будет выглядеть аналогично (в зависимости от того, какой пакет регистратора вы будете использовать).
package mw
import (
"go.uber.org/zap"
"github.com/labstack/echo/v4"
)
func AddContextLogger(logger zap.Logger) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Set("logger", logger)
return next(c)
}
}
}
2) создайте для себя пакет API, т.е.
И внедрить его как зависимость
package v1
type Api struct {
UsersAPI
InvoicesAPI
logger logging.Logger
}
func NewApi(logger logging.Logger) *Api {
return &Api{
UsersAPI: UsersAPI{logger: logger},
InvoicesAPI: InvoicesAPI{logger: logger},
logger: logger,
}
}
и используй это
func NewRestServer(...
logger := "initialize your logger as you like"
v1api := v1.NewApi(logger)
и позвони ему через
e.GET("/v1/users", v1api.Users(c))
внутри пакета v1api у вас будут методы
func (a *api) Method1(...) (...) {
a.logger.Info("test")
}