decred.org/dcrwallet/v3@v3.1.0/internal/loggers/loggers.go (about) 1 // Copyright (c) 2023 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package loggers 6 7 import ( 8 "fmt" 9 "os" 10 "path/filepath" 11 12 "github.com/decred/slog" 13 "github.com/jrick/logrotate/rotator" 14 ) 15 16 // logWriter implements an io.Writer that outputs to both standard output and 17 // the write-end pipe of an initialized log rotator. 18 type logWriter struct{} 19 20 func (logWriter) Write(p []byte) (n int, err error) { 21 os.Stdout.Write(p) 22 if logRotator != nil { 23 logRotator.Write(p) 24 } 25 return len(p), nil 26 } 27 28 // Loggers per subsystem. A single backend logger is created and all subsytem 29 // loggers created from it will write to the backend. When adding new 30 // subsystems, add the subsystem logger variable here and to the 31 // subsystemLoggers map. 32 // 33 // Loggers can not be used before the log rotator has been initialized with a 34 // log file. This must be performed early during application startup by calling 35 // initLogRotator. 36 var ( 37 // backendLog is the logging backend used to create all subsystem loggers. 38 // The backend must not be used before the log rotator has been initialized, 39 // or data races and/or nil pointer dereferences will occur. 40 backendLog = slog.NewBackend(logWriter{}) 41 42 // logRotator is one of the logging outputs. It should be closed on 43 // application shutdown. 44 logRotator *rotator.Rotator 45 46 MainLog = backendLog.Logger("DCRW") 47 LoaderLog = backendLog.Logger("LODR") 48 WalletLog = backendLog.Logger("WLLT") 49 TkbyLog = backendLog.Logger("TKBY") 50 SyncLog = backendLog.Logger("SYNC") 51 GrpcLog = backendLog.Logger("GRPC") 52 JsonrpcLog = backendLog.Logger("RPCS") 53 CmgrLog = backendLog.Logger("CMGR") 54 VspcLog = backendLog.Logger("VSPC") 55 ) 56 57 // InitLogRotator initializes the logging rotater to write logs to logFile and 58 // create roll files in the same directory. logSize is the size in KiB after 59 // which a log file will be rotated and compressed. 60 // 61 // This function must be called before the package-global log rotater variables 62 // are used. 63 func InitLogRotator(logFile string, logSize int64) { 64 logDir, _ := filepath.Split(logFile) 65 err := os.MkdirAll(logDir, 0700) 66 if err != nil { 67 fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err) 68 os.Exit(1) 69 } 70 r, err := rotator.New(logFile, logSize, false, 0) 71 if err != nil { 72 fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err) 73 os.Exit(1) 74 } 75 76 logRotator = r 77 } 78 79 // CloseLogRotator closes the log rotator, syncing all file writes, if the 80 // rotator was initialized. 81 func CloseLogRotator() error { 82 if logRotator == nil { 83 return nil 84 } 85 86 return logRotator.Close() 87 }