makeshift/pkg/log/log.go

126 lines
2.8 KiB
Go

package log
import (
"fmt"
"io"
"os"
"path/filepath"
"slices"
"strings"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
// string representation that directly corresponds to zerolog.Level
type LogLevel string
type LogLevelList []LogLevel
type LogFilter string
const (
DEBUG LogLevel = "debug"
INFO LogLevel = "info"
WARN LogLevel = "warn"
ERROR LogLevel = "error"
DISABLED LogLevel = "disabled"
TRACE LogLevel = "trace"
)
var Levels = [6]LogLevel{DEBUG, INFO, WARN, ERROR, DISABLED, TRACE}
var LogFile *os.File
func (ll LogLevel) String() string {
return string(ll)
}
func (ll *LogLevel) Set(v string) error {
switch LogLevel(v) {
case DEBUG, INFO, WARN, ERROR, DISABLED, TRACE:
*ll = LogLevel(v)
return nil
default:
return fmt.Errorf("must be one of %v", []LogLevel{
DEBUG,
INFO,
WARN,
ERROR,
DISABLED,
TRACE,
})
}
}
func (df LogLevel) Type() string {
return "LogLevel"
}
func InitWithLogLevel(logLevel LogLevel, logPath string) error {
var (
logger zerolog.Logger
level zerolog.Level
writer zerolog.LevelWriter
writers []io.Writer
err error
)
// set the logging level
level, err = strToLogLevel(logLevel)
if err != nil {
return fmt.Errorf("failed to convert log level: %v", err)
}
// add the default stderr writer
writers = append(writers, &zerolog.FilteredLevelWriter{
Writer: &zerolog.LevelWriterAdapter{os.Stderr},
Level: level,
})
// make the log directory if necessary
err = os.MkdirAll(filepath.Dir(logPath), 0o777)
if err != nil {
return fmt.Errorf("failed to create log path directory: %v", err)
}
// add another writer to write to a log file
if logPath != "" {
LogFile, err = os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
if err != nil {
return fmt.Errorf("failed to open log file: %v", err)
}
// add another write to write to the specified log file
writers = append(writers, &zerolog.FilteredLevelWriter{
Writer: zerolog.LevelWriterAdapter{LogFile},
Level: level,
})
}
writer = zerolog.MultiLevelWriter(writers...)
logger = zerolog.New(writer).Level(level).With().Timestamp().Caller().Logger()
zerolog.SetGlobalLevel(level)
log.Logger = logger
return nil
}
func strToLogLevel(ll LogLevel) (zerolog.Level, error) {
var tostr = func(lls []LogLevel) []string {
s := []string{}
for _, l := range lls {
s = append(s, string(l))
}
return s
}
if index := slices.Index(Levels[:], ll); index >= 0 {
// handle special cases to map index to DISABLED and TRACE
switch index {
case 4:
return zerolog.Disabled, nil
case 5:
return zerolog.TraceLevel, nil
}
return zerolog.Level(index), nil
}
return -100, fmt.Errorf(
"invalid log level (options: %s)", strings.Join(tostr(Levels[:]), ", "),
) // use 'info' by default
}