Merge Go frontend (apiserver + xcecli) into meson build
This commit is contained in:
parent
43dc12a36c
commit
c9dc8c4676
205 changed files with 30793 additions and 328 deletions
188
src/frontend/apiserver/utils/logger.go
Normal file
188
src/frontend/apiserver/utils/logger.go
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
Log *zap.Logger
|
||||
once sync.Once
|
||||
config Config
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Logging struct {
|
||||
Level string `yaml:"level"`
|
||||
Encoding string `yaml:"encoding"`
|
||||
OutputPath string `yaml:"outputPath"`
|
||||
File struct {
|
||||
MaxSize int `yaml:"maxSize"`
|
||||
MaxBackups int `yaml:"maxBackups"`
|
||||
MaxAge int `yaml:"maxAge"`
|
||||
Compress bool `yaml:"compress"`
|
||||
} `yaml:"file"`
|
||||
EncoderConfig struct {
|
||||
MessageKey string `yaml:"messageKey"`
|
||||
LevelKey string `yaml:"levelKey"`
|
||||
TimeKey string `yaml:"timeKey"`
|
||||
NameKey string `yaml:"nameKey"`
|
||||
CallerKey string `yaml:"callerKey"`
|
||||
FunctionKey string `yaml:"functionKey"`
|
||||
StacktraceKey string `yaml:"stacktraceKey"`
|
||||
EncodeTime string `yaml:"timeEncoder"`
|
||||
EncodeLevel string `yaml:"levelEncoder"`
|
||||
} `yaml:"encoderConfig"`
|
||||
} `yaml:"logging"`
|
||||
}
|
||||
|
||||
func InitLogger() error {
|
||||
var err error
|
||||
once.Do(func() {
|
||||
err = loadLoggerConfig()
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func loadLoggerConfig() error {
|
||||
// read logger configuration file
|
||||
configPath := filepath.Join(Global_TopDir, "config", "logger.yaml")
|
||||
|
||||
// validate the yaml file format
|
||||
data, err := ValidateYamlFormat(configPath)
|
||||
if err != nil {
|
||||
DiagnoseLogCreationError("Fail to call DiagnoseLogCreationError with error", err)
|
||||
return err
|
||||
}
|
||||
if data == nil {
|
||||
err = errors.New("invalid logger.yaml file")
|
||||
DiagnoseLogCreationError("Fail to call ValidateYamlFormat and data is nil", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||
DiagnoseLogCreationError("Failed to parse logger configuration file", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle both formats for OutputPath
|
||||
if !filepath.IsAbs(config.Logging.OutputPath) {
|
||||
// If OutputPath is relative, prepend the logs directory
|
||||
config.Logging.OutputPath = filepath.Join(Global_TopDir, "logs", config.Logging.OutputPath)
|
||||
}
|
||||
|
||||
// Get the directory from the absolute path
|
||||
logFilePath := config.Logging.OutputPath // it store the absolute path
|
||||
logDir := filepath.Dir(logFilePath) // Extract the directory
|
||||
// Create the directory if it does not exist
|
||||
if err := os.MkdirAll(logDir, 0755); err != nil {
|
||||
DiagnoseLogCreationError("Failed to create logs directory", err)
|
||||
return err
|
||||
}
|
||||
|
||||
Log, err = createLogger(config)
|
||||
if err != nil {
|
||||
DiagnoseLogCreationError("Failed to create logger", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createLogger(config Config) (*zap.Logger, error) {
|
||||
configLevel, err := zapcore.ParseLevel(config.Logging.Level)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// create log file and set the permission
|
||||
file, err := os.OpenFile(config.Logging.OutputPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file.Close()
|
||||
|
||||
// configure lumberjack for log rotation
|
||||
logWriter := &lumberjack.Logger{
|
||||
Filename: config.Logging.OutputPath,
|
||||
MaxSize: config.Logging.File.MaxSize,
|
||||
MaxBackups: config.Logging.File.MaxBackups,
|
||||
MaxAge: config.Logging.File.MaxAge,
|
||||
Compress: config.Logging.File.Compress,
|
||||
}
|
||||
|
||||
// Create cores for different log levels
|
||||
core := zapcore.NewCore(
|
||||
zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
|
||||
MessageKey: config.Logging.EncoderConfig.MessageKey,
|
||||
LevelKey: config.Logging.EncoderConfig.LevelKey,
|
||||
TimeKey: config.Logging.EncoderConfig.TimeKey,
|
||||
NameKey: config.Logging.EncoderConfig.NameKey,
|
||||
CallerKey: config.Logging.EncoderConfig.CallerKey,
|
||||
StacktraceKey: "", // disable stacktrace
|
||||
EncodeTime: zapcore.ISO8601TimeEncoder,
|
||||
EncodeLevel: zapcore.CapitalLevelEncoder,
|
||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||
ConsoleSeparator: " ",
|
||||
}),
|
||||
zapcore.AddSync(logWriter),
|
||||
configLevel,
|
||||
)
|
||||
logger := zap.New(core,
|
||||
zap.AddCaller(), // caller info
|
||||
zap.AddStacktrace(zap.ErrorLevel), // show error stacktrace
|
||||
zap.AddCallerSkip(1), // skip one layer of caller
|
||||
)
|
||||
return logger, nil
|
||||
|
||||
}
|
||||
|
||||
func Info(msg string, fields ...zap.Field) {
|
||||
Log.WithOptions(zap.WithCaller(false)).Info(msg, fields...)
|
||||
}
|
||||
func Error(msg string, fields ...zap.Field) {
|
||||
Log.WithOptions(zap.WithCaller(false)).Error(msg, fields...)
|
||||
}
|
||||
|
||||
func Warn(msg string, fields ...zap.Field) {
|
||||
Log.WithOptions(zap.WithCaller(false)).Warn(msg, fields...)
|
||||
}
|
||||
|
||||
func Debug(msg string, fields ...zap.Field) {
|
||||
Log.WithOptions(zap.WithCaller(true)).Debug(msg, fields...)
|
||||
}
|
||||
|
||||
func Fatal(msg string, fields ...zap.Field) {
|
||||
Log.WithOptions(zap.WithCaller(false)).Fatal(msg, fields...)
|
||||
}
|
||||
|
||||
// DiagnoseLogCreationError is a helper function to diagnose the error when creating log file
|
||||
func DiagnoseLogCreationError(context string, err error) {
|
||||
// construct the error message
|
||||
logMsg := fmt.Sprintf("[%s] %s: %v\n", time.Now().Format("2006-01-02 15:04:05"), context, err)
|
||||
// define logger_error.log file path
|
||||
logFilePath := filepath.Join(Global_TopDir, "logs", "logger_error.log")
|
||||
// open log file
|
||||
f, fileErr := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if fileErr != nil {
|
||||
fmt.Printf("Failed to open logger_error.log: %v\n", fileErr)
|
||||
// if failed to open log file, print the error message to console
|
||||
fmt.Print(logMsg)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
// write the error message
|
||||
if _, writeErr := f.WriteString(logMsg); writeErr != nil {
|
||||
fmt.Printf("Failed to write to logger_error.log: %v\n", writeErr)
|
||||
// if failed to write to log file, print the error message to console
|
||||
fmt.Print(logMsg)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue