Go Gin: Pass Zap Logger

1.7k views Asked by At

I'm working in a project using Gin and recently started implementing a logger through the project. I saw a couple libraries but decided to go with uber's Zap.

I've got controllers that look like this:

package controllers

func ListAllArtists(c *gin.Context) {
    db := c.MustGet("db").(*gorm.DB)
    service := services.NewArtistService(db)
    pagination := entities.PaginationFromRequest(c)
    err := service.FindAll(pagination)
    if err != nil {
        err := c.AbortWithError(http.StatusBadRequest, err)
        if err != nil {
            fmt.Print(err)
        }
        return
    }

    responses.RespondPaginated(c, pagination, service.Artists)
}

as you can see they call a service which performs a DB call. So the only parameter the service receives (in this case) is the db connection.

Routes are defined as following:

func ArtistRoutes(router *gin.RouterGroup) {
    artistRouter := router.Group("/artists")
    {
        artistRouter.POST("", controllers.CreateNewArtist)
        artistRouter.GET("", controllers.ListAllArtists)
        artistRouter.GET("/search", controllers.SearchArtists)
        artistRouter.GET("/slug/:slug", controllers.GetArtistBySlug)
        artistRouter.GET("/:id", controllers.GetArtistById)
        artistRouter.DELETE("/:id", controllers.DeleteArtistById)
        artistRouter.PATCH("/:id", controllers.UpdateArtist)
    }
}

My main file looks like:

app := core.NewApp()
    if app == nil {
        log.Fatal("app could not be initialized. Shutting down")
    }

    // initialize middlewares.
    app.Router.Use(func(c *gin.Context) {
        c.Set("db", app.Db)
    })

    // serve static files. All static files (images, videos, css, js, etc) will be served from this location.
    app.Router.Static("/assets", "./assets")

    // Initialize all api routes
    routes.InitializeRoutes(app.Router.Group("/api/v1"))

My question is: is there a way to pass down the logger? can I make it part of c *gin.Context so it's widely available?

I'm aware of an option that zap offers in which you can make the logger global, but that's not recommended (although my project is pretty small) so I wouldn't want to go that route.

1

There are 1 answers

1
MrCujo On

Not sure if this is the best way but it is what I ended doing (at the moment, waiting for a more suitable response to implement):

Created a logger.go file in my utils package:

package utils

import "go.uber.org/zap"

var Logger *zap.Logger

func InitializeLogger() {
    Logger, _ = zap.NewProduction()
}

then in my main I initialized the logger:

utils.InitializeLogger()

and using the logger throughout the project like:

func CreateNewArtist(c *gin.Context) {
    db := c.MustGet("db").(*gorm.DB)
    service := services.NewArtistService(db)

    utils.Logger.Info("Creating new artist")

    body := forms.AddArtistForm{}

    utils.Logger.Info("Request body")
    utils.Logger.Info(body.Name)
    // getting request's body
    if err := c.BindJSON(&body); err != nil {
        responses.RespondWithErrors(c, http.StatusBadRequest, err)
        return
    }

    artist, err := service.Save(body)
    if err != nil {
        responses.RespondWithErrors(c, http.StatusBadRequest, err)
        return
    }

    responses.RespondSuccess(c, artist)
}