multus-cni/logging/logging.go
Shahar Klein ecb79330c0 Add support for log rotation
When using debug level the log files tends to fill up quickly.
Add support for log rotation using lumberjack, simple and easy to use
log rotation module.

Signed-off-by: Shahar Klein <sklein@nvidia.com>
2020-06-17 15:31:19 +09:00

159 lines
3.6 KiB
Go

// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logging
import (
"fmt"
"os"
"strings"
"time"
"io"
"github.com/pkg/errors"
lumberjack "gopkg.in/natefinch/lumberjack.v2"
)
// Level type
type Level uint32
// PanicLevel...MaxLevel indicates the logging level
const (
PanicLevel Level = iota
ErrorLevel
VerboseLevel
DebugLevel
MaxLevel
UnknownLevel
)
var loggingStderr bool
var loggingW io.Writer
var loggingLevel Level
const defaultTimestampFormat = time.RFC3339
func (l Level) String() string {
switch l {
case PanicLevel:
return "panic"
case VerboseLevel:
return "verbose"
case ErrorLevel:
return "error"
case DebugLevel:
return "debug"
}
return "unknown"
}
func printf(level Level, format string, a ...interface{}) {
header := "%s [%s] "
t := time.Now()
if level > loggingLevel {
return
}
if loggingStderr {
fmt.Fprintf(os.Stderr, header, t.Format(defaultTimestampFormat), level)
fmt.Fprintf(os.Stderr, format, a...)
fmt.Fprintf(os.Stderr, "\n")
}
if loggingW != nil {
fmt.Fprintf(loggingW, header, t.Format(defaultTimestampFormat), level)
fmt.Fprintf(loggingW, format, a...)
fmt.Fprintf(loggingW, "\n")
}
}
// Debugf prints logging if logging level >= debug
func Debugf(format string, a ...interface{}) {
printf(DebugLevel, format, a...)
}
// Verbosef prints logging if logging level >= verbose
func Verbosef(format string, a ...interface{}) {
printf(VerboseLevel, format, a...)
}
// Errorf prints logging if logging level >= error
func Errorf(format string, a ...interface{}) error {
printf(ErrorLevel, format, a...)
return fmt.Errorf(format, a...)
}
// Panicf prints logging plus stack trace. This should be used only for unrecoverble error
func Panicf(format string, a ...interface{}) {
printf(PanicLevel, format, a...)
printf(PanicLevel, "========= Stack trace output ========")
printf(PanicLevel, "%+v", errors.New("Multus Panic"))
printf(PanicLevel, "========= Stack trace output end ========")
}
// GetLoggingLevel gets current logging level
func GetLoggingLevel() Level {
return loggingLevel
}
func getLoggingLevel(levelStr string) Level {
switch strings.ToLower(levelStr) {
case "debug":
return DebugLevel
case "verbose":
return VerboseLevel
case "error":
return ErrorLevel
case "panic":
return PanicLevel
}
fmt.Fprintf(os.Stderr, "multus logging: cannot set logging level to %s\n", levelStr)
return UnknownLevel
}
// SetLogLevel sets logging level
func SetLogLevel(levelStr string) {
level := getLoggingLevel(levelStr)
if level < MaxLevel {
loggingLevel = level
}
}
// SetLogStderr sets flag for logging stderr output
func SetLogStderr(enable bool) {
loggingStderr = enable
}
// SetLogFile sets logging file
func SetLogFile(filename string) {
if filename == "" {
return
}
loggingW = &lumberjack.Logger{
Filename: filename,
MaxSize: 100, // megabytes
MaxBackups: 5,
MaxAge: 5, // days
Compress: true,
}
}
func init() {
loggingStderr = true
loggingW = nil
loggingLevel = PanicLevel
}