• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 11216766535

07 Oct 2024 01:37PM UTC coverage: 57.817% (-1.0%) from 58.817%
11216766535

Pull #9148

github

ProofOfKeags
lnwire: remove kickoff feerate from propose/commit
Pull Request #9148: DynComms [2/n]: lnwire: add authenticated wire messages for Dyn*

571 of 879 new or added lines in 16 files covered. (64.96%)

23253 existing lines in 251 files now uncovered.

99022 of 171268 relevant lines covered (57.82%)

38420.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

58.25
/build/log.go
1
package build
2

3
import (
4
        "fmt"
5
        "io"
6
        "strings"
7

8
        "github.com/btcsuite/btclog"
9
)
10

11
// LogType is an indicating the type of logging specified by the build flag.
12
type LogType byte
13

14
const (
15
        // LogTypeNone indicates no logging.
16
        LogTypeNone LogType = iota
17

18
        // LogTypeStdOut all logging is written directly to stdout.
19
        LogTypeStdOut
20

21
        // LogTypeDefault logs to both stdout and a given io.PipeWriter.
22
        LogTypeDefault
23
)
24

25
// String returns a human readable identifier for the logging type.
UNCOV
26
func (t LogType) String() string {
×
UNCOV
27
        switch t {
×
28
        case LogTypeNone:
×
29
                return "none"
×
30
        case LogTypeStdOut:
×
31
                return "stdout"
×
UNCOV
32
        case LogTypeDefault:
×
UNCOV
33
                return "default"
×
34
        default:
×
35
                return "unknown"
×
36
        }
37
}
38

39
// Declare the supported log file compressors as exported consts for easier use
40
// from other projects.
41
const (
42
        // Gzip is the default compressor.
43
        Gzip = "gzip"
44

45
        // Zstd is a modern compressor that compresses better than Gzip, in less
46
        // time.
47
        Zstd = "zstd"
48
)
49

50
// logCompressors maps the identifier for each supported compression algorithm
51
// to the extension used for the compressed log files.
52
var logCompressors = map[string]string{
53
        Gzip: "gz",
54
        Zstd: "zst",
55
}
56

57
// SuportedLogCompressor returns whether or not logCompressor is a supported
58
// compression algorithm for log files.
UNCOV
59
func SuportedLogCompressor(logCompressor string) bool {
×
UNCOV
60
        _, ok := logCompressors[logCompressor]
×
UNCOV
61

×
UNCOV
62
        return ok
×
UNCOV
63
}
×
64

65
// LogWriter is a stub type whose behavior can be changed using the build flags
66
// "stdlog" and "nolog". The default behavior is to write to both stdout and the
67
// RotatorPipe. Passing "stdlog" will cause it only to write to stdout, and
68
// "nolog" implements Write as a no-op.
69
type LogWriter struct {
70
        // RotatorPipe is the write-end pipe for writing to the log rotator.  It
71
        // is written to by the Write method of the LogWriter type. This only
72
        // needs to be set if neither the stdlog or nolog builds are set.
73
        RotatorPipe *io.PipeWriter
74
}
75

76
// NewSubLogger constructs a new subsystem log from the current LogWriter
77
// implementation. This is primarily intended for use with stdlog, as the actual
78
// writer is shared amongst all instantiations.
79
func NewSubLogger(subsystem string,
80
        genSubLogger func(string) btclog.Logger) btclog.Logger {
578✔
81

578✔
82
        switch Deployment {
578✔
83

84
        // For production builds, generate a new subsystem logger from the
85
        // primary log backend. If no function is provided, logging will be
86
        // disabled.
87
        case Production:
×
88
                if genSubLogger != nil {
×
89
                        return genSubLogger(subsystem)
×
90
                }
×
91

92
        // For development builds, we must handle two distinct types of logging:
93
        // unit tests and running the live daemon, e.g. for integration testing.
94
        case Development:
578✔
95
                switch LoggingType {
578✔
96

97
                // Default logging is used when running the standalone daemon.
98
                // We'll use the optional sublogger constructor to mimic the
99
                // production behavior.
UNCOV
100
                case LogTypeDefault:
×
UNCOV
101
                        if genSubLogger != nil {
×
UNCOV
102
                                return genSubLogger(subsystem)
×
UNCOV
103
                        }
×
104

105
                // Logging to stdout is used in unit tests. It is not important
106
                // that they share the same backend, since all output is written
107
                // to std out.
108
                case LogTypeStdOut:
×
109
                        backend := btclog.NewBackend(&LogWriter{})
×
110
                        logger := backend.Logger(subsystem)
×
111

×
112
                        // Set the logging level of the stdout logger to use the
×
113
                        // configured logging level specified by build flags.
×
114
                        level, _ := btclog.LevelFromString(LogLevel)
×
115
                        logger.SetLevel(level)
×
116

×
117
                        return logger
×
118
                }
119
        }
120

121
        // For any other configurations, we'll disable logging.
122
        return btclog.Disabled
578✔
123
}
124

