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

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

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

61.43
/build/sub_logger.go
1
package build
2

3
import (
4
        "fmt"
5
        "sort"
6
        "strings"
7
        "sync"
8

9
        "github.com/btcsuite/btclog/v2"
10
)
11

12
// SubLogCreator can be used to create a new logger for a particular subsystem.
13
type SubLogCreator interface {
14
        // Logger returns a new logger for a particular subsystem.
15
        Logger(subsystemTag string) btclog.Logger
16
}
17

18
// SubLoggerManager manages a set of subsystem loggers. Level updates will be
19
// applied to all the loggers managed by the manager.
20
type SubLoggerManager struct {
21
        genLogger SubLogCreator
22

23
        loggers SubLoggers
24
        mu      sync.Mutex
25
}
26

27
// A compile time check to ensure SubLoggerManager implements the
28
// LeveledSubLogger interface.
29
var _ LeveledSubLogger = (*SubLoggerManager)(nil)
30

31
// NewSubLoggerManager constructs a new SubLoggerManager.
32
func NewSubLoggerManager(handlers ...btclog.Handler) *SubLoggerManager {
3✔
33
        return &SubLoggerManager{
3✔
34
                loggers: make(SubLoggers),
3✔
35
                genLogger: newSubLogGenerator(
3✔
36
                        newHandlerSet(btclog.LevelInfo, handlers...),
3✔
37
                ),
3✔
38
        }
3✔
39
}
3✔
40

41
// GenSubLogger creates a new sub-logger and adds it to the set managed by the
42
// SubLoggerManager. A shutdown callback function is provided to be able to shut
43
// down in case of a critical error.
44
func (r *SubLoggerManager) GenSubLogger(subsystem string,
45
        shutdown func()) btclog.Logger {
3✔
46

3✔
47
        // Create a new logger with the given subsystem tag.
3✔
48
        logger := r.genLogger.Logger(subsystem)
3✔
49

3✔
50
        // Wrap the new logger in a Shutdown logger so that the shutdown
3✔
51
        // call back is called if a critical log is ever written via this new
3✔
52
        // logger.
3✔
53
        l := NewShutdownLogger(logger, shutdown)
3✔
54

3✔
55
        r.RegisterSubLogger(subsystem, l)
3✔
56

3✔
57
        return l
3✔
58
}
3✔
59

60
// RegisterSubLogger registers the given logger under the given subsystem name.
61
func (r *SubLoggerManager) RegisterSubLogger(subsystem string,
62
        logger btclog.Logger) {
3✔
63

3✔
64
        // Add the new logger to the set of loggers managed by the manager.
3✔
65
        r.mu.Lock()
3✔
66
        r.loggers[subsystem] = logger
3✔
67
        r.mu.Unlock()
3✔
68
}
3✔
69

70
// SubLoggers returns all currently registered subsystem loggers for this log
71
// writer.
72
//
73
// NOTE: This is part of the LeveledSubLogger interface.
74
func (r *SubLoggerManager) SubLoggers() SubLoggers {
×
75
        r.mu.Lock()
×
76
        defer r.mu.Unlock()
×
77

×
78
        return r.loggers
×
79
}
×
80

81
// SupportedSubsystems returns a sorted string slice of all keys in the
82
// subsystems map, corresponding to the names of the subsystems.
83
//
84
// NOTE: This is part of the LeveledSubLogger interface.
85
func (r *SubLoggerManager) SupportedSubsystems() []string {
3✔
86
        r.mu.Lock()
3✔
87
        defer r.mu.Unlock()
3✔
88

3✔
89
        // Convert the subsystemLoggers map keys to a string slice.
3✔
90
        subsystems := make([]string, 0, len(r.loggers))
3✔
91
        for subsysID := range r.loggers {
6✔
92
                subsystems = append(subsystems, subsysID)
3✔
93
        }
3✔
94

95
        // Sort the subsystems for stable display.
96
        sort.Strings(subsystems)
3✔
97

3✔
98
        return subsystems
3✔
99
}
100

101
// SetLogLevel sets the logging level for provided subsystem. Invalid
102
// subsystems are ignored. Uninitialized subsystems are dynamically created as
103
// needed.
104
//
105
// NOTE: This is part of the LeveledSubLogger interface.
106
func (r *SubLoggerManager) SetLogLevel(subsystemID string, logLevel string) {
×
107
        r.mu.Lock()
×
108
        defer r.mu.Unlock()
×
109

×
110
        r.setLogLevelUnsafe(subsystemID, logLevel)
×
111
}
×
112

113
// setLogLevelUnsafe sets the logging level for provided subsystem. Invalid
114
// subsystems are ignored. Uninitialized subsystems are dynamically created as
115
// needed.
116
//
117
// NOTE: the SubLoggerManager mutex must be held before calling this method.
118
func (r *SubLoggerManager) setLogLevelUnsafe(subsystemID string,
119
        logLevel string) {
3✔
120

3✔
121
        // Ignore invalid subsystems.
3✔
122
        logger, ok := r.loggers[subsystemID]
3✔
123
        if !ok {
3✔
124
                return
×
125
        }
×
126

127
        // Defaults to info if the log level is invalid.
128
        level, _ := btclog.LevelFromString(logLevel)
3✔
129

3✔
130
        logger.SetLevel(level)
3✔
131
}
132

