148 lines
3.6 KiB
Go
148 lines
3.6 KiB
Go
package logger
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// LogLevel represents different log levels
|
|
type LogLevel int
|
|
|
|
const (
|
|
DEBUG LogLevel = iota
|
|
INFO
|
|
WARN
|
|
ERROR
|
|
OPPORTUNITY // Special level for opportunities
|
|
)
|
|
|
|
var logLevelNames = map[LogLevel]string{
|
|
DEBUG: "DEBUG",
|
|
INFO: "INFO",
|
|
WARN: "WARN",
|
|
ERROR: "ERROR",
|
|
OPPORTUNITY: "OPPORTUNITY",
|
|
}
|
|
|
|
// Logger represents a simple logger wrapper
|
|
type Logger struct {
|
|
logger *log.Logger
|
|
level LogLevel
|
|
levelName string
|
|
}
|
|
|
|
// parseLogLevel converts string log level to LogLevel enum
|
|
func parseLogLevel(level string) LogLevel {
|
|
switch strings.ToLower(level) {
|
|
case "debug":
|
|
return DEBUG
|
|
case "info":
|
|
return INFO
|
|
case "warn", "warning":
|
|
return WARN
|
|
case "error":
|
|
return ERROR
|
|
default:
|
|
return INFO // Default to INFO level
|
|
}
|
|
}
|
|
|
|
// New creates a new logger
|
|
func New(level string, format string, file string) *Logger {
|
|
// Determine output destination
|
|
var output *os.File
|
|
if file != "" {
|
|
f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
|
if err != nil {
|
|
log.Printf("Failed to create log file %s: %v, falling back to stdout", file, err)
|
|
output = os.Stdout
|
|
} else {
|
|
output = f
|
|
}
|
|
} else {
|
|
output = os.Stdout
|
|
}
|
|
|
|
// Create the logger with custom format
|
|
logger := log.New(output, "", 0) // No flags, we'll format ourselves
|
|
|
|
logLevel := parseLogLevel(level)
|
|
|
|
return &Logger{
|
|
logger: logger,
|
|
level: logLevel,
|
|
levelName: level,
|
|
}
|
|
}
|
|
|
|
// shouldLog determines if a message should be logged based on level
|
|
func (l *Logger) shouldLog(level LogLevel) bool {
|
|
return level >= l.level
|
|
}
|
|
|
|
// formatMessage formats a log message with timestamp and level
|
|
func (l *Logger) formatMessage(level LogLevel, v ...interface{}) string {
|
|
timestamp := time.Now().Format("2006/01/02 15:04:05")
|
|
levelName := logLevelNames[level]
|
|
message := fmt.Sprint(v...)
|
|
return fmt.Sprintf("%s [%s] %s", timestamp, levelName, message)
|
|
}
|
|
|
|
// Debug logs a debug message
|
|
func (l *Logger) Debug(v ...interface{}) {
|
|
if l.shouldLog(DEBUG) {
|
|
l.logger.Println(l.formatMessage(DEBUG, v...))
|
|
}
|
|
}
|
|
|
|
// Info logs an info message
|
|
func (l *Logger) Info(v ...interface{}) {
|
|
if l.shouldLog(INFO) {
|
|
l.logger.Println(l.formatMessage(INFO, v...))
|
|
}
|
|
}
|
|
|
|
// Warn logs a warning message
|
|
func (l *Logger) Warn(v ...interface{}) {
|
|
if l.shouldLog(WARN) {
|
|
l.logger.Println(l.formatMessage(WARN, v...))
|
|
}
|
|
}
|
|
|
|
// Error logs an error message
|
|
func (l *Logger) Error(v ...interface{}) {
|
|
if l.shouldLog(ERROR) {
|
|
l.logger.Println(l.formatMessage(ERROR, v...))
|
|
}
|
|
}
|
|
|
|
// Opportunity logs a found opportunity with detailed information
|
|
// This always logs regardless of level since opportunities are critical
|
|
func (l *Logger) Opportunity(txHash, from, to, method, protocol string, amountIn, amountOut, minOut, profitUSD float64, additionalData map[string]interface{}) {
|
|
timestamp := time.Now().Format("2006/01/02 15:04:05")
|
|
|
|
message := fmt.Sprintf(`%s [OPPORTUNITY] 🎯 ARBITRAGE OPPORTUNITY DETECTED
|
|
├── Transaction: %s
|
|
├── From: %s → To: %s
|
|
├── Method: %s (%s)
|
|
├── Amount In: %.6f tokens
|
|
├── Amount Out: %.6f tokens
|
|
├── Min Out: %.6f tokens
|
|
├── Estimated Profit: $%.2f USD
|
|
└── Additional Data: %v`,
|
|
timestamp, txHash, from, to, method, protocol,
|
|
amountIn, amountOut, minOut, profitUSD, additionalData)
|
|
|
|
l.logger.Println(message)
|
|
}
|
|
|
|
// OpportunitySimple logs a simple opportunity message (for backwards compatibility)
|
|
func (l *Logger) OpportunitySimple(v ...interface{}) {
|
|
timestamp := time.Now().Format("2006/01/02 15:04:05")
|
|
message := fmt.Sprint(v...)
|
|
l.logger.Printf("%s [OPPORTUNITY] %s", timestamp, message)
|
|
}
|