diff --git a/log/input.go b/log/input.go index 60f4af6..639278c 100644 --- a/log/input.go +++ b/log/input.go @@ -8,6 +8,12 @@ import ( "time" ) +var ( + warnLogLines = new(uint64) + errLogLines = new(uint64) + critLogLines = new(uint64) +) + func log(level Severity, msg string, tracer *ContextTracer) { if !started.IsSet() { @@ -146,6 +152,7 @@ func Infof(format string, things ...interface{}) { // Warning is used to log (potentially) bad events, but nothing broke (even a little) and there is no need to panic yet. func Warning(msg string) { + atomic.AddUint64(warnLogLines, 1) if fastcheck(WarningLevel) { log(WarningLevel, msg, nil) } @@ -153,6 +160,7 @@ func Warning(msg string) { // Warningf is used to log (potentially) bad events, but nothing broke (even a little) and there is no need to panic yet. func Warningf(format string, things ...interface{}) { + atomic.AddUint64(warnLogLines, 1) if fastcheck(WarningLevel) { log(WarningLevel, fmt.Sprintf(format, things...), nil) } @@ -160,6 +168,7 @@ func Warningf(format string, things ...interface{}) { // Error is used to log errors that break or impair functionality. The task/process may have to be aborted and tried again later. The system is still operational. Maybe User/Admin should be informed. func Error(msg string) { + atomic.AddUint64(errLogLines, 1) if fastcheck(ErrorLevel) { log(ErrorLevel, msg, nil) } @@ -167,6 +176,7 @@ func Error(msg string) { // Errorf is used to log errors that break or impair functionality. The task/process may have to be aborted and tried again later. The system is still operational. func Errorf(format string, things ...interface{}) { + atomic.AddUint64(errLogLines, 1) if fastcheck(ErrorLevel) { log(ErrorLevel, fmt.Sprintf(format, things...), nil) } @@ -174,6 +184,7 @@ func Errorf(format string, things ...interface{}) { // Critical is used to log events that completely break the system. Operation connot continue. User/Admin must be informed. func Critical(msg string) { + atomic.AddUint64(critLogLines, 1) if fastcheck(CriticalLevel) { log(CriticalLevel, msg, nil) } @@ -181,7 +192,26 @@ func Critical(msg string) { // Criticalf is used to log events that completely break the system. Operation connot continue. User/Admin must be informed. func Criticalf(format string, things ...interface{}) { + atomic.AddUint64(critLogLines, 1) if fastcheck(CriticalLevel) { log(CriticalLevel, fmt.Sprintf(format, things...), nil) } } + +// TotalWarningLogLines returns the total amount of warning log lines since +// start of the program. +func TotalWarningLogLines() uint64 { + return atomic.LoadUint64(warnLogLines) +} + +// TotalErrorLogLines returns the total amount of error log lines since start +// of the program. +func TotalErrorLogLines() uint64 { + return atomic.LoadUint64(errLogLines) +} + +// TotalCriticalLogLines returns the total amount of critical log lines since +// start of the program. +func TotalCriticalLogLines() uint64 { + return atomic.LoadUint64(critLogLines) +} diff --git a/metrics/metric_logs.go b/metrics/metric_logs.go new file mode 100644 index 0000000..fbf570a --- /dev/null +++ b/metrics/metric_logs.go @@ -0,0 +1,49 @@ +package metrics + +import ( + "github.com/safing/portbase/api" + "github.com/safing/portbase/log" +) + +func registeLogMetrics() (err error) { + _, err = NewFetchingCounter( + "logs/warning/total", + nil, + log.TotalWarningLogLines, + &Options{ + Name: "Total Warning Log Lines", + Permission: api.PermitUser, + }, + ) + if err != nil { + return err + } + + _, err = NewFetchingCounter( + "logs/error/total", + nil, + log.TotalErrorLogLines, + &Options{ + Name: "Total Error Log Lines", + Permission: api.PermitUser, + }, + ) + if err != nil { + return err + } + + _, err = NewFetchingCounter( + "logs/critical/total", + nil, + log.TotalCriticalLogLines, + &Options{ + Name: "Total Critical Log Lines", + Permission: api.PermitUser, + }, + ) + if err != nil { + return err + } + + return nil +} diff --git a/metrics/module.go b/metrics/module.go index 4eeb2be..d8df458 100644 --- a/metrics/module.go +++ b/metrics/module.go @@ -29,6 +29,9 @@ var ( // ErrAlreadySet is returned when a value is already set and cannot be changed. ErrAlreadySet = errors.New("already set") + + // ErrInvalidOptions is returned when invalid options where provided. + ErrInvalidOptions = errors.New("invalid options") ) func init() { @@ -59,6 +62,10 @@ func start() error { return err } + if err := registeLogMetrics(); err != nil { + return err + } + if err := registerAPI(); err != nil { return err }