diff --git a/log/flags.go b/log/flags.go new file mode 100644 index 0000000..b00a94b --- /dev/null +++ b/log/flags.go @@ -0,0 +1,13 @@ +package log + +import "flag" + +var ( + logLevelFlag string + fileLogLevelsFlag string +) + +func init() { + flag.StringVar(&logLevelFlag, "log", "info", "set log level to [trace|debug|info|warning|error|critical]") + flag.StringVar(&fileLogLevelsFlag, "flog", "", "set log level of files: database=trace,firewall=debug") +} diff --git a/log/interface.go b/log/interface.go deleted file mode 100644 index 766b8f7..0000000 --- a/log/interface.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright Safing ICS Technologies GmbH. Use of this source code is governed by the AGPL license that can be found in the LICENSE file. - -package log - -var Logger *LoggingInterface - -type LoggingInterface struct { -} - -func (*LoggingInterface) Tracef(things ...interface{}) { - Tracef(things...) -} - -func (*LoggingInterface) Trace(msg string) { - Trace(msg) -} - -func (*LoggingInterface) Debugf(things ...interface{}) { - Debugf(things...) -} - -func (*LoggingInterface) Debug(msg string) { - Debug(msg) -} - -func (*LoggingInterface) Infof(things ...interface{}) { - Infof(things...) -} - -func (*LoggingInterface) Info(msg string) { - Info(msg) -} - -func (*LoggingInterface) Warningf(things ...interface{}) { - Warningf(things...) -} - -func (*LoggingInterface) Warning(msg string) { - Warning(msg) -} - -func (*LoggingInterface) Errorf(things ...interface{}) { - Errorf(things...) -} - -func (*LoggingInterface) Error(msg string) { - Error(msg) -} - -func (*LoggingInterface) Criticalf(things ...interface{}) { - Criticalf(things...) -} - -func (*LoggingInterface) Critical(msg string) { - Critical(msg) -} - -func init() { - Logger = &LoggingInterface{} -} diff --git a/log/logging.go b/log/logging.go index d6e05c7..a053cf0 100644 --- a/log/logging.go +++ b/log/logging.go @@ -10,9 +10,6 @@ import ( "time" "github.com/tevino/abool" - - "github.com/Safing/safing-core/meta" - "github.com/Safing/safing-core/modules" ) // concept @@ -54,8 +51,6 @@ const ( ) var ( - module *modules.Module - logBuffer chan *logLine forceEmptyingOfBuffer chan bool @@ -68,6 +63,12 @@ var ( logsWaiting = make(chan bool, 1) logsWaitingFlag = abool.NewBool(false) + + shutdownSignal = make(chan struct{}, 0) + shutdownWaitGroup sync.WaitGroup + + started = abool.NewBool(false) + testErrors = abool.NewBool(false) ) func SetFileLevels(levels map[string]severity) { @@ -103,37 +104,34 @@ func ParseLevel(level string) severity { return 0 } -var () +func Start() error { -func init() { - - module = modules.Register("Logging", 0) - modules.RegisterLogger(Logger) + if !started.SetToIf(false, true) { + return nil + } logBuffer = make(chan *logLine, 8192) forceEmptyingOfBuffer = make(chan bool, 4) - initialLogLevel := ParseLevel(meta.LogLevel()) + initialLogLevel := ParseLevel(logLevelFlag) if initialLogLevel > 0 { atomic.StoreUint32(logLevel, uint32(initialLogLevel)) } else { - fmt.Printf("WARNING: invalid log level, falling back to level info.") + return fmt.Errorf("invalid log level \"%s\", falling back to level info", logLevelFlag) } // get and set file loglevels - fileLogLevels := meta.FileLogLevels() + fileLogLevels := fileLogLevelsFlag if len(fileLogLevels) > 0 { newFileLevels := make(map[string]severity) for _, pair := range strings.Split(fileLogLevels, ",") { splitted := strings.Split(pair, "=") if len(splitted) != 2 { - fmt.Printf("WARNING: invalid file log level \"%s\", ignoring", pair) - continue + return fmt.Errorf("invalid file log level \"%s\", ignoring", pair) } fileLevel := ParseLevel(splitted[1]) if fileLevel == 0 { - fmt.Printf("WARNING: invalid file log level \"%s\", ignoring", pair) - continue + return fmt.Errorf("invalid file log level \"%s\", ignoring", pair) } newFileLevels[splitted[0]] = fileLevel } @@ -141,5 +139,13 @@ func init() { } go writer() + Info("logging: started") + return nil } + +// Shutdown writes remaining log lines and then stops the logger. +func Shutdown() { + close(shutdownSignal) + shutdownWaitGroup.Wait() +} diff --git a/log/logging_test.go b/log/logging_test.go index a2e39f4..a7bfcdb 100644 --- a/log/logging_test.go +++ b/log/logging_test.go @@ -10,6 +10,11 @@ import ( // test waiting func TestLogging(t *testing.T) { + err := Start() + if err != nil { + t.Errorf("start failed: %s", err) + } + // skip if testing.Short() { t.Skip("skipping test in short mode.") diff --git a/log/output.go b/log/output.go index fc76773..7d4cb53 100644 --- a/log/output.go +++ b/log/output.go @@ -4,7 +4,7 @@ package log import ( "fmt" - "github.com/Safing/safing-core/taskmanager" + "github.com/Safing/portbase/taskmanager" "time" ) @@ -20,6 +20,8 @@ func writeLine(line *logLine) { func writer() { var line *logLine startedTask := false + shutdownWaitGroup.Add(1) + defer shutdownWaitGroup.Done() for { @@ -27,7 +29,7 @@ func writer() { select { case <-logsWaiting: logsWaitingFlag.UnSet() - case <-module.Stop: + case <-shutdownSignal: } // wait for timeslot to log, or when buffer is full @@ -35,20 +37,21 @@ func writer() { case <-taskmanager.StartVeryLowPriorityMicroTask(): startedTask = true case <-forceEmptyingOfBuffer: - case <-module.Stop: - select { - case line = <-logBuffer: - writeLine(line) - case <-time.After(10 * time.Millisecond): - writeLine(&logLine{ - "===== LOGGING STOPPED =====", - WarningLevel, - time.Now(), - "", - 0, - }) - module.StopComplete() - return + case <-shutdownSignal: + for { + select { + case line = <-logBuffer: + writeLine(line) + case <-time.After(10 * time.Millisecond): + writeLine(&logLine{ + "===== LOGGING STOPPED =====", + WarningLevel, + time.Now(), + "", + 0, + }) + return + } } }