Как использовать связующее программное обеспечение

Ниже приведена точка входа в мое веб-приложение, написанное на 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")
}
Другие вопросы по тегам