Logging lib used by Cyclops-enterprise
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
logging/logging.go

168 lines
2.9 KiB

//
// A logging framework for use within the Cyclops Accounting
// and Billing framework.
//
// (C) Cyclops Labs 2019
//
package logging
6 years ago
import (
"errors"
6 years ago
"fmt"
"io"
"log"
"os"
"runtime"
"strconv"
6 years ago
"strings"
)
// higher log level means more logging...
6 years ago
const (
ERROR = iota
WARNING
INFO
DEBUG
TRACE
)
var logLevelStringMap = map[string]int{
"error": ERROR,
"warning": WARNING,
"info": INFO,
"debug": DEBUG,
"trace": TRACE,
}
type logOutput interface {
Printf(format string, a ...interface{})
// Println(format string, a ...interface{})
init(m *io.Writer, s string, ll int)
}
type logStream struct {
s *log.Logger
logLevel int
}
var (
Trace logStream
Debug logStream
Info logStream
Warning logStream
Error logStream
DefaultLogger logStream
LogLevel = WARNING
6 years ago
)
func (l *logStream) Printf(format string, a ...interface{}) {
6 years ago
// describe(a)
if LogLevel < l.logLevel {
6 years ago
return
6 years ago
}
// if no specific logger is configured for this logstrea, write to stdout...
logMessage := fmt.Sprintf(format, a...)
// Caller(1) is one level up the call stack - 0 identifies the caller of
// Caller which is this function...
callingStr := "[Unknown calling function]"
_, fn, lineNum, callerValid := runtime.Caller(1)
if callerValid {
callingStr = fn + ":" + strconv.Itoa(lineNum)
}
6 years ago
if l.s == nil {
fmt.Print(callingStr, " ", logMessage)
6 years ago
return
6 years ago
}
l.s.Print(callingStr, " ", logMessage)
// Printf(format, a...)
6 years ago
}
func (l *logStream) init(m io.Writer, s string, ll int) {
l.s = log.New(m, s, log.Ldate|log.Ltime)
6 years ago
l.logLevel = ll
6 years ago
}
// function to parse string representation of log level into integer - if there
// is no match of the string, it will return 0 which maps to error only
// logging...perhaps this could be made more explicit
func determineLogLevel(lstr string) (returnVal int, err error) {
var validLogLevel bool
lstrLowerCase := strings.ToLower(lstr)
if returnVal, validLogLevel = logLevelStringMap[lstrLowerCase]; validLogLevel == false {
err = errors.New("Invalid Log Level")
}
return
6 years ago
}
// InitLogger initializes the logging system
func InitLogger(logFile string, logLevelStr string, logToConsole bool) (err error) {
6 years ago
var file *os.File
var writters []io.Writer
if LogLevel, err = determineLogLevel(logLevelStr); err != nil {
6 years ago
log.Println("Unable to determine the log level:", logLevelStr, ":", err)
return
}
6 years ago
if logFile != "" {
if file, err = os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); err != nil {
log.Println("Failed to open log file:", logFile, ":", err)
return
6 years ago
}
writters = append(writters, file)
}
if logToConsole {
writters = append(writters, os.Stdout)
6 years ago
}
multi := io.MultiWriter(writters...)
6 years ago
Trace.init(multi, " TRACE: ", TRACE)
Debug.init(multi, " DEBUG: ", DEBUG)
Info.init(multi, " INFO: ", INFO)
Warning.init(multi, "WARNING: ", WARNING)
Error.init(multi, " ERROR: ", ERROR)
return
6 years ago
}