github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/logger/logger.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package logger 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 "github.com/juju/names/v5" 10 "github.com/juju/worker/v3" 11 12 "github.com/juju/juju/core/watcher" 13 "github.com/juju/juju/state/mgo" 14 ) 15 16 // LoggerAPI represents the API calls the logger makes. 17 type LoggerAPI interface { 18 LoggingConfig(agentTag names.Tag) (string, error) 19 WatchLoggingConfig(agentTag names.Tag) (watcher.NotifyWatcher, error) 20 } 21 22 // WorkerConfig contains the information required for the Logger worker 23 // to operate. 24 type WorkerConfig struct { 25 Context *loggo.Context 26 API LoggerAPI 27 Tag names.Tag 28 Logger Logger 29 Override string 30 31 Callback func(string) error 32 } 33 34 // Validate ensures all the necessary fields have values. 35 func (c *WorkerConfig) Validate() error { 36 if c.Context == nil { 37 return errors.NotValidf("missing logging context") 38 } 39 if c.API == nil { 40 return errors.NotValidf("missing api") 41 } 42 if c.Logger == nil { 43 return errors.NotValidf("missing logger") 44 } 45 return nil 46 } 47 48 // loggerWorker is responsible for updating the loggo configuration when the 49 // environment watcher tells the agent that the value has changed. 50 type loggerWorker struct { 51 config WorkerConfig 52 lastConfig string 53 } 54 55 // NewLogger returns a worker.Worker that uses the notify watcher returned 56 // from the setup. 57 func NewLogger(config WorkerConfig) (worker.Worker, error) { 58 if err := config.Validate(); err != nil { 59 return nil, errors.Trace(err) 60 } 61 logger := &loggerWorker{ 62 config: config, 63 lastConfig: config.Context.Config().String(), 64 } 65 config.Logger.Debugf("initial log config: %q", logger.lastConfig) 66 67 w, err := watcher.NewNotifyWorker(watcher.NotifyConfig{ 68 Handler: logger, 69 }) 70 if err != nil { 71 return nil, errors.Trace(err) 72 } 73 return w, nil 74 } 75 76 func (l *loggerWorker) setLogging() { 77 loggingConfig := "" 78 logger := l.config.Logger 79 80 if override := l.config.Override; override != "" { 81 logger.Debugf("overriding logging config with override from agent.conf %q", override) 82 loggingConfig = override 83 } else { 84 modelLoggingConfig, err := l.config.API.LoggingConfig(l.config.Tag) 85 if err != nil { 86 logger.Errorf("%v", err) 87 return 88 } 89 loggingConfig = modelLoggingConfig 90 } 91 92 if loggingConfig != l.lastConfig { 93 logger.Debugf("reconfiguring logging from %q to %q", l.lastConfig, loggingConfig) 94 context := l.config.Context 95 context.ResetLoggerLevels() 96 if err := context.ConfigureLoggers(loggingConfig); err != nil { 97 // This shouldn't occur as the loggingConfig should be 98 // validated by the original Config before it gets here. 99 logger.Warningf("configure loggers failed: %v", err) 100 // Try to reset to what we had before 101 _ = context.ConfigureLoggers(l.lastConfig) 102 return 103 } 104 mgo.ConfigureMgoLogging() 105 l.lastConfig = loggingConfig 106 // Save the logging config in the agent.conf file. 107 if callback := l.config.Callback; callback != nil { 108 err := callback(loggingConfig) 109 if err != nil { 110 logger.Errorf("%v", err) 111 } 112 } 113 } 114 } 115 116 // SetUp is called by the NotifyWorker when the worker starts, and it is 117 // required to return a notify watcher that is used as the event source 118 // for the Handle method. 119 func (l *loggerWorker) SetUp() (watcher.NotifyWatcher, error) { 120 l.config.Logger.Infof("logger worker started") 121 // We need to set this up initially as the NotifyWorker sucks up the first 122 // event. 123 l.setLogging() 124 return l.config.API.WatchLoggingConfig(l.config.Tag) 125 } 126 127 // Handle is called by the NotifyWorker whenever the notify event is fired. 128 func (l *loggerWorker) Handle(_ <-chan struct{}) error { 129 l.setLogging() 130 return nil 131 } 132 133 // TearDown is called by the NotifyWorker when the worker is being stopped. 134 func (l *loggerWorker) TearDown() error { 135 // Nothing to cleanup, only state is the watcher 136 l.config.Logger.Infof("logger worker stopped") 137 return nil 138 }