package proxy import ( "fmt" "os" "sync" "time" ) type appendLineLogger struct { path string mu sync.Mutex openFile *os.File closed bool } func newAppendLineLogger(path string) *appendLineLogger { return &appendLineLogger{path: path} } func (l *appendLineLogger) writeLine(line string) { if l == nil || l.path == "" { return } l.mu.Lock() defer l.mu.Unlock() if l.closed { return } if l.openFile == nil { file, errorValue := os.OpenFile(l.path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) if errorValue != nil { return } l.openFile = file } _, _ = l.openFile.WriteString(line) } func (l *appendLineLogger) setPath(path string) { if l == nil { return } l.mu.Lock() defer l.mu.Unlock() if l.path == path { return } if l.openFile != nil { _ = l.openFile.Close() l.openFile = nil } l.closed = false l.path = path } func (l *appendLineLogger) close() { if l == nil { return } l.mu.Lock() defer l.mu.Unlock() if l.closed { return } l.closed = true if l.openFile != nil { _ = l.openFile.Close() l.openFile = nil } } func subscribeAccessLog(events *EventBus, path string) *appendLineLogger { if events == nil || path == "" { return nil } logger := newAppendLineLogger(path) events.Subscribe(EventLogin, func(event Event) { if event.Miner == nil { return } logger.writeLine(fmt.Sprintf("%s CONNECT %s %s %s\n", time.Now().UTC().Format(time.RFC3339), event.Miner.IP(), event.Miner.User(), event.Miner.Agent(), )) }) events.Subscribe(EventClose, func(event Event) { if event.Miner == nil { return } logger.writeLine(fmt.Sprintf("%s CLOSE %s %s rx=%d tx=%d\n", time.Now().UTC().Format(time.RFC3339), event.Miner.IP(), event.Miner.User(), event.Miner.RX(), event.Miner.TX(), )) }) return logger } func subscribeShareLog(events *EventBus, path string) *appendLineLogger { if events == nil || path == "" { return nil } logger := newAppendLineLogger(path) events.Subscribe(EventAccept, func(event Event) { if event.Miner == nil { return } logger.writeLine(fmt.Sprintf("%s ACCEPT %s diff=%d latency=%dms\n", time.Now().UTC().Format(time.RFC3339), event.Miner.User(), event.Diff, event.Latency, )) }) events.Subscribe(EventReject, func(event Event) { if event.Miner == nil { return } logger.writeLine(fmt.Sprintf("%s REJECT %s reason=%q\n", time.Now().UTC().Format(time.RFC3339), event.Miner.User(), event.Error, )) }) return logger }