From d780c2a988df57f0ac69678fcd618052f702ad0b Mon Sep 17 00:00:00 2001 From: tinkle-community Date: Mon, 8 Dec 2025 02:13:58 +0800 Subject: [PATCH] refactor: simplify log format --- api/server.go | 96 ++++++++++++++++++++---------------------------- logger/logger.go | 51 +++++++++++++++++-------- 2 files changed, 75 insertions(+), 72 deletions(-) diff --git a/api/server.go b/api/server.go index c05670eb..29df97c4 100644 --- a/api/server.go +++ b/api/server.go @@ -348,22 +348,22 @@ func (s *Server) getTraderFromQuery(c *gin.Context) (*manager.TraderManager, str // AI trader management related structures type CreateTraderRequest struct { - Name string `json:"name" binding:"required"` - AIModelID string `json:"ai_model_id" binding:"required"` - ExchangeID string `json:"exchange_id" binding:"required"` - StrategyID string `json:"strategy_id"` // Strategy ID (new version) - InitialBalance float64 `json:"initial_balance"` - ScanIntervalMinutes int `json:"scan_interval_minutes"` - IsCrossMargin *bool `json:"is_cross_margin"` // Pointer type, nil means use default value true + Name string `json:"name" binding:"required"` + AIModelID string `json:"ai_model_id" binding:"required"` + ExchangeID string `json:"exchange_id" binding:"required"` + StrategyID string `json:"strategy_id"` // Strategy ID (new version) + InitialBalance float64 `json:"initial_balance"` + ScanIntervalMinutes int `json:"scan_interval_minutes"` + IsCrossMargin *bool `json:"is_cross_margin"` // Pointer type, nil means use default value true // The following fields are kept for backward compatibility, new version uses strategy config - BTCETHLeverage int `json:"btc_eth_leverage"` - AltcoinLeverage int `json:"altcoin_leverage"` - TradingSymbols string `json:"trading_symbols"` - CustomPrompt string `json:"custom_prompt"` - OverrideBasePrompt bool `json:"override_base_prompt"` - SystemPromptTemplate string `json:"system_prompt_template"` // System prompt template name - UseCoinPool bool `json:"use_coin_pool"` - UseOITop bool `json:"use_oi_top"` + BTCETHLeverage int `json:"btc_eth_leverage"` + AltcoinLeverage int `json:"altcoin_leverage"` + TradingSymbols string `json:"trading_symbols"` + CustomPrompt string `json:"custom_prompt"` + OverrideBasePrompt bool `json:"override_base_prompt"` + SystemPromptTemplate string `json:"system_prompt_template"` // System prompt template name + UseCoinPool bool `json:"use_coin_pool"` + UseOITop bool `json:"use_oi_top"` } type ModelConfig struct { @@ -381,8 +381,8 @@ type SafeModelConfig struct { Name string `json:"name"` Provider string `json:"provider"` Enabled bool `json:"enabled"` - CustomAPIURL string `json:"customApiUrl"` // Custom API URL (usually not sensitive) - CustomModelName string `json:"customModelName"` // Custom model name (not sensitive) + CustomAPIURL string `json:"customApiUrl"` // Custom API URL (usually not sensitive) + CustomModelName string `json:"customModelName"` // Custom model name (not sensitive) } type ExchangeConfig struct { @@ -403,8 +403,8 @@ type SafeExchangeConfig struct { Enabled bool `json:"enabled"` Testnet bool `json:"testnet,omitempty"` HyperliquidWalletAddr string `json:"hyperliquidWalletAddr"` // Hyperliquid wallet address (not sensitive) - AsterUser string `json:"asterUser"` // Aster username (not sensitive) - AsterSigner string `json:"asterSigner"` // Aster signer (not sensitive) + AsterUser string `json:"asterUser"` // Aster username (not sensitive) + AsterSigner string `json:"asterSigner"` // Aster signer (not sensitive) } type UpdateModelConfigRequest struct { @@ -584,8 +584,8 @@ func (s *Server) handleCreateTrader(c *gin.Context) { Name: req.Name, AIModelID: req.AIModelID, ExchangeID: req.ExchangeID, - StrategyID: req.StrategyID, // Associated strategy ID (new version) - InitialBalance: actualBalance, // Use actual queried balance + StrategyID: req.StrategyID, // Associated strategy ID (new version) + InitialBalance: actualBalance, // Use actual queried balance BTCETHLeverage: btcEthLeverage, AltcoinLeverage: altcoinLeverage, TradingSymbols: req.TradingSymbols, @@ -630,20 +630,20 @@ func (s *Server) handleCreateTrader(c *gin.Context) { // UpdateTraderRequest Update trader request type UpdateTraderRequest struct { - Name string `json:"name" binding:"required"` - AIModelID string `json:"ai_model_id" binding:"required"` - ExchangeID string `json:"exchange_id" binding:"required"` - StrategyID string `json:"strategy_id"` // Strategy ID (new version) - InitialBalance float64 `json:"initial_balance"` - ScanIntervalMinutes int `json:"scan_interval_minutes"` - IsCrossMargin *bool `json:"is_cross_margin"` + Name string `json:"name" binding:"required"` + AIModelID string `json:"ai_model_id" binding:"required"` + ExchangeID string `json:"exchange_id" binding:"required"` + StrategyID string `json:"strategy_id"` // Strategy ID (new version) + InitialBalance float64 `json:"initial_balance"` + ScanIntervalMinutes int `json:"scan_interval_minutes"` + IsCrossMargin *bool `json:"is_cross_margin"` // The following fields are kept for backward compatibility, new version uses strategy config - BTCETHLeverage int `json:"btc_eth_leverage"` - AltcoinLeverage int `json:"altcoin_leverage"` - TradingSymbols string `json:"trading_symbols"` - CustomPrompt string `json:"custom_prompt"` - OverrideBasePrompt bool `json:"override_base_prompt"` - SystemPromptTemplate string `json:"system_prompt_template"` + BTCETHLeverage int `json:"btc_eth_leverage"` + AltcoinLeverage int `json:"altcoin_leverage"` + TradingSymbols string `json:"trading_symbols"` + CustomPrompt string `json:"custom_prompt"` + OverrideBasePrompt bool `json:"override_base_prompt"` + SystemPromptTemplate string `json:"system_prompt_template"` } // handleUpdateTrader Update trader configuration @@ -974,11 +974,11 @@ func (s *Server) handleSyncBalance(c *gin.Context) { exchangeCfg.AsterSigner, exchangeCfg.AsterPrivateKey, ) - case "bybit": - tempTrader = trader.NewBybitTrader( - exchangeCfg.APIKey, - exchangeCfg.SecretKey, - ) + case "bybit": + tempTrader = trader.NewBybitTrader( + exchangeCfg.APIKey, + exchangeCfg.SecretKey, + ) default: c.JSON(http.StatusBadRequest, gin.H{"error": "Unsupported exchange type"}) return @@ -1271,23 +1271,6 @@ func (s *Server) handleGetExchangeConfigs(c *gin.Context) { } logger.Infof("✅ Found %d exchange configs", len(exchanges)) - // Debug: Output config details (masked) - for _, ex := range exchanges { - apiKeyMasked := "" - if len(ex.APIKey) > 8 { - apiKeyMasked = ex.APIKey[:8] + "..." - } - secretKeyMasked := "" - if len(ex.SecretKey) > 8 { - secretKeyMasked = ex.SecretKey[:8] + "..." - } - logger.Infof(" └─ Exchange: %s, APIKey: %s, SecretKey: %s", ex.ID, apiKeyMasked, secretKeyMasked) - } - - // Print complete JSON response for debugging - jsonData, _ := json.Marshal(exchanges) - logger.Infof("📤 Complete JSON response: %s", string(jsonData)) - // Convert to safe response structure, remove sensitive information safeExchanges := make([]SafeExchangeConfig, len(exchanges)) for i, exchange := range exchanges { @@ -1742,7 +1725,6 @@ func (s *Server) authMiddleware() gin.HandlerFunc { } } - // handleLogout Add current token to blacklist func (s *Server) handleLogout(c *gin.Context) { authHeader := c.GetHeader("Authorization") diff --git a/logger/logger.go b/logger/logger.go index 2e52a74f..1b2e71ca 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,7 +1,11 @@ package logger import ( + "fmt" "os" + "path/filepath" + "runtime" + "strings" "github.com/sirupsen/logrus" ) @@ -11,15 +15,40 @@ var ( Log *logrus.Logger ) +// compactFormatter is a custom formatter for cleaner log output +type compactFormatter struct { + logrus.TextFormatter +} + +func (f *compactFormatter) Format(entry *logrus.Entry) ([]byte, error) { + level := strings.ToUpper(entry.Level.String())[0:4] + + // Skip frames to find actual caller (skip logrus + our wrapper functions) + caller := "" + for i := 3; i < 10; i++ { + _, file, line, ok := runtime.Caller(i) + if !ok { + break + } + // Skip logrus internal and our logger.go + if !strings.Contains(file, "logrus") && !strings.HasSuffix(file, "logger/logger.go") { + // Get package name from path (e.g., "nofx/manager/trader_manager.go" -> "manager") + dir := filepath.Dir(file) + pkg := filepath.Base(dir) + caller = fmt.Sprintf("%s/%s:%d", pkg, filepath.Base(file), line) + break + } + } + + msg := fmt.Sprintf("[%s] %s %s\n", level, caller, entry.Message) + return []byte(msg), nil +} + func init() { // Auto-initialize default logger to ensure it works before Init is called Log = logrus.New() Log.SetLevel(logrus.InfoLevel) - Log.SetFormatter(&logrus.TextFormatter{ - FullTimestamp: true, - TimestampFormat: "2006-01-02 15:04:05", - ForceColors: true, - }) + Log.SetFormatter(&compactFormatter{}) Log.SetOutput(os.Stdout) } @@ -47,17 +76,9 @@ func Init(cfg *Config) error { } Log.SetLevel(level) - // Set formatter (always use colored text format) - Log.SetFormatter(&logrus.TextFormatter{ - FullTimestamp: true, - TimestampFormat: "2006-01-02 15:04:05", - ForceColors: true, - }) - - // Set output target (default stdout) + // Set compact formatter + Log.SetFormatter(&compactFormatter{}) Log.SetOutput(os.Stdout) - - // Enable caller location info Log.SetReportCaller(true) return nil