mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-07-22 20:41:40 +02:00
Rework pkg/log, add 'loglevel' and 'logdate' flags, streamline
- removes some previously added manual location strings: now handled by pkg/log depending on loglevel - kept manual string locations on fmt print functions - add 'notice' and 'critical' loglevels - add 'Panic' and 'Panicf' functions to log panics - adresses issue #26
This commit is contained in:
@@ -46,7 +46,7 @@ func loadJobMeta(filename string) (*schema.JobMeta, error) {
|
||||
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
log.Errorf("ARCHIVE/FSBACKEND > loadJobMeta() > open file error: %v", err)
|
||||
log.Errorf("loadJobMeta() > open file error: %v", err)
|
||||
return &schema.JobMeta{}, err
|
||||
}
|
||||
defer f.Close()
|
||||
@@ -58,19 +58,19 @@ func (fsa *FsArchive) Init(rawConfig json.RawMessage) error {
|
||||
|
||||
var config FsArchiveConfig
|
||||
if err := json.Unmarshal(rawConfig, &config); err != nil {
|
||||
log.Errorf("ARCHIVE/FSBACKEND > Init() > Unmarshal error: %v", err)
|
||||
log.Errorf("Init() > Unmarshal error: %v", err)
|
||||
return err
|
||||
}
|
||||
if config.Path == "" {
|
||||
err := fmt.Errorf("ARCHIVE/FSBACKEND > Init() : empty config.Path")
|
||||
log.Errorf("ARCHIVE/FSBACKEND > Init() > config.Path error: %v", err)
|
||||
log.Errorf("Init() > config.Path error: %v", err)
|
||||
return err
|
||||
}
|
||||
fsa.path = config.Path
|
||||
|
||||
entries, err := os.ReadDir(fsa.path)
|
||||
if err != nil {
|
||||
log.Errorf("ARCHIVE/FSBACKEND > Init() > ReadDir() error: %v", err)
|
||||
log.Errorf("Init() > ReadDir() error: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func (fsa *FsArchive) LoadJobData(job *schema.Job) (schema.JobData, error) {
|
||||
filename := getPath(job, fsa.path, "data.json")
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
log.Errorf("ARCHIVE/FSBACKEND > LoadJobData() > open file error: %v", err)
|
||||
log.Errorf("LoadJobData() > open file error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
@@ -104,7 +104,7 @@ func (fsa *FsArchive) LoadClusterCfg(name string) (*schema.Cluster, error) {
|
||||
|
||||
b, err := os.ReadFile(filepath.Join(fsa.path, name, "cluster.json"))
|
||||
if err != nil {
|
||||
log.Errorf("ARCHIVE/FSBACKEND > LoadClusterCfg() > open file error: %v", err)
|
||||
log.Errorf("LoadClusterCfg() > open file error: %v", err)
|
||||
return &schema.Cluster{}, err
|
||||
}
|
||||
if config.Keys.Validate {
|
||||
@@ -121,13 +121,13 @@ func (fsa *FsArchive) Iter() <-chan *schema.JobMeta {
|
||||
go func() {
|
||||
clustersDir, err := os.ReadDir(fsa.path)
|
||||
if err != nil {
|
||||
log.Fatalf("ARCHIVE/FSBACKEND > Reading clusters failed @ cluster dirs: %s", err.Error())
|
||||
log.Fatalf("Reading clusters failed @ cluster dirs: %s", err.Error())
|
||||
}
|
||||
|
||||
for _, clusterDir := range clustersDir {
|
||||
lvl1Dirs, err := os.ReadDir(filepath.Join(fsa.path, clusterDir.Name()))
|
||||
if err != nil {
|
||||
log.Fatalf("ARCHIVE/FSBACKEND > Reading jobs failed @ lvl1 dirs: %s", err.Error())
|
||||
log.Fatalf("Reading jobs failed @ lvl1 dirs: %s", err.Error())
|
||||
}
|
||||
|
||||
for _, lvl1Dir := range lvl1Dirs {
|
||||
@@ -138,21 +138,21 @@ func (fsa *FsArchive) Iter() <-chan *schema.JobMeta {
|
||||
|
||||
lvl2Dirs, err := os.ReadDir(filepath.Join(fsa.path, clusterDir.Name(), lvl1Dir.Name()))
|
||||
if err != nil {
|
||||
log.Fatalf("ARCHIVE/FSBACKEND > Reading jobs failed @ lvl2 dirs: %s", err.Error())
|
||||
log.Fatalf("Reading jobs failed @ lvl2 dirs: %s", err.Error())
|
||||
}
|
||||
|
||||
for _, lvl2Dir := range lvl2Dirs {
|
||||
dirpath := filepath.Join(fsa.path, clusterDir.Name(), lvl1Dir.Name(), lvl2Dir.Name())
|
||||
startTimeDirs, err := os.ReadDir(dirpath)
|
||||
if err != nil {
|
||||
log.Fatalf("ARCHIVE/FSBACKEND > Reading jobs failed @ starttime dirs: %s", err.Error())
|
||||
log.Fatalf("Reading jobs failed @ starttime dirs: %s", err.Error())
|
||||
}
|
||||
|
||||
for _, startTimeDir := range startTimeDirs {
|
||||
if startTimeDir.IsDir() {
|
||||
job, err := loadJobMeta(filepath.Join(dirpath, startTimeDir.Name(), "meta.json"))
|
||||
if err != nil {
|
||||
log.Errorf("ARCHIVE/FSBACKEND > error in %s: %s", filepath.Join(dirpath, startTimeDir.Name()), err.Error())
|
||||
log.Errorf("error in %s: %s", filepath.Join(dirpath, startTimeDir.Name()), err.Error())
|
||||
} else {
|
||||
ch <- job
|
||||
}
|
||||
|
@@ -64,7 +64,7 @@ type NLExprIntRange struct {
|
||||
|
||||
func (nle NLExprIntRange) consume(input string) (next string, ok bool) {
|
||||
if !nle.zeroPadded || nle.digits < 1 {
|
||||
log.Error("ARCHIVE/NODELIST > only zero-padded ranges are allowed")
|
||||
log.Error("only zero-padded ranges are allowed")
|
||||
return "", false
|
||||
}
|
||||
|
||||
|
224
pkg/log/log.go
224
pkg/log/log.go
@@ -9,122 +9,274 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Provides a simple way of logging with different levels.
|
||||
// Time/Data are not logged on purpose because systemd adds
|
||||
// them for us.
|
||||
// Time/Date are not logged because systemd adds
|
||||
// them for us (Default, can be changed by flag '--logdate true').
|
||||
//
|
||||
// Uses these prefixes: https://www.freedesktop.org/software/systemd/man/sd-daemon.html
|
||||
|
||||
var logDateTime bool
|
||||
var logLevel string
|
||||
|
||||
var (
|
||||
DebugWriter io.Writer = os.Stderr
|
||||
NoteWriter io.Writer = os.Stderr
|
||||
InfoWriter io.Writer = os.Stderr
|
||||
WarnWriter io.Writer = os.Stderr
|
||||
ErrWriter io.Writer = os.Stderr
|
||||
CritWriter io.Writer = os.Stderr
|
||||
)
|
||||
|
||||
var (
|
||||
DebugPrefix string = "<7>[DEBUG] "
|
||||
InfoPrefix string = "<6>[INFO] "
|
||||
WarnPrefix string = "<4>[WARNING] "
|
||||
ErrPrefix string = "<3>[ERROR] "
|
||||
DebugPrefix string = "<7>[DEBUG] "
|
||||
InfoPrefix string = "<6>[INFO] "
|
||||
NotePrefix string = "<5>[NOTICE] "
|
||||
WarnPrefix string = "<4>[WARNING] "
|
||||
ErrPrefix string = "<3>[ERROR] "
|
||||
CritPrefix string = "<2>[CRITICAL] "
|
||||
)
|
||||
|
||||
var (
|
||||
// No Time/Date
|
||||
DebugLog *log.Logger = log.New(DebugWriter, DebugPrefix, 0)
|
||||
InfoLog *log.Logger = log.New(InfoWriter, InfoPrefix, 0)
|
||||
WarnLog *log.Logger = log.New(WarnWriter, WarnPrefix, 0)
|
||||
ErrLog *log.Logger = log.New(ErrWriter, ErrPrefix, 0)
|
||||
InfoLog *log.Logger = log.New(InfoWriter, InfoPrefix, 0)
|
||||
NoteLog *log.Logger = log.New(NoteWriter, NotePrefix, log.Lshortfile)
|
||||
WarnLog *log.Logger = log.New(WarnWriter, WarnPrefix, log.Lshortfile)
|
||||
ErrLog *log.Logger = log.New(ErrWriter, ErrPrefix, log.Llongfile)
|
||||
CritLog *log.Logger = log.New(CritWriter, CritPrefix, log.Llongfile)
|
||||
// Log Time/Date
|
||||
DebugTimeLog *log.Logger = log.New(DebugWriter, DebugPrefix, log.LstdFlags)
|
||||
InfoTimeLog *log.Logger = log.New(InfoWriter, InfoPrefix, log.LstdFlags)
|
||||
NoteTimeLog *log.Logger = log.New(NoteWriter, NotePrefix, log.LstdFlags|log.Lshortfile)
|
||||
WarnTimeLog *log.Logger = log.New(WarnWriter, WarnPrefix, log.LstdFlags|log.Lshortfile)
|
||||
ErrTimeLog *log.Logger = log.New(ErrWriter, ErrPrefix, log.LstdFlags|log.Llongfile)
|
||||
CritTimeLog *log.Logger = log.New(CritWriter, CritPrefix, log.LstdFlags|log.Llongfile)
|
||||
)
|
||||
|
||||
func init() {
|
||||
if lvl, ok := os.LookupEnv("LOGLEVEL"); ok {
|
||||
switch lvl {
|
||||
/* CONFIG */
|
||||
|
||||
func SetLogLevel(lvl string) {
|
||||
// fmt.Printf("pkg/log: Set LOGLEVEL -> %s\n", lvl)
|
||||
switch lvl {
|
||||
case "crit":
|
||||
ErrWriter = io.Discard
|
||||
fallthrough
|
||||
case "err", "fatal":
|
||||
WarnWriter = io.Discard
|
||||
fallthrough
|
||||
case "warn":
|
||||
InfoWriter = io.Discard
|
||||
fallthrough
|
||||
case "notice":
|
||||
NoteWriter = io.Discard
|
||||
fallthrough
|
||||
case "info":
|
||||
DebugWriter = io.Discard
|
||||
break
|
||||
case "debug":
|
||||
// Nothing to do...
|
||||
break
|
||||
default:
|
||||
Warnf("environment variable LOGLEVEL has invalid value %#v", lvl)
|
||||
}
|
||||
fmt.Printf("pkg/log: Flag 'loglevel' has invalid value %#v\npkg/log: Will use default loglevel 'debug'\n", lvl)
|
||||
SetLogLevel("debug")
|
||||
}
|
||||
}
|
||||
|
||||
func Debug(v ...interface{}) {
|
||||
if DebugWriter != io.Discard {
|
||||
DebugLog.Print(v...)
|
||||
}
|
||||
func SetLogDateTime(logdate bool) {
|
||||
//fmt.Printf("pkg/log: Set DATEBOOL -> %v\n", logdate)
|
||||
logDateTime = logdate
|
||||
}
|
||||
|
||||
func Info(v ...interface{}) {
|
||||
if InfoWriter != io.Discard {
|
||||
InfoLog.Print(v...)
|
||||
}
|
||||
/* PRINT */
|
||||
|
||||
// Private helper
|
||||
func printStr(v ...interface{}) string {
|
||||
return fmt.Sprint(v...)
|
||||
}
|
||||
|
||||
func Print(v ...interface{}) {
|
||||
Info(v...)
|
||||
}
|
||||
|
||||
func Debug(v ...interface{}) {
|
||||
if DebugWriter != io.Discard {
|
||||
out := printStr(v...)
|
||||
if logDateTime {
|
||||
DebugTimeLog.Output(2, out)
|
||||
} else {
|
||||
DebugLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Info(v ...interface{}) {
|
||||
if InfoWriter != io.Discard {
|
||||
out := printStr(v...)
|
||||
if logDateTime {
|
||||
InfoTimeLog.Output(2, out)
|
||||
} else {
|
||||
InfoLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Note(v ...interface{}) {
|
||||
if NoteWriter != io.Discard {
|
||||
out := printStr(v...)
|
||||
if logDateTime {
|
||||
NoteTimeLog.Output(2, out)
|
||||
} else {
|
||||
NoteLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Warn(v ...interface{}) {
|
||||
if WarnWriter != io.Discard {
|
||||
WarnLog.Print(v...)
|
||||
out := printStr(v...)
|
||||
if logDateTime {
|
||||
WarnTimeLog.Output(2, out)
|
||||
} else {
|
||||
WarnLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Error(v ...interface{}) {
|
||||
if ErrWriter != io.Discard {
|
||||
ErrLog.Print(v...)
|
||||
out := printStr(v...)
|
||||
if logDateTime {
|
||||
ErrTimeLog.Output(2, out)
|
||||
} else {
|
||||
ErrLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Writes panic stacktrace, keeps application alive
|
||||
func Panic(v ...interface{}) {
|
||||
Error(v...)
|
||||
panic("Panic triggered ...")
|
||||
}
|
||||
|
||||
// Writes error log, stops application
|
||||
func Fatal(v ...interface{}) {
|
||||
Error(v...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
if DebugWriter != io.Discard {
|
||||
DebugLog.Printf(format, v...)
|
||||
func Crit(v ...interface{}) {
|
||||
if CritWriter != io.Discard {
|
||||
out := printStr(v...)
|
||||
if logDateTime {
|
||||
CritTimeLog.Output(2, out)
|
||||
} else {
|
||||
CritLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Infof(format string, v ...interface{}) {
|
||||
if InfoWriter != io.Discard {
|
||||
InfoLog.Printf(format, v...)
|
||||
}
|
||||
/* PRINT FORMAT*/
|
||||
|
||||
// Private helper
|
||||
func printfStr(format string, v ...interface{}) string {
|
||||
return fmt.Sprintf(format, v...)
|
||||
}
|
||||
|
||||
func Printf(format string, v ...interface{}) {
|
||||
Infof(format, v...)
|
||||
}
|
||||
|
||||
func Finfof(w io.Writer, format string, v ...interface{}) {
|
||||
if w != io.Discard {
|
||||
fmt.Fprintf(InfoWriter, InfoPrefix+format+"\n", v...)
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
if DebugWriter != io.Discard {
|
||||
out := printfStr(format, v...)
|
||||
if logDateTime {
|
||||
DebugTimeLog.Output(2, out)
|
||||
} else {
|
||||
DebugLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Infof(format string, v ...interface{}) {
|
||||
if InfoWriter != io.Discard {
|
||||
out := printfStr(format, v...)
|
||||
if logDateTime {
|
||||
InfoTimeLog.Output(2, out)
|
||||
} else {
|
||||
InfoLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Notef(format string, v ...interface{}) {
|
||||
if NoteWriter != io.Discard {
|
||||
out := printfStr(format, v...)
|
||||
if logDateTime {
|
||||
NoteTimeLog.Output(2, out)
|
||||
} else {
|
||||
NoteLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
if WarnWriter != io.Discard {
|
||||
WarnLog.Printf(format, v...)
|
||||
out := printfStr(format, v...)
|
||||
if logDateTime {
|
||||
WarnTimeLog.Output(2, out)
|
||||
} else {
|
||||
WarnLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
if ErrWriter != io.Discard {
|
||||
ErrLog.Printf(format, v...)
|
||||
out := printfStr(format, v...)
|
||||
if logDateTime {
|
||||
ErrTimeLog.Output(2, out)
|
||||
} else {
|
||||
ErrLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Writes panic stacktrace, keeps application alive
|
||||
func Panicf(format string, v ...interface{}) {
|
||||
Errorf(format, v...)
|
||||
panic("Panic triggered ...")
|
||||
}
|
||||
|
||||
// Writes error log, stops application
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
Errorf(format, v...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func Critf(format string, v ...interface{}) {
|
||||
if CritWriter != io.Discard {
|
||||
out := printfStr(format, v...)
|
||||
if logDateTime {
|
||||
CritTimeLog.Output(2, out)
|
||||
} else {
|
||||
CritLog.Output(2, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SPECIAL */
|
||||
|
||||
func Finfof(w io.Writer, format string, v ...interface{}) {
|
||||
if w != io.Discard {
|
||||
if logDateTime {
|
||||
currentTime := time.Now()
|
||||
fmt.Fprintf(InfoWriter, currentTime.String()+InfoPrefix+format+"\n", v...)
|
||||
} else {
|
||||
fmt.Fprintf(InfoWriter, InfoPrefix+format+"\n", v...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ func Validate(k Kind, r io.Reader) (err error) {
|
||||
|
||||
var v interface{}
|
||||
if err := json.NewDecoder(r).Decode(&v); err != nil {
|
||||
log.Errorf("SCHEMA/VALIDATE > Failed to decode %v", err)
|
||||
log.Errorf("Failed to decode %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user