package logger import ( "fmt" "os" "sync" "time" "github.com/gofiber/fiber/v2/utils" "github.com/gofiber/fiber/v3" "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) var mu sync.Mutex // default logger for fiber func defaultLoggerInstance(c fiber.Ctx, data *Data, cfg Config) error { // Alias colors colors := c.App().Config().ColorScheme // Get new buffer buf := bytebufferpool.Get() // Put buffer back to pool defer bytebufferpool.Put(buf) // Default output when no custom Format or io.Writer is given if cfg.enableColors && cfg.Format == defaultFormat { // Format error if exist formatErr := "" if data.ChainErr != nil { formatErr = colors.Red + " | " + data.ChainErr.Error() + colors.Reset } // Format log to buffer _, _ = buf.WriteString(fmt.Sprintf("%s |%s %3d %s| %7v | %15s |%s %-7s %s| %-"+data.ErrPaddingStr+"s %s\n", data.Timestamp.Load().(string), statusColor(c.Response().StatusCode(), colors), c.Response().StatusCode(), colors.Reset, data.Stop.Sub(data.Start).Round(time.Millisecond), c.IP(), methodColor(c.Method(), colors), c.Method(), colors.Reset, c.Path(), formatErr, )) // Write buffer to output _, _ = cfg.Output.Write(buf.Bytes()) if cfg.Done != nil { cfg.Done(c, buf.Bytes()) } // End chain return nil } var err error // Loop over template parts execute dynamic parts and add fixed parts to the buffer for i, logFunc := range data.LogFuncChain { if logFunc == nil { _, _ = buf.Write(data.TemplateChain[i]) } else if data.TemplateChain[i] == nil { _, err = logFunc(buf, c, data, "") } else { _, err = logFunc(buf, c, data, utils.UnsafeString(data.TemplateChain[i])) } if err != nil { break } } // Also write errors to the buffer if err != nil { _, _ = buf.WriteString(err.Error()) } mu.Lock() // Write buffer to output if _, err := cfg.Output.Write(buf.Bytes()); err != nil { // Write error to output if _, err := cfg.Output.Write([]byte(err.Error())); err != nil { // There is something wrong with the given io.Writer fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) } } mu.Unlock() if cfg.Done != nil { cfg.Done(c, buf.Bytes()) } return nil } // run something before returning the handler func beforeHandlerFunc(cfg Config) { // If colors are enabled, check terminal compatibility if cfg.enableColors { cfg.Output = colorable.NewColorableStdout() if os.Getenv("TERM") == "dumb" || os.Getenv("NO_COLOR") == "1" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) { cfg.Output = colorable.NewNonColorable(os.Stdout) } } } func appendInt(output Buffer, v int) (int, error) { old := output.Len() output.Set(fasthttp.AppendUint(output.Bytes(), v)) return output.Len() - old, nil }