208 lines
5.0 KiB
Go
208 lines
5.0 KiB
Go
package logger
|
||
|
||
import (
|
||
"fmt"
|
||
"io"
|
||
"log"
|
||
"os"
|
||
"path/filepath"
|
||
|
||
"git.toowon.com/jimmy/go-common/config"
|
||
)
|
||
|
||
// Logger 日志记录器
|
||
type Logger struct {
|
||
infoLog *log.Logger
|
||
errorLog *log.Logger
|
||
warnLog *log.Logger
|
||
debugLog *log.Logger
|
||
config *config.LoggerConfig
|
||
}
|
||
|
||
// NewLogger 创建日志记录器
|
||
func NewLogger(cfg *config.LoggerConfig) (*Logger, error) {
|
||
if cfg == nil {
|
||
// 使用默认配置
|
||
cfg = &config.LoggerConfig{
|
||
Level: "info",
|
||
Output: "stdout",
|
||
FilePath: "",
|
||
}
|
||
}
|
||
|
||
// 设置默认值
|
||
if cfg.Level == "" {
|
||
cfg.Level = "info"
|
||
}
|
||
if cfg.Output == "" {
|
||
cfg.Output = "stdout"
|
||
}
|
||
|
||
// 创建输出目标
|
||
var writers []io.Writer
|
||
switch cfg.Output {
|
||
case "stdout":
|
||
writers = append(writers, os.Stdout)
|
||
case "stderr":
|
||
writers = append(writers, os.Stderr)
|
||
case "file":
|
||
if cfg.FilePath == "" {
|
||
return nil, fmt.Errorf("file path is required when output is file")
|
||
}
|
||
// 确保目录存在
|
||
dir := filepath.Dir(cfg.FilePath)
|
||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||
return nil, fmt.Errorf("failed to create log directory: %w", err)
|
||
}
|
||
file, err := os.OpenFile(cfg.FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to open log file: %w", err)
|
||
}
|
||
writers = append(writers, file)
|
||
case "both":
|
||
writers = append(writers, os.Stdout)
|
||
if cfg.FilePath == "" {
|
||
return nil, fmt.Errorf("file path is required when output is both")
|
||
}
|
||
dir := filepath.Dir(cfg.FilePath)
|
||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||
return nil, fmt.Errorf("failed to create log directory: %w", err)
|
||
}
|
||
file, err := os.OpenFile(cfg.FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to open log file: %w", err)
|
||
}
|
||
writers = append(writers, file)
|
||
default:
|
||
return nil, fmt.Errorf("invalid output type: %s", cfg.Output)
|
||
}
|
||
|
||
// 创建多写入器
|
||
multiWriter := io.MultiWriter(writers...)
|
||
|
||
// 创建日志前缀
|
||
prefix := ""
|
||
if cfg.Prefix != "" {
|
||
prefix = cfg.Prefix + " "
|
||
}
|
||
|
||
// 创建日志记录器
|
||
logger := &Logger{
|
||
config: cfg,
|
||
}
|
||
|
||
// 根据日志级别创建不同的logger
|
||
flags := log.LstdFlags
|
||
if cfg.DisableTimestamp {
|
||
flags = 0
|
||
}
|
||
|
||
if cfg.Level == "debug" || cfg.Level == "info" || cfg.Level == "warn" || cfg.Level == "error" {
|
||
logger.infoLog = log.New(multiWriter, prefix+"[INFO] ", flags)
|
||
logger.warnLog = log.New(multiWriter, prefix+"[WARN] ", flags)
|
||
logger.errorLog = log.New(multiWriter, prefix+"[ERROR] ", flags)
|
||
if cfg.Level == "debug" {
|
||
logger.debugLog = log.New(multiWriter, prefix+"[DEBUG] ", flags)
|
||
}
|
||
}
|
||
|
||
return logger, nil
|
||
}
|
||
|
||
// Debug 记录调试日志
|
||
func (l *Logger) Debug(format string, v ...interface{}) {
|
||
if l.debugLog != nil {
|
||
l.debugLog.Printf(format, v...)
|
||
}
|
||
}
|
||
|
||
// Info 记录信息日志
|
||
func (l *Logger) Info(format string, v ...interface{}) {
|
||
if l.infoLog != nil {
|
||
l.infoLog.Printf(format, v...)
|
||
}
|
||
}
|
||
|
||
// Warn 记录警告日志
|
||
func (l *Logger) Warn(format string, v ...interface{}) {
|
||
if l.warnLog != nil {
|
||
l.warnLog.Printf(format, v...)
|
||
}
|
||
}
|
||
|
||
// Error 记录错误日志
|
||
func (l *Logger) Error(format string, v ...interface{}) {
|
||
if l.errorLog != nil {
|
||
l.errorLog.Printf(format, v...)
|
||
}
|
||
}
|
||
|
||
// Fatal 记录致命错误日志并退出程序
|
||
func (l *Logger) Fatal(format string, v ...interface{}) {
|
||
if l.errorLog != nil {
|
||
l.errorLog.Fatalf(format, v...)
|
||
} else {
|
||
log.Fatalf(format, v...)
|
||
}
|
||
}
|
||
|
||
// Panic 记录恐慌日志并触发panic
|
||
func (l *Logger) Panic(format string, v ...interface{}) {
|
||
if l.errorLog != nil {
|
||
l.errorLog.Panicf(format, v...)
|
||
} else {
|
||
log.Panicf(format, v...)
|
||
}
|
||
}
|
||
|
||
// WithFields 创建带字段的日志记录器(简化版,返回格式化字符串)
|
||
func (l *Logger) WithFields(fields map[string]interface{}) *Logger {
|
||
// 返回自身,实际使用时可以在format中包含fields
|
||
return l
|
||
}
|
||
|
||
// formatFields 格式化字段
|
||
func formatFields(fields map[string]interface{}) string {
|
||
if len(fields) == 0 {
|
||
return ""
|
||
}
|
||
result := ""
|
||
for k, v := range fields {
|
||
result += fmt.Sprintf("%s=%v ", k, v)
|
||
}
|
||
return result
|
||
}
|
||
|
||
// Debugf 记录调试日志(带字段)
|
||
func (l *Logger) Debugf(fields map[string]interface{}, format string, v ...interface{}) {
|
||
if l.debugLog != nil {
|
||
fieldStr := formatFields(fields)
|
||
l.debugLog.Printf(fieldStr+format, v...)
|
||
}
|
||
}
|
||
|
||
// Infof 记录信息日志(带字段)
|
||
func (l *Logger) Infof(fields map[string]interface{}, format string, v ...interface{}) {
|
||
if l.infoLog != nil {
|
||
fieldStr := formatFields(fields)
|
||
l.infoLog.Printf(fieldStr+format, v...)
|
||
}
|
||
}
|
||
|
||
// Warnf 记录警告日志(带字段)
|
||
func (l *Logger) Warnf(fields map[string]interface{}, format string, v ...interface{}) {
|
||
if l.warnLog != nil {
|
||
fieldStr := formatFields(fields)
|
||
l.warnLog.Printf(fieldStr+format, v...)
|
||
}
|
||
}
|
||
|
||
// Errorf 记录错误日志(带字段)
|
||
func (l *Logger) Errorf(fields map[string]interface{}, format string, v ...interface{}) {
|
||
if l.errorLog != nil {
|
||
fieldStr := formatFields(fields)
|
||
l.errorLog.Printf(fieldStr+format, v...)
|
||
}
|
||
}
|
||
|