101 lines
1.9 KiB
Go
101 lines
1.9 KiB
Go
|
|
package proxy
|
||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
"sync"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
type accessLogSink struct {
|
||
|
|
path string
|
||
|
|
file *os.File
|
||
|
|
mu sync.Mutex
|
||
|
|
}
|
||
|
|
|
||
|
|
func newAccessLogSink(path string) *accessLogSink {
|
||
|
|
return &accessLogSink{path: path}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (l *accessLogSink) SetPath(path string) {
|
||
|
|
if l == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
l.mu.Lock()
|
||
|
|
defer l.mu.Unlock()
|
||
|
|
if l.path == path {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
l.path = path
|
||
|
|
if l.file != nil {
|
||
|
|
_ = l.file.Close()
|
||
|
|
l.file = nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (l *accessLogSink) Close() {
|
||
|
|
if l == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
l.mu.Lock()
|
||
|
|
defer l.mu.Unlock()
|
||
|
|
if l.file != nil {
|
||
|
|
_ = l.file.Close()
|
||
|
|
l.file = nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (l *accessLogSink) OnLogin(e Event) {
|
||
|
|
if l == nil || e.Miner == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
l.writeLine("CONNECT", e.Miner.IP(), e.Miner.User(), e.Miner.Agent(), 0, 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (l *accessLogSink) OnClose(e Event) {
|
||
|
|
if l == nil || e.Miner == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
l.writeLine("CLOSE", e.Miner.IP(), e.Miner.User(), "", e.Miner.RX(), e.Miner.TX())
|
||
|
|
}
|
||
|
|
|
||
|
|
func (l *accessLogSink) writeLine(kind, ip, user, agent string, rx, tx uint64) {
|
||
|
|
l.mu.Lock()
|
||
|
|
defer l.mu.Unlock()
|
||
|
|
if strings.TrimSpace(l.path) == "" {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if l.file == nil {
|
||
|
|
file, err := os.OpenFile(l.path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
|
||
|
|
if err != nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
l.file = file
|
||
|
|
}
|
||
|
|
var builder strings.Builder
|
||
|
|
builder.WriteString(time.Now().UTC().Format(time.RFC3339))
|
||
|
|
builder.WriteByte(' ')
|
||
|
|
builder.WriteString(kind)
|
||
|
|
builder.WriteString(" ")
|
||
|
|
builder.WriteString(ip)
|
||
|
|
builder.WriteString(" ")
|
||
|
|
builder.WriteString(user)
|
||
|
|
if agent != "" {
|
||
|
|
builder.WriteString(" ")
|
||
|
|
builder.WriteString(agent)
|
||
|
|
}
|
||
|
|
if rx > 0 || tx > 0 {
|
||
|
|
builder.WriteString(" rx=")
|
||
|
|
builder.WriteString(formatUint(rx))
|
||
|
|
builder.WriteString(" tx=")
|
||
|
|
builder.WriteString(formatUint(tx))
|
||
|
|
}
|
||
|
|
builder.WriteByte('\n')
|
||
|
|
_, _ = l.file.WriteString(builder.String())
|
||
|
|
}
|
||
|
|
|
||
|
|
func formatUint(value uint64) string {
|
||
|
|
return strconv.FormatUint(value, 10)
|
||
|
|
}
|