* Copyright (c) 2024 Huawei Technologies Co., Ltd.
* openFuyao is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package tools
import (
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
)
const (
defaultLogPath = "/var/log/logging-operator"
)
var Logger *zap.SugaredLogger
var logLevel = map[string]zapcore.Level{
"debug": zapcore.DebugLevel,
"info": zapcore.InfoLevel,
"warn": zapcore.WarnLevel,
"error": zapcore.ErrorLevel,
}
type LogConfig struct {
Level string
EncoderType string
Path string
FileName string
MaxSize int
MaxBackups int
MaxAge int
LocalTime bool
Compress bool
OutMod string
}
func init() {
fmt.Print("The logging backend started running.")
conf := getDefaultConf()
Logger = GetLogger(conf)
}
func getDefaultConf() *LogConfig {
var defaultConf = &LogConfig{
Level: "info",
EncoderType: "console",
Path: defaultLogPath,
FileName: "logging-operator.log",
MaxSize: 20,
MaxBackups: 0,
MaxAge: 7,
LocalTime: false,
Compress: true,
OutMod: "console",
}
exePath, err := os.Executable()
if err != nil {
return defaultConf
}
serviceName := strings.TrimSuffix(filepath.Base(exePath), filepath.Ext(filepath.Base(exePath)))
defaultConf.Path = filepath.Join(defaultLogPath, serviceName)
return defaultConf
}
func GetLogger(conf *LogConfig) *zap.SugaredLogger {
writeSyncer := getLogWriter(conf)
encoder := getEncoder(conf)
level, ok := logLevel[strings.ToLower(conf.Level)]
if !ok {
level = logLevel["info"]
}
core := zapcore.NewCore(encoder, writeSyncer, level)
logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
return logger.Sugar()
}
func getEncoder(conf *LogConfig) zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
if strings.ToLower(conf.EncoderType) == "json" {
return zapcore.NewJSONEncoder(encoderConfig)
}
return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter(conf *LogConfig) zapcore.WriteSyncer {
switch conf.OutMod {
case "console":
return zapcore.AddSync(os.Stdout)
case "file":
return zapcore.AddSync(createLumberjackLogger(conf))
case "both":
return zapcore.NewMultiWriteSyncer(zapcore.AddSync(createLumberjackLogger(conf)), zapcore.AddSync(os.Stdout))
default:
return zapcore.AddSync(os.Stdout)
}
}
func createLumberjackLogger(conf *LogConfig) *lumberjack.Logger {
return &lumberjack.Logger{
Filename: filepath.Join(conf.Path, conf.FileName),
MaxSize: conf.MaxSize,
MaxBackups: conf.MaxBackups,
MaxAge: conf.MaxAge,
LocalTime: conf.LocalTime,
Compress: conf.Compress,
}
}
func HandleError(response http.ResponseWriter, statusCode int, err error) {
errorMessage := fmt.Sprintf("Error occurred: %v", err)
LogError(errorMessage)
response.WriteHeader(statusCode)
code, err := response.Write([]byte(errorMessage))
if err != nil {
errorMessage := fmt.Sprintf("Failed to write entity: %v", err)
LogError(errorMessage)
}
errorMessage = fmt.Sprintf("Error code %v", code)
LogError(errorMessage)
}
func AddContext(args ...interface{}) *zap.SugaredLogger {
return Logger.With(args...)
}
func LogDebug(args ...interface{}) {
Logger.Debug(args...)
}
func LogInfo(args ...interface{}) {
Logger.Info(args...)
}
func LogError(args ...interface{}) {
Logger.Error(args...)
}