Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Simple logging in Golang

I’m aware this might be a duplicate of How to implement level-based logging in Golang?, but I’d appreciate additional advice specific to my situation, perhaps for 11 years something new came up :D.

I’m have already used Go’s built-in log package, which works fine, but I’d like to enhance, see an example of simple but still usable implementation. I’ve got those criterias in mind:

  • Separating logging into its own package.
  • Handling different log levels (e.g., info, warning, error).
  • Structuring the system to allow for both error and general message logs.
  • Maybe use a slog instead of plain log

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

If you really need something simple, here is how I usually write for pet-projects:

package logging

import (
    "fmt"
    "log"
    "os"
    "regexp"
    "runtime"
)

type logLevel int

const (
    INFO logLevel = iota
    ERR
)

type application struct {
    level    logLevel
    errorLog *log.Logger
    infoLog  *log.Logger
}

var infoLog = log.New(os.Stdout, "INFO: \t", log.Ltime)
var errorLog = log.New(os.Stderr, "ERROR: \t", log.Ltime)

var path string

func NewLogger(Level logLevel) *application {
    return &application{
        level:    Level,
        errorLog: errorLog,
        infoLog:  infoLog,
    }
}

func (l *application) Info(msg ...any) {
    if l.level <= INFO {
        file, line := getCaller()
        l.infoLog.Printf("[%s : %d] \n\n%s\n\n", file, line, fmt.Sprint(msg...))
    }
}

func (l *application) Error(err ...any) {
    if l.level <= ERR {
        file, line := getCaller()
        l.errorLog.Fatalf("[%s : %d] \n\n%s\n\n", file, line, fmt.Sprint(err...))
    }
}

func getCaller() (string, int) {
    key := os.Getenv("KEY_WORD") // assign your folder name, so we can crop no-required part

    _, file, line, ok := runtime.Caller(2)
    if !ok {
        log.Fatal("runtime caller has an error")
    }

    if key == "" {
        fmt.Print("key is empty")
        return file, line // Return without modifying if key is not set
    }

    regExp, _ := regexp.Compile(".*" + regexp.QuoteMeta(key)) // regex for deleting left side 

    file = regExp.ReplaceAllString(file, key)

    return file, line
}

It is not super advance or something, but still does the job well, main feature is, perhaps, levelling logs and errors into different streams, and showing path to file, where error did occur.

If your goal is study – look up at question you attached,

there are a bunch of examples. Look at them and try to advance snippet I provided in the way you like

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading