Zeropino package provides a custom JSON format as a default for zerolog logger. This log format is inspired by Mia-Platform logging guidelines and glogger logger.
In addition, it draws similarities to the structure adopted by Pino logger for Node JS. This allows to parse Zerolog logs by prettifiers, such as pino-pretty library, simplifing their inspection, while preserving logger efficiency during services opererations.
Besides logger customization, Zeropino package offers middleware functions for the following web libraries and frameworks:
These should help integrate the custom logger within a service.
Installation
go get -u github.com/danibix95/zeropino
Getting Started
Basic Initialization and Usage
Create a zerolog logger with the added fields specified by Zeropino.
package main
import "github.com/danibix95/zeropino"
func main() {
logger, err := zeropino.Init(zeropino.InitOptions{})
// handle err here
logger.Warn().Msg("there is no real going back")
}
// Output: {"level":"40","pid":12739,"hostname":"bag-end","time":1618003000857,"msg":"there is no real going back"}
For additional details on how to use and customize the logger, please read zerolog documentation.
Custom Fields
Below are reported the custom JSON properties added or modified with respect to the default logger provided by zerolog:
level [string] represents log message level. It can get a value from 10 to 70, increasing of 10 steps at each level.
pid [int] the process id that is running the go program
hostname [string] the hostname which is running the go program
time int the time when the log is created, as a Unix Timestamp in milliseconds
msg [string] the actual message (as same as zerolog)
Init Options
There are three main options to customize the logger:
Level [string] select logger level - it can be one of these values, starting from the lowest to the highest:
trace
debug
info
warn
error
fatal
panic
silent (no log is produced using this level)
DisableTimeMs [bool] select whether the Unix timestamp should be in seconds rather than default format of milliseconds
Writer [io.Writer] define which writer should be used to produce the logs
Go net/http library
Here is provided an example of how to use the Zeropino RequestLogger middleware for net/http library:
package main
import (
"fmt"
"net/http"
"github.com/danibix95/zeropino"
zpstd "github.com/danibix95/zeropino/middlewares/std"
)
func welcomeHandler() http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
fmt.Fprint(w, "Hello, World!")
})
}
func main() {
logger, _ := zeropino.Init(zeropino.InitOptions{Level: "trace"})
router := http.NewServeMux()
// add the zeropino request logger middleware
middleware := zpstd.RequestLogger(logger, []string{"/-/"})
router.Handle("/welcome", middleware(welcomeHandler()))
server := &http.Server{
Addr: "0.0.0.0:3000",
Handler: router,
}
if err := server.ListenAndServe(); err != nil {
logger.Error().Err(err).Send()
}
}
Fiber Middleware
Here is provided an example of how to use the Zeropino RequestLogger middleware for fiber:
package main
import (
"github.com/gofiber/fiber/v2"
zp "github.com/danibix95/zeropino"
zpfiber "github.com/danibix95/zeropino/middlewares/fiber"
)
func main() {
app := fiber.New()
logger, _ := zp.Init(zp.InitOptions{Level: "trace"})
// add the zeropino request logger middleware
app.Use(zpfiber.RequestLogger(logger))
app.Get("/welcome", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"msg": "Hello, World!"})
})
if err := app.Listen(":3000"); err != nil {
logger.Fatal().Err(err).Msg("terminating app")
}
}
The RequestLogger middleware store a logger specific to each request in the fiber Locals request storage. It is possible to retrieve it with ReqLogger method, so that it is not necessary to create a new logger withing each handler.
Moreover, it is possible to change the stored logger using the methods and WithLogger. This enables the possibility to further customize it.
For example:
// add another middleware that use injected logger an further customize it
app.Use(func (c *fiber) error {
// get existing logger
// Note: if no logger exists, return a new zerolog Logger with
// the default zeropino configuration (level: info, writer: os.Stdout)
reqLogger := zpfiber.ReqLogger(c)
quoteLogger := reqLogger.With().Str("quote", "This is the way").Logger()
// modify the logger stored in the fiber context
zpfiber.WithLogger(c, "eLogger)
return c.Next()
})
app.Get("/quote", func (c *fiber.Ctx) error {
// get existing logger and log current fields
zpfiber.ReqLogger(c).Info().Send()
return c.JSON(fiber.Map{"msg": "a quote has been logged"})
})