125
// SubLoggers is a type that holds a map of subsystem loggers keyed by their
126
// subsystem name.
127
type SubLoggers map[string]btclog.Logger
128

129
// LeveledSubLogger provides the ability to retrieve the subsystem loggers of
130
// a logger and set their log levels individually or all at once.
131
type LeveledSubLogger interface {
132
        // SubLoggers returns the map of all registered subsystem loggers.
133
        SubLoggers() SubLoggers
134

135
        // SupportedSubsystems returns a slice of strings containing the names
136
        // of the supported subsystems. Should ideally correspond to the keys
137
        // of the subsystem logger map and be sorted.
138
        SupportedSubsystems() []string
139

140
        // SetLogLevel assigns an individual subsystem logger a new log level.
141
        SetLogLevel(subsystemID string, logLevel string)
142

143
        // SetLogLevels assigns all subsystem loggers the same new log level.
144
        SetLogLevels(logLevel string)
145
}
146

147
// ParseAndSetDebugLevels attempts to parse the specified debug level and set
148
// the levels accordingly on the given logger. An appropriate error is returned
149
// if anything is invalid.
150
func ParseAndSetDebugLevels(level string, logger LeveledSubLogger) error {
8✔
151
        // Split at the delimiter.
8✔
152
        levels := strings.Split(level, ",")
8✔
153
        if len(levels) == 0 {
8✔
154
                return fmt.Errorf("invalid log level: %v", level)
×
155
        }
×
156

157
        // If the first entry has no =, treat is as the log level for all
158
        // subsystems.
159
        globalLevel := levels[0]
8✔
160
        if !strings.Contains(globalLevel, "=") {
13✔
161
                // Validate debug log level.
5✔
162
                if !validLogLevel(globalLevel) {
7✔
163
                        str := "the specified debug level [%v] is invalid"
2✔
164
                        return fmt.Errorf(str, globalLevel)
2✔
165
                }
2✔
166

167
                // Change the logging level for all subsystems.
168
                logger.SetLogLevels(globalLevel)
3✔
169

3✔
170
                // The rest will target specific subsystems.
3✔
171
                levels = levels[1:]
3✔
172
        }
173

174
        // Go through the subsystem/level pairs while detecting issues and
175
        // update the log levels accordingly.
176
        for _, logLevelPair := range levels {
14✔
177
                if !strings.Contains(logLevelPair, "=") {
10✔
178
                        str := "the specified debug level contains an " +
2✔
179
                                "invalid subsystem/level pair [%v]"
2✔
180
                        return fmt.Errorf(str, logLevelPair)
2✔
181
                }
2✔
182

183
                // Extract the specified subsystem and log level.
184
                fields := strings.Split(logLevelPair, "=")
6✔
185
                if len(fields) != 2 {
6✔
186
                        str := "the specified debug level has an invalid " +
×
187
                                "format [%v] -- use format subsystem1=level1," +
×
188
                                "subsystem2=level2"
×
189
                        return fmt.Errorf(str, logLevelPair)
×
190
                }
×
191
                subsysID, logLevel := fields[0], fields[1]
6✔
192
                subLoggers := logger.SubLoggers()
6✔
193

6✔
194
                // Validate subsystem.
6✔
195
                if _, exists := subLoggers[subsysID]; !exists {
7✔
196
                        str := "the specified subsystem [%v] is invalid -- " +
1✔
197
                                "supported subsystems are %v"
1✔
198
                        return fmt.Errorf(
1✔
199
                                str, subsysID, logger.SupportedSubsystems(),
1✔
200
                        )
1✔
201
                }
1✔
202

203
                // Validate log level.
204
                if !validLogLevel(logLevel) {
5✔
205
                        str := "the specified debug level [%v] is invalid"
×
206
                        return fmt.Errorf(str, logLevel)
×
207
                }
×
208

209
                logger.SetLogLevel(subsysID, logLevel)
5✔
210
        }
211

212
        return nil
3✔
213
}
214

215
// validLogLevel returns whether or not logLevel is a valid debug log level.
216
func validLogLevel(logLevel string) bool {
10✔
217
        switch logLevel {
10✔
218
        case "trace":
1✔
219
                fallthrough
1✔
220
        case "debug":
5✔
221
                fallthrough
5✔
222
        case "info":
8✔
223
                fallthrough
8✔
224
        case "warn":
8✔
225
                fallthrough
8✔
226
        case "error":
8✔
227
                fallthrough
8✔
228
        case "critical":
8✔
229
                fallthrough
8✔
230
        case "off":
8✔
231
                return true
8✔
232
        }
233
        return false
2✔
234
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc