Skip to content

Commit 5841e95

Browse files
committed
log: Refactor to define proper loggers tree
*container.C is also now passed to module constructor allowing access to container logger for sublogger initialization. This in turn required some package movement to break import cycles.
1 parent 88e41ff commit 5841e95

106 files changed

Lines changed: 679 additions & 487 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cmd/maddy/maddy.conf

Lines changed: 0 additions & 13 deletions
This file was deleted.

config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func LogOutputOption(args []string) (log.Output, error) {
7171
}
7272
return log.NopOutput{}, nil
7373
default:
74-
// Log file paths are converted to absolute to make sure
74+
// log file paths are converted to absolute to make sure
7575
// we will be able to recreate them in right location
7676
// after changing working directory to the state dir.
7777
absPath, err := filepath.Abs(arg)
@@ -98,7 +98,7 @@ func LogOutputOption(args []string) (log.Output, error) {
9898
}
9999

100100
func defaultLogOutput() (interface{}, error) {
101-
return log.DefaultLogger.Out, nil
101+
return nil, nil
102102
}
103103

104104
func reinitLogging() {
@@ -115,7 +115,7 @@ func reinitLogging() {
115115
}
116116

117117
if err := out.Close(); err != nil {
118-
log.Println("Can't close logger:", err)
118+
log.Println("Can't close old logger:", err)
119119
}
120120

121121
log.DefaultLogger.Out = newOut

framework/config/module/modconfig.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,32 @@ import (
3636
"github.com/foxcpp/maddy/framework/container"
3737
"github.com/foxcpp/maddy/framework/log"
3838
"github.com/foxcpp/maddy/framework/module"
39+
"github.com/foxcpp/maddy/framework/module/modules"
3940
)
4041

4142
// createInlineModule is a helper function for config matchers that can create inline modules.
42-
func createInlineModule(preferredNamespace, modName string) (module.Module, error) {
43-
var newMod module.FuncNewModule
43+
func createInlineModule(c *container.C, preferredNamespace, modName string) (module.Module, error) {
44+
var newMod modules.FuncNewModule
4445
originalModName := modName
4546

4647
// First try to extend the name with preferred namespace unless the name
4748
// already contains it.
4849
if !strings.Contains(modName, ".") && preferredNamespace != "" {
4950
modName = preferredNamespace + "." + modName
50-
newMod = module.Get(modName)
51+
newMod = modules.Get(modName)
5152
}
5253

5354
// Then try global namespace for compatibility and complex modules.
5455
if newMod == nil {
55-
newMod = module.Get(originalModName)
56+
newMod = modules.Get(originalModName)
5657
}
5758

5859
// Bail if both failed.
5960
if newMod == nil {
6061
return nil, fmt.Errorf("unknown module: %s (namespace: %s)", originalModName, preferredNamespace)
6162
}
6263

63-
return newMod(modName, "")
64+
return newMod(c, modName, "")
6465
}
6566

6667
// configureInlineModule constructs "faked" config tree and passes it to module
@@ -73,7 +74,7 @@ func configureInlineModule(modObj module.Module, args []string, globals map[stri
7374
return err
7475
}
7576

76-
if li, ok := modObj.(module.LifetimeModule); ok {
77+
if li, ok := modObj.(container.LifetimeModule); ok {
7778
container.Global.Lifetime.Add(li)
7879
}
7980

@@ -115,7 +116,7 @@ func ModuleFromNode(preferredNamespace string, args []string, inlineCfg config.N
115116
log.Debugf("%s:%d: reference %s", inlineCfg.File, inlineCfg.Line, args[0])
116117
} else {
117118
log.Debugf("%s:%d: new module %s %v", inlineCfg.File, inlineCfg.Line, args[0], args[1:])
118-
modObj, err = createInlineModule(preferredNamespace, args[0])
119+
modObj, err = createInlineModule(container.Global, preferredNamespace, args[0])
119120
}
120121
if err != nil {
121122
return err

framework/container/container.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ package container
2020

2121
import (
2222
"github.com/foxcpp/maddy/framework/log"
23-
"github.com/foxcpp/maddy/framework/module"
2423
)
2524

2625
type GlobalConfig struct {
@@ -53,16 +52,17 @@ type GlobalConfig struct {
5352

5453
type C struct {
5554
Config GlobalConfig
56-
DefaultLogger log.Logger
57-
Modules *module.Registry
58-
Lifetime *module.LifetimeTracker
55+
DefaultLogger *log.Logger
56+
Modules *Registry
57+
Lifetime *LifetimeTracker
5958
}
6059

6160
func New() *C {
61+
rootLog := log.DefaultLogger.Sublogger("")
6262
return &C{
63-
DefaultLogger: log.DefaultLogger,
64-
Modules: module.NewRegistry(log.DefaultLogger.Sublogger("registry")),
65-
Lifetime: module.NewLifetime(log.DefaultLogger.Sublogger("lifetime")),
63+
DefaultLogger: rootLog,
64+
Modules: NewRegistry(rootLog.Sublogger("registry")),
65+
Lifetime: NewLifetime(rootLog.Sublogger("lifetime")),
6666
}
6767
}
6868

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,25 @@ You should have received a copy of the GNU General Public License
1616
along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19-
package module
19+
package container
2020

2121
import (
2222
"fmt"
2323

2424
"github.com/foxcpp/maddy/framework/log"
25+
"github.com/foxcpp/maddy/framework/module"
2526
)
2627

2728
// LifetimeModule is a stateful module that needs to have post-configuration
2829
// startup and graceful shutdown functionality.
2930
type LifetimeModule interface {
30-
Module
31+
module.Module
3132
Start() error
3233
Stop() error
3334
}
3435

3536
type ReloadModule interface {
36-
Module
37+
module.Module
3738
Reload() error
3839
}
3940

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ You should have received a copy of the GNU General Public License
1616
along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19-
package module
19+
package container
2020

2121
import (
2222
"errors"
2323

2424
"github.com/foxcpp/maddy/framework/log"
25+
"github.com/foxcpp/maddy/framework/module"
2526
)
2627

2728
var (
@@ -30,7 +31,7 @@ var (
3031
)
3132

3233
type registryEntry struct {
33-
Mod Module
34+
Mod module.Module
3435
LazyInit func() error
3536
}
3637

@@ -56,7 +57,7 @@ func NewRegistry(log *log.Logger) *Registry {
5657
//
5758
// lazyInit function will be called on first request to get the module from
5859
// registry.
59-
func (r *Registry) Register(mod Module, lazyInit func() error) error {
60+
func (r *Registry) Register(mod module.Module, lazyInit func() error) error {
6061
instName := mod.InstanceName()
6162
if instName == "" {
6263
panic("module with empty instance name cannot be added to the registry")
@@ -114,7 +115,7 @@ func (r *Registry) ensureInitialized(name string, entry *registryEntry) error {
114115
return nil
115116
}
116117

117-
func (r *Registry) Get(name string) (Module, error) {
118+
func (r *Registry) Get(name string) (module.Module, error) {
118119
if name == "" {
119120
panic("cannot get module with empty name")
120121
}
@@ -135,8 +136,8 @@ func (r *Registry) Get(name string) (Module, error) {
135136
return mod.Mod, nil
136137
}
137138

138-
func (r *Registry) NotInitialized() []Module {
139-
notinit := make([]Module, 0, len(r.instances)-len(r.initialized))
139+
func (r *Registry) NotInitialized() []module.Module {
140+
notinit := make([]module.Module, 0, len(r.instances)-len(r.initialized))
140141
for name, mod := range r.instances {
141142
if _, ok := r.initialized[name]; ok {
142143
continue

framework/log/log.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,7 @@ func (l *Logger) Zap() *zap.Logger {
5959
}
6060

6161
func (l *Logger) IsDebug() bool {
62-
if l.Parent == nil {
63-
return l.Debug
64-
}
65-
return l.Debug || l.Parent.IsDebug()
62+
return l.Debug || (l.Parent != nil && l.Parent.IsDebug())
6663
}
6764

6865
func (l *Logger) Debugf(format string, val ...interface{}) {
@@ -217,19 +214,30 @@ func (l *Logger) DebugWriter() io.Writer {
217214
return l2
218215
}
219216

217+
func (l *Logger) output() Output {
218+
if l.Out != nil {
219+
return l.Out
220+
}
221+
if l.Parent != nil {
222+
return l.Parent.output()
223+
}
224+
225+
if DefaultLogger.Out == nil {
226+
panic("DefaultLogger.Out is not set")
227+
}
228+
if l.Parent == nil && l != &DefaultLogger {
229+
DefaultLogger.Out.Write(time.Now(), true, "logger "+l.Name+" has no parent, this is a bug")
230+
}
231+
return DefaultLogger.Out
232+
}
233+
220234
func (l *Logger) log(debug bool, s string) {
221235
if l.Name != "" {
222236
s = l.Name + ": " + s
223237
}
224238

225-
if l.Out != nil {
226-
l.Out.Write(time.Now(), debug, s)
227-
return
228-
}
229-
if DefaultLogger.Out != nil {
230-
DefaultLogger.Out.Write(time.Now(), debug, s)
231-
return
232-
}
239+
out := l.output()
240+
out.Write(time.Now(), debug, s)
233241

234242
// Logging is disabled - do nothing.
235243
}
@@ -240,9 +248,7 @@ func (l *Logger) Sublogger(name string) *Logger {
240248
}
241249
return &Logger{
242250
Parent: l,
243-
Out: l.Out,
244251
Name: name,
245-
Debug: l.Debug,
246252
}
247253
}
248254

@@ -253,6 +259,12 @@ func (l *Logger) Sublogger(name string) *Logger {
253259
// however underlying log.Output may provide necessary serialization.
254260
var DefaultLogger = Logger{Out: WriterOutput(os.Stderr, false)}
255261

262+
// NopLogger is the logger that discards all messages written to it.
263+
var NopLogger = Logger{
264+
Parent: &DefaultLogger,
265+
Out: NopOutput{},
266+
}
267+
256268
func Debugf(format string, val ...interface{}) { DefaultLogger.Debugf(format, val...) }
257269
func Debugln(val ...interface{}) { DefaultLogger.Debugln(val...) }
258270
func Printf(format string, val ...interface{}) { DefaultLogger.Printf(format, val...) }

framework/module/module.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,25 +50,3 @@ type Module interface {
5050
// string if module instance is unnamed.
5151
InstanceName() string
5252
}
53-
54-
// FuncNewModule is function that creates new instance of module with specified name.
55-
//
56-
// Module.InstanceName() of the returned module object should return instName.
57-
// If module is defined inline, instName will be empty.
58-
//
59-
// Returned Module may additionally implement LifetimeModule.
60-
type FuncNewModule func(modName, instName string) (Module, error)
61-
62-
// FuncNewEndpoint is a function that creates new instance of endpoint
63-
// module.
64-
//
65-
// Compared to regular modules, endpoint module instances are:
66-
// - Not registered in the global registry.
67-
// - Can't be defined inline.
68-
// - Don't have an unique name
69-
// - All config arguments are always passed as an 'addrs' slice and not used as
70-
// names.
71-
//
72-
// As a consequence of having no per-instance name, InstanceName of the module
73-
// object always returns the same value as Name.
74-
type FuncNewEndpoint func(modName string, addrs []string) (LifetimeModule, error)
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
1616
along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19-
package module
19+
package modules
2020

2121
import (
2222
"context"
@@ -25,6 +25,8 @@ import (
2525
"github.com/emersion/go-smtp"
2626
"github.com/foxcpp/maddy/framework/buffer"
2727
"github.com/foxcpp/maddy/framework/config"
28+
"github.com/foxcpp/maddy/framework/container"
29+
"github.com/foxcpp/maddy/framework/module"
2830
)
2931

3032
// Dummy is a struct that implements PlainAuth and DeliveryTarget
@@ -58,7 +60,7 @@ func (d *Dummy) Configure(_ []string, _ *config.Map) error {
5860
return nil
5961
}
6062

61-
func (d *Dummy) StartDelivery(ctx context.Context, msgMeta *MsgMetadata, mailFrom string) (Delivery, error) {
63+
func (d *Dummy) StartDelivery(ctx context.Context, msgMeta *module.MsgMetadata, mailFrom string) (module.Delivery, error) {
6264
return dummyDelivery{}, nil
6365
}
6466

@@ -80,8 +82,6 @@ func (dd dummyDelivery) Commit(ctx context.Context) error {
8082
return nil
8183
}
8284

83-
func init() {
84-
Register("dummy", func(_, instName string) (Module, error) {
85-
return &Dummy{instName: instName}, nil
86-
})
85+
func NewDummy(_ *container.C, _, instName string) (module.Module, error) {
86+
return &Dummy{instName: instName}, nil
8787
}

0 commit comments

Comments
 (0)