Skip to content

Commit 9e5c66c

Browse files
authored
Merge pull request #99 from guggero/persistent-logger
multi: add persistent logger
2 parents 71eb1dd + df08893 commit 9e5c66c

21 files changed

+217
-139
lines changed

.golangci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ linters:
3838
# the linter.
3939
- prealloc
4040

41+
# Init functions are used by loggers throughout the codebase.
42+
- gochecknoinits
43+
4144
issues:
4245
# Only show newly introduced problems.
4346
new-from-rev: 36838cf7f464cf73b0201798063b2caffeae4250

client.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func (s *Client) Run(ctx context.Context,
192192
if err != nil {
193193
return fmt.Errorf("GetInfo error: %v", err)
194194
}
195-
logger.Infof("Connected to lnd node %v with pubkey %v",
195+
log.Infof("Connected to lnd node %v with pubkey %v",
196196
info.Alias, hex.EncodeToString(info.IdentityPubkey[:]),
197197
)
198198

@@ -235,22 +235,22 @@ func (s *Client) Run(ctx context.Context,
235235
}
236236

237237
if err != nil {
238-
logger.Errorf("Swap client terminating: %v", err)
238+
log.Errorf("Swap client terminating: %v", err)
239239
} else {
240-
logger.Info("Swap client terminating")
240+
log.Info("Swap client terminating")
241241
}
242242

243243
// Cancel all remaining active goroutines.
244244
mainCancel()
245245

246246
// Wait for all to finish.
247-
logger.Debug("Wait for executor to finish")
247+
log.Debug("Wait for executor to finish")
248248
s.executor.waitFinished()
249249

250-
logger.Debug("Wait for goroutines to finish")
250+
log.Debug("Wait for goroutines to finish")
251251
s.wg.Wait()
252252

253-
logger.Info("Swap client terminated")
253+
log.Info("Swap client terminated")
254254

255255
return err
256256
}
@@ -270,7 +270,7 @@ func (s *Client) resumeSwaps(ctx context.Context,
270270
}
271271
swap, err := resumeLoopOutSwap(ctx, swapCfg, pend)
272272
if err != nil {
273-
logger.Errorf("resuming loop out swap: %v", err)
273+
log.Errorf("resuming loop out swap: %v", err)
274274
continue
275275
}
276276

@@ -283,7 +283,7 @@ func (s *Client) resumeSwaps(ctx context.Context,
283283
}
284284
swap, err := resumeLoopInSwap(ctx, swapCfg, pend)
285285
if err != nil {
286-
logger.Errorf("resuming loop in swap: %v", err)
286+
log.Errorf("resuming loop in swap: %v", err)
287287
continue
288288
}
289289

@@ -303,7 +303,7 @@ func (s *Client) resumeSwaps(ctx context.Context,
303303
func (s *Client) LoopOut(globalCtx context.Context,
304304
request *OutRequest) (*lntypes.Hash, btcutil.Address, error) {
305305

306-
logger.Infof("LoopOut %v to %v (channel: %v)",
306+
log.Infof("LoopOut %v to %v (channel: %v)",
307307
request.Amount, request.DestAddr,
308308
request.LoopOutChannel,
309309
)
@@ -358,7 +358,7 @@ func (s *Client) LoopOutQuote(ctx context.Context,
358358
return nil, err
359359
}
360360

361-
logger.Infof("Offchain swap destination: %x", quote.SwapPaymentDest)
361+
log.Infof("Offchain swap destination: %x", quote.SwapPaymentDest)
362362

363363
swapFee := quote.SwapFee
364364

@@ -418,7 +418,7 @@ func (s *Client) waitForInitialized(ctx context.Context) error {
418418
func (s *Client) LoopIn(globalCtx context.Context,
419419
request *LoopInRequest) (*lntypes.Hash, btcutil.Address, error) {
420420

421-
logger.Infof("Loop in %v (channel: %v)",
421+
log.Infof("Loop in %v (channel: %v)",
422422
request.Amount,
423423
request.LoopInChannel,
424424
)

cmd/loopd/config.go

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
package main
22

3+
import (
4+
"path/filepath"
5+
6+
"github.com/btcsuite/btcutil"
7+
)
8+
9+
var (
10+
loopDirBase = btcutil.AppDataDir("loop", false)
11+
12+
defaultLogLevel = "info"
13+
defaultLogDirname = "logs"
14+
defaultLogFilename = "loopd.log"
15+
defaultLogDir = filepath.Join(loopDirBase, defaultLogDirname)
16+
17+
defaultMaxLogFiles = 3
18+
defaultMaxLogFileSize = 10
19+
)
20+
321
type lndConfig struct {
422
Host string `long:"host" description:"lnd instance rpc address"`
523
MacaroonDir string `long:"macaroondir" description:"Path to the directory containing all the required lnd macaroons"`
@@ -16,6 +34,12 @@ type config struct {
1634
RPCListen string `long:"rpclisten" description:"Address to listen on for gRPC clients"`
1735
RESTListen string `long:"restlisten" description:"Address to listen on for REST clients"`
1836

37+
LogDir string `long:"logdir" description:"Directory to log output."`
38+
MaxLogFiles int `long:"maxlogfiles" description:"Maximum logfiles to keep (0 for no rotation)"`
39+
MaxLogFileSize int `long:"maxlogfilesize" description:"Maximum logfile size in MB"`
40+
41+
DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"`
42+
1943
Lnd *lndConfig `group:"lnd" namespace:"lnd"`
2044

2145
View viewParameters `command:"view" alias:"v" description:"View all swaps in the database. This command can only be executed when loopd is not running."`
@@ -27,10 +51,14 @@ const (
2751
)
2852

2953
var defaultConfig = config{
30-
Network: "mainnet",
31-
RPCListen: "localhost:11010",
32-
RESTListen: "localhost:8081",
33-
Insecure: false,
54+
Network: "mainnet",
55+
RPCListen: "localhost:11010",
56+
RESTListen: "localhost:8081",
57+
Insecure: false,
58+
LogDir: defaultLogDir,
59+
MaxLogFiles: defaultMaxLogFiles,
60+
MaxLogFileSize: defaultMaxLogFileSize,
61+
DebugLevel: defaultLogLevel,
3462
Lnd: &lndConfig{
3563
Host: "localhost:10009",
3664
},

cmd/loopd/daemon.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func daemon(config *config) error {
4040
}
4141
}
4242

43-
logger.Infof("Swap server address: %v", config.SwapServer)
43+
log.Infof("Swap server address: %v", config.SwapServer)
4444

4545
// Create an instance of the loop client library.
4646
swapClient, cleanup, err := getClient(
@@ -73,7 +73,7 @@ func daemon(config *config) error {
7373
looprpc.RegisterSwapClientServer(grpcServer, &server)
7474

7575
// Next, start the gRPC server listening for HTTP/2 connections.
76-
logger.Infof("Starting gRPC listener")
76+
log.Infof("Starting gRPC listener")
7777
grpcListener, err := net.Listen("tcp", config.RPCListen)
7878
if err != nil {
7979
return fmt.Errorf("RPC server unable to listen on %s",
@@ -95,7 +95,7 @@ func daemon(config *config) error {
9595
return err
9696
}
9797

98-
logger.Infof("Starting REST proxy listener")
98+
log.Infof("Starting REST proxy listener")
9999
restListener, err := net.Listen("tcp", config.RESTListen)
100100
if err != nil {
101101
return fmt.Errorf("REST proxy unable to listen on %s",
@@ -115,14 +115,14 @@ func daemon(config *config) error {
115115
go func() {
116116
defer wg.Done()
117117

118-
logger.Infof("Starting swap client")
118+
log.Infof("Starting swap client")
119119
err := swapClient.Run(mainCtx, statusChan)
120120
if err != nil {
121-
logger.Error(err)
121+
log.Error(err)
122122
}
123-
logger.Infof("Swap client stopped")
123+
log.Infof("Swap client stopped")
124124

125-
logger.Infof("Stopping gRPC server")
125+
log.Infof("Stopping gRPC server")
126126
grpcServer.Stop()
127127

128128
cancel()
@@ -133,7 +133,7 @@ func daemon(config *config) error {
133133
go func() {
134134
defer wg.Done()
135135

136-
logger.Infof("Waiting for updates")
136+
log.Infof("Waiting for updates")
137137
for {
138138
select {
139139
case swap := <-statusChan:
@@ -160,12 +160,12 @@ func daemon(config *config) error {
160160
go func() {
161161
defer wg.Done()
162162

163-
logger.Infof("RPC server listening on %s", grpcListener.Addr())
164-
logger.Infof("REST proxy listening on %s", restListener.Addr())
163+
log.Infof("RPC server listening on %s", grpcListener.Addr())
164+
log.Infof("REST proxy listening on %s", restListener.Addr())
165165

166166
err = grpcServer.Serve(grpcListener)
167167
if err != nil {
168-
logger.Error(err)
168+
log.Error(err)
169169
}
170170
}()
171171

@@ -175,7 +175,7 @@ func daemon(config *config) error {
175175
// Run until the users terminates loopd or an error occurred.
176176
select {
177177
case <-interruptChannel:
178-
logger.Infof("Received SIGINT (Ctrl+C).")
178+
log.Infof("Received SIGINT (Ctrl+C).")
179179

180180
// TODO: Remove debug code.
181181
// Debug code to dump goroutines on hanging exit.

cmd/loopd/log.go

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
11
package main
22

33
import (
4-
"os"
5-
64
"github.com/btcsuite/btclog"
5+
"github.com/lightninglabs/loop"
6+
"github.com/lightninglabs/loop/lndclient"
7+
"github.com/lightninglabs/loop/loopdb"
8+
"github.com/lightningnetwork/lnd/build"
79
)
810

9-
// log is a logger that is initialized with no output filters. This means the
10-
// package will not perform any logging by default until the caller requests
11-
// it.
1211
var (
13-
backendLog = btclog.NewBackend(logWriter{})
14-
logger = backendLog.Logger("LOOPD")
12+
logWriter = build.NewRotatingLogWriter()
13+
14+
log = build.NewSubLogger("LOOPD", logWriter.GenSubLogger)
1515
)
1616

17-
// logWriter implements an io.Writer that outputs to both standard output and
18-
// the write-end pipe of an initialized log rotator.
19-
type logWriter struct{}
17+
func init() {
18+
setSubLogger("LOOPD", log, nil)
19+
addSubLogger("LOOP", loop.UseLogger)
20+
addSubLogger("LNDC", lndclient.UseLogger)
21+
addSubLogger("STORE", loopdb.UseLogger)
22+
}
23+
24+
// addSubLogger is a helper method to conveniently create and register the
25+
// logger of a sub system.
26+
func addSubLogger(subsystem string, useLogger func(btclog.Logger)) {
27+
logger := build.NewSubLogger(subsystem, logWriter.GenSubLogger)
28+
setSubLogger(subsystem, logger, useLogger)
29+
}
30+
31+
// setSubLogger is a helper method to conveniently register the logger of a sub
32+
// system.
33+
func setSubLogger(subsystem string, logger btclog.Logger,
34+
useLogger func(btclog.Logger)) {
2035

21-
func (logWriter) Write(p []byte) (n int, err error) {
22-
os.Stdout.Write(p)
23-
return len(p), nil
36+
logWriter.RegisterSubLogger(subsystem, logger)
37+
if useLogger != nil {
38+
useLogger(logger)
39+
}
2440
}

cmd/loopd/main.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import (
77
"strings"
88
"sync"
99

10-
flags "github.com/jessevdk/go-flags"
11-
12-
"github.com/btcsuite/btcutil"
10+
"github.com/jessevdk/go-flags"
1311
"github.com/lightninglabs/loop"
12+
"github.com/lightningnetwork/lnd/build"
1413
"github.com/lightningnetwork/lnd/lntypes"
1514
)
1615

@@ -19,7 +18,6 @@ const (
1918
)
2019

2120
var (
22-
loopDirBase = btcutil.AppDataDir("loop", false)
2321
defaultConfigFilename = "loopd.conf"
2422

2523
swaps = make(map[lntypes.Hash]loop.SwapInfo)
@@ -81,8 +79,32 @@ func start() error {
8179
os.Exit(0)
8280
}
8381

82+
// Special show command to list supported subsystems and exit.
83+
if config.DebugLevel == "show" {
84+
fmt.Printf("Supported subsystems: %v\n",
85+
logWriter.SupportedSubsystems())
86+
os.Exit(0)
87+
}
88+
89+
// Append the network type to the log directory so it is
90+
// "namespaced" per network in the same fashion as the data directory.
91+
config.LogDir = filepath.Join(config.LogDir, config.Network)
92+
93+
// Initialize logging at the default logging level.
94+
err = logWriter.InitLogRotator(
95+
filepath.Join(config.LogDir, defaultLogFilename),
96+
config.MaxLogFileSize, config.MaxLogFiles,
97+
)
98+
if err != nil {
99+
return err
100+
}
101+
err = build.ParseAndSetDebugLevels(config.DebugLevel, logWriter)
102+
if err != nil {
103+
return err
104+
}
105+
84106
// Print the version before executing either primary directive.
85-
logger.Infof("Version: %v", loop.Version())
107+
log.Infof("Version: %v", loop.Version())
86108

87109
// Execute command.
88110
if parser.Active == nil {

0 commit comments

Comments
 (0)