| package logger |
|
|
| import ( |
| "context" |
| "encoding/json" |
| "fmt" |
| "io" |
| "log" |
| "os" |
| "path/filepath" |
| "sync" |
| "time" |
|
|
| "github.com/QuantumNous/new-api/common" |
| "github.com/QuantumNous/new-api/setting/operation_setting" |
|
|
| "github.com/bytedance/gopkg/util/gopool" |
| "github.com/gin-gonic/gin" |
| ) |
|
|
| const ( |
| loggerINFO = "INFO" |
| loggerWarn = "WARN" |
| loggerError = "ERR" |
| loggerDebug = "DEBUG" |
| ) |
|
|
| const maxLogCount = 1000000 |
|
|
| var logCount int |
| var setupLogLock sync.Mutex |
| var setupLogWorking bool |
|
|
| func SetupLogger() { |
| defer func() { |
| setupLogWorking = false |
| }() |
| if *common.LogDir != "" { |
| ok := setupLogLock.TryLock() |
| if !ok { |
| log.Println("setup log is already working") |
| return |
| } |
| defer func() { |
| setupLogLock.Unlock() |
| }() |
| logPath := filepath.Join(*common.LogDir, fmt.Sprintf("oneapi-%s.log", time.Now().Format("20060102150405"))) |
| fd, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) |
| if err != nil { |
| log.Fatal("failed to open log file") |
| } |
| gin.DefaultWriter = io.MultiWriter(os.Stdout, fd) |
| gin.DefaultErrorWriter = io.MultiWriter(os.Stderr, fd) |
| } |
| } |
|
|
| func LogInfo(ctx context.Context, msg string) { |
| logHelper(ctx, loggerINFO, msg) |
| } |
|
|
| func LogWarn(ctx context.Context, msg string) { |
| logHelper(ctx, loggerWarn, msg) |
| } |
|
|
| func LogError(ctx context.Context, msg string) { |
| logHelper(ctx, loggerError, msg) |
| } |
|
|
| func LogDebug(ctx context.Context, msg string, args ...any) { |
| if common.DebugEnabled { |
| if len(args) > 0 { |
| msg = fmt.Sprintf(msg, args...) |
| } |
| logHelper(ctx, loggerDebug, msg) |
| } |
| } |
|
|
| func logHelper(ctx context.Context, level string, msg string) { |
| writer := gin.DefaultErrorWriter |
| if level == loggerINFO { |
| writer = gin.DefaultWriter |
| } |
| id := ctx.Value(common.RequestIdKey) |
| if id == nil { |
| id = "SYSTEM" |
| } |
| now := time.Now() |
| _, _ = fmt.Fprintf(writer, "[%s] %v | %s | %s \n", level, now.Format("2006/01/02 - 15:04:05"), id, msg) |
| logCount++ |
| if logCount > maxLogCount && !setupLogWorking { |
| logCount = 0 |
| setupLogWorking = true |
| gopool.Go(func() { |
| SetupLogger() |
| }) |
| } |
| } |
|
|
| func LogQuota(quota int) string { |
| |
| q := float64(quota) |
| switch operation_setting.GetQuotaDisplayType() { |
| case operation_setting.QuotaDisplayTypeCNY: |
| usd := q / common.QuotaPerUnit |
| cny := usd * operation_setting.USDExchangeRate |
| return fmt.Sprintf("¥%.6f 额度", cny) |
| case operation_setting.QuotaDisplayTypeCustom: |
| usd := q / common.QuotaPerUnit |
| rate := operation_setting.GetGeneralSetting().CustomCurrencyExchangeRate |
| symbol := operation_setting.GetGeneralSetting().CustomCurrencySymbol |
| if symbol == "" { |
| symbol = "¤" |
| } |
| if rate <= 0 { |
| rate = 1 |
| } |
| v := usd * rate |
| return fmt.Sprintf("%s%.6f 额度", symbol, v) |
| case operation_setting.QuotaDisplayTypeTokens: |
| return fmt.Sprintf("%d 点额度", quota) |
| default: |
| return fmt.Sprintf("$%.6f 额度", q/common.QuotaPerUnit) |
| } |
| } |
|
|
| func FormatQuota(quota int) string { |
| q := float64(quota) |
| switch operation_setting.GetQuotaDisplayType() { |
| case operation_setting.QuotaDisplayTypeCNY: |
| usd := q / common.QuotaPerUnit |
| cny := usd * operation_setting.USDExchangeRate |
| return fmt.Sprintf("¥%.6f", cny) |
| case operation_setting.QuotaDisplayTypeCustom: |
| usd := q / common.QuotaPerUnit |
| rate := operation_setting.GetGeneralSetting().CustomCurrencyExchangeRate |
| symbol := operation_setting.GetGeneralSetting().CustomCurrencySymbol |
| if symbol == "" { |
| symbol = "¤" |
| } |
| if rate <= 0 { |
| rate = 1 |
| } |
| v := usd * rate |
| return fmt.Sprintf("%s%.6f", symbol, v) |
| case operation_setting.QuotaDisplayTypeTokens: |
| return fmt.Sprintf("%d", quota) |
| default: |
| return fmt.Sprintf("$%.6f", q/common.QuotaPerUnit) |
| } |
| } |
|
|
| |
| func LogJson(ctx context.Context, msg string, obj any) { |
| jsonStr, err := json.Marshal(obj) |
| if err != nil { |
| LogError(ctx, fmt.Sprintf("json marshal failed: %s", err.Error())) |
| return |
| } |
| LogDebug(ctx, fmt.Sprintf("%s | %s", msg, string(jsonStr))) |
| } |
|
|