diff --git a/cmd/peerswaplnd/config.go b/cmd/peerswaplnd/config.go index d756f8e6..3a88f95c 100644 --- a/cmd/peerswaplnd/config.go +++ b/cmd/peerswaplnd/config.go @@ -44,6 +44,8 @@ type PeerSwapConfig struct { DataDir string `long:"datadir" description:"peerswap datadir"` LogLevel LogLevel `long:"loglevel" description:"loglevel (1=Info, 2=Debug)"` + LogRotation LogRotationConfig `group:"Log rotation" namespace:"logrotation"` + LndConfig *LndConfig `group:"Lnd Grpc config" namespace:"lnd"` ElementsConfig *OnchainConfig `group:"Elements Rpc Config" namespace:"elementsd"` LWKConfig *lwk.Conf @@ -75,6 +77,9 @@ func (p *PeerSwapConfig) String() string { } func (p *PeerSwapConfig) Validate() error { + if err := p.LogRotation.Validate(); err != nil { + return err + } if p.ElementsConfig.RpcHost != "" && p.ElementsConfig.LiquidSwaps != false { err := p.ElementsConfig.Validate() if err != nil { @@ -139,6 +144,28 @@ type LndConfig struct { MacaroonPath string `long:"macaroonpath" description:"path to the macaroon (admin.macaroon or custom baked one)"` } +type LogRotationConfig struct { + // In megabytes + MaxSize int `long:"maxsize" description:"maximum size in megabytes of the log file before rotation."` + MaxBackups int `long:"maxbackups" description:"maximum number of old log files to retain."` + // In days + MaxAge int `long:"maxage" description:"maximum number of days to retain old log files."` + Compress bool `long:"compress" description:"whether to compress log files using gzip"` +} + +func (l LogRotationConfig) Validate() error { + if l.MaxSize <= 0 { + return fmt.Errorf("logrotation.maxsize must be > 0, got %d", l.MaxSize) + } + if l.MaxBackups < 0 { + return fmt.Errorf("logrotation.maxbackups must be >= 0, got %d", l.MaxBackups) + } + if l.MaxAge < 0 { + return fmt.Errorf("logrotation.maxage must be >= 0, got %d", l.MaxAge) + } + return nil +} + func DefaultConfig() *PeerSwapConfig { return &PeerSwapConfig{ Host: DefaultPeerswapHost, @@ -154,6 +181,7 @@ func DefaultConfig() *PeerSwapConfig { BitcoinEnabled: DefaultBitcoinEnabled, ElementsConfig: defaultLiquidConfig(), LogLevel: DefaultLogLevel, + LogRotation: defaultLogRotationConfig(), } } @@ -170,6 +198,15 @@ func defaultLiquidConfig() *OnchainConfig { } } +func defaultLogRotationConfig() LogRotationConfig { + return LogRotationConfig{ + MaxSize: 10, + MaxBackups: 5, + MaxAge: 28, + Compress: true, + } +} + func LWKFromIniFileConfig(filePath string) (*lwk.Conf, error) { type LWK struct { SignerName string `long:"signername" description:"name of the signer"` diff --git a/cmd/peerswaplnd/config_test.go b/cmd/peerswaplnd/config_test.go index 1f0ac728..fc61570b 100644 --- a/cmd/peerswaplnd/config_test.go +++ b/cmd/peerswaplnd/config_test.go @@ -11,6 +11,77 @@ import ( "github.com/vulpemventures/go-elements/network" ) +func TestLogRotationConfigValidate(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + cfg peerswaplnd.LogRotationConfig + wantErr bool + }{ + { + name: "valid values", + cfg: peerswaplnd.LogRotationConfig{ + MaxSize: 10, + MaxBackups: 5, + MaxAge: 28, + Compress: true, + }, + wantErr: false, + }, + { + name: "maxsize zero", + cfg: peerswaplnd.LogRotationConfig{ + MaxSize: 0, + MaxBackups: 5, + MaxAge: 28, + }, + wantErr: true, + }, + { + name: "maxsize negative", + cfg: peerswaplnd.LogRotationConfig{ + MaxSize: -1, + MaxBackups: 5, + MaxAge: 28, + }, + wantErr: true, + }, + { + name: "maxbackups negative", + cfg: peerswaplnd.LogRotationConfig{ + MaxSize: 10, + MaxBackups: -1, + MaxAge: 28, + }, + wantErr: true, + }, + { + name: "maxage negative", + cfg: peerswaplnd.LogRotationConfig{ + MaxSize: 10, + MaxBackups: 5, + MaxAge: -1, + }, + wantErr: true, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := tt.cfg.Validate() + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + func TestLWKFromIniFileConfig(t *testing.T) { t.Parallel() t.Run("valid ini config", func(t *testing.T) { diff --git a/cmd/peerswaplnd/peerswapd/main.go b/cmd/peerswaplnd/peerswapd/main.go index 61032f60..6f5a2c3a 100644 --- a/cmd/peerswaplnd/peerswapd/main.go +++ b/cmd/peerswaplnd/peerswapd/main.go @@ -46,6 +46,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/encoding/protojson" + "gopkg.in/natefinch/lumberjack.v2" ) const ( @@ -92,11 +93,10 @@ func run() error { return err } - logger, closeFunc, err := NewLndLogger(cfg) + logger, err := NewLndLogger(cfg) if err != nil { return err } - defer closeFunc() log.SetLogger(logger) // make datadir @@ -597,23 +597,32 @@ type LndLogger struct { loglevel peerswaplnd.LogLevel } -func NewLndLogger(cfg *peerswaplnd.PeerSwapConfig) (*LndLogger, func() error, error) { - logFile, err := os.OpenFile(filepath.Join(cfg.DataDir, "log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) +func NewLndLogger(cfg *peerswaplnd.PeerSwapConfig) (*LndLogger, error) { + err := os.MkdirAll(cfg.DataDir, 0755) if err != nil { - return nil, nil, err + return nil, err } - w := io.MultiWriter(os.Stdout, logFile) + logFile := filepath.Join(cfg.DataDir, "log") + core_log.SetFlags(core_log.LstdFlags | core_log.LUTC) + + w := io.MultiWriter(os.Stdout, &lumberjack.Logger{ + Filename: logFile, + MaxSize: cfg.LogRotation.MaxSize, + MaxBackups: cfg.LogRotation.MaxBackups, + MaxAge: cfg.LogRotation.MaxAge, + Compress: cfg.LogRotation.Compress, + }) core_log.SetOutput(w) - return &LndLogger{loglevel: cfg.LogLevel}, logFile.Close, nil + return &LndLogger{loglevel: cfg.LogLevel}, nil } -func (l *LndLogger) Infof(format string, v ...interface{}) { +func (l *LndLogger) Infof(format string, v ...any) { core_log.Printf("[INFO] "+format, v...) } -func (l *LndLogger) Debugf(format string, v ...interface{}) { +func (l *LndLogger) Debugf(format string, v ...any) { if l.loglevel == peerswaplnd.LOGLEVEL_DEBUG { core_log.Printf("[DEBUG] "+format, v...) } diff --git a/go.mod b/go.mod index ec6b7c03..d4773218 100644 --- a/go.mod +++ b/go.mod @@ -137,7 +137,7 @@ require ( google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect gopkg.in/errgo.v1 v1.0.1 // indirect gopkg.in/macaroon-bakery.v2 v2.3.0 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect @@ -164,7 +164,6 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang-migrate/migrate/v4 v4.17.0 // indirect - github.com/golang/mock v1.6.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index f61194c1..2f3d51a5 100644 --- a/go.sum +++ b/go.sum @@ -38,7 +38,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= @@ -256,8 +255,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -951,7 +948,6 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= @@ -1060,8 +1056,8 @@ gopkg.in/macaroon-bakery.v2 v2.3.0/go.mod h1:/8YhtPARXeRzbpEPLmRB66+gQE8/pzBBkWw gopkg.in/macaroon.v2 v2.1.0 h1:HZcsjBCzq9t0eBPMKqTN/uSN6JOm78ZJ2INbqcBQOUI= gopkg.in/macaroon.v2 v2.1.0/go.mod h1:OUb+TQP/OP0WOerC2Jp/3CwhIKyIa9kQjuc7H24e6/o= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=