133
// SetLogLevels sets the log level for all subsystem loggers to the passed
134
// level. It also dynamically creates the subsystem loggers as needed, so it
135
// can be used to initialize the logging system.
136
//
137
// NOTE: This is part of the LeveledSubLogger interface.
138
func (r *SubLoggerManager) SetLogLevels(logLevel string) {
3✔
139
        r.mu.Lock()
3✔
140
        defer r.mu.Unlock()
3✔
141

3✔
142
        // Configure all sub-systems with the new logging level. Dynamically
3✔
143
        // create loggers as needed.
3✔
144
        for subsystemID := range r.loggers {
6✔
145
                r.setLogLevelUnsafe(subsystemID, logLevel)
3✔
146
        }
3✔
147
}
148

149
// SubLoggers is a type that holds a map of subsystem loggers keyed by their
150
// subsystem name.
151
type SubLoggers map[string]btclog.Logger
152

153
// LeveledSubLogger provides the ability to retrieve the subsystem loggers of
154
// a logger and set their log levels individually or all at once.
155
type LeveledSubLogger interface {
156
        // SubLoggers returns the map of all registered subsystem loggers.
157
        SubLoggers() SubLoggers
158

159
        // SupportedSubsystems returns a slice of strings containing the names
160
        // of the supported subsystems. Should ideally correspond to the keys
161
        // of the subsystem logger map and be sorted.
162
        SupportedSubsystems() []string
163

164
        // SetLogLevel assigns an individual subsystem logger a new log level.
165
        SetLogLevel(subsystemID string, logLevel string)
166

167
        // SetLogLevels assigns all subsystem loggers the same new log level.
168
        SetLogLevels(logLevel string)
169
}
170

171
// ParseAndSetDebugLevels attempts to parse the specified debug level and set
172
// the levels accordingly on the given logger. An appropriate error is returned
173
// if anything is invalid.
174
func ParseAndSetDebugLevels(level string, logger LeveledSubLogger) error {
3✔
175
        // Split at the delimiter.
3✔
176
        levels := strings.Split(level, ",")
3✔
177
        if len(levels) == 0 {
3✔
178
                return fmt.Errorf("invalid log level: %v", level)
×
179
        }
×
180

181
        // If the first entry has no =, treat is as the log level for all
182
        // subsystems.
183
        globalLevel := levels[0]
3✔
184
        if !strings.Contains(globalLevel, "=") {
6✔
185
                // Validate debug log level.
3✔
186
                if !validLogLevel(globalLevel) {
3✔
UNCOV
187
                        str := "the specified debug level [%v] is invalid"
×
UNCOV
188

×
UNCOV
189
                        return fmt.Errorf(str, globalLevel)
×
UNCOV
190
                }
×
191

192
                // Change the logging level for all subsystems.
193
                logger.SetLogLevels(globalLevel)
3✔
194

3✔
195
                // The rest will target specific subsystems.
3✔
196
                levels = levels[1:]
3✔
197
        }
198

199
        // Go through the subsystem/level pairs while detecting issues and
200
        // update the log levels accordingly.
201
        for _, logLevelPair := range levels {
3✔
UNCOV
202
                if !strings.Contains(logLevelPair, "=") {
×
UNCOV
203
                        str := "the specified debug level contains an " +
×
UNCOV
204
                                "invalid subsystem/level pair [%v]"
×
UNCOV
205

×
UNCOV
206
                        return fmt.Errorf(str, logLevelPair)
×
UNCOV
207
                }
×
208

209
                // Extract the specified subsystem and log level.
UNCOV
210
                fields := strings.Split(logLevelPair, "=")
×
UNCOV
211
                if len(fields) != 2 {
×
212
                        str := "the specified debug level has an invalid " +
×
213
                                "format [%v] -- use format subsystem1=level1," +
×
214
                                "subsystem2=level2"
×
215

×
216
                        return fmt.Errorf(str, logLevelPair)
×
217
                }
×
UNCOV
218
                subsysID, logLevel := fields[0], fields[1]
×
UNCOV
219
                subLoggers := logger.SubLoggers()
×
UNCOV
220

×
UNCOV
221
                // Validate subsystem.
×
UNCOV
222
                if _, exists := subLoggers[subsysID]; !exists {
×
UNCOV
223
                        str := "the specified subsystem [%v] is invalid -- " +
×
UNCOV
224
                                "supported subsystems are %v"
×
UNCOV
225

×
UNCOV
226
                        return fmt.Errorf(
×
UNCOV
227
                                str, subsysID, logger.SupportedSubsystems(),
×
UNCOV
228
                        )
×
UNCOV
229
                }
×
230

231
                // Validate log level.
UNCOV
232
                if !validLogLevel(logLevel) {
×
233
                        str := "the specified debug level [%v] is invalid"
×
234
                        return fmt.Errorf(str, logLevel)
×
235
                }
×
236

UNCOV
237
                logger.SetLogLevel(subsysID, logLevel)
×
238
        }
239

240
        return nil
3✔
241
}
242

243
// validLogLevel returns whether or not logLevel is a valid debug log level.
244
func validLogLevel(logLevel string) bool {
3✔
245
        switch logLevel {
3✔
UNCOV
246
        case "trace":
×
UNCOV
247
                fallthrough
×
248
        case "debug":
3✔
249
                fallthrough
3✔
250
        case "info":
3✔
251
                fallthrough
3✔
252
        case "warn":
3✔
253
                fallthrough
3✔
254
        case "error":
3✔
255
                fallthrough
3✔
256
        case "critical":
3✔
257
                fallthrough
3✔
258
        case "off":
3✔
259
                return true
3✔
260
        }
261

UNCOV
262
        return false
×
263
}
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