github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/daemon/logger/factory.go (about) 1 package logger // import "github.com/docker/docker/daemon/logger" 2 3 import ( 4 "fmt" 5 "sort" 6 "sync" 7 8 containertypes "github.com/docker/docker/api/types/container" 9 "github.com/docker/docker/pkg/plugingetter" 10 units "github.com/docker/go-units" 11 "github.com/pkg/errors" 12 ) 13 14 // Creator builds a logging driver instance with given context. 15 type Creator func(Info) (Logger, error) 16 17 // LogOptValidator checks the options specific to the underlying 18 // logging implementation. 19 type LogOptValidator func(cfg map[string]string) error 20 21 type logdriverFactory struct { 22 registry map[string]Creator 23 optValidator map[string]LogOptValidator 24 m sync.Mutex 25 } 26 27 func (lf *logdriverFactory) list() []string { 28 ls := make([]string, 0, len(lf.registry)) 29 lf.m.Lock() 30 for name := range lf.registry { 31 ls = append(ls, name) 32 } 33 lf.m.Unlock() 34 sort.Strings(ls) 35 return ls 36 } 37 38 // ListDrivers gets the list of registered log driver names 39 func ListDrivers() []string { 40 return factory.list() 41 } 42 43 func (lf *logdriverFactory) register(name string, c Creator) error { 44 registered, err := lf.driverRegistered(name) 45 if err != nil { 46 return err 47 } 48 if registered { 49 return fmt.Errorf("logger: log driver named '%s' is already registered", name) 50 } 51 52 lf.m.Lock() 53 lf.registry[name] = c 54 lf.m.Unlock() 55 return nil 56 } 57 58 func (lf *logdriverFactory) driverRegistered(name string) (bool, error) { 59 lf.m.Lock() 60 _, ok := lf.registry[name] 61 lf.m.Unlock() 62 if !ok { 63 if pluginGetter != nil { // this can be nil when the init functions are running 64 l, err := getPlugin(name, plugingetter.Lookup) 65 if err != nil { 66 return false, err 67 } 68 if l != nil { 69 return true, nil 70 } 71 } 72 } 73 return ok, nil 74 } 75 76 func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidator) error { 77 lf.m.Lock() 78 defer lf.m.Unlock() 79 80 if _, ok := lf.optValidator[name]; ok { 81 return fmt.Errorf("logger: log validator named '%s' is already registered", name) 82 } 83 lf.optValidator[name] = l 84 return nil 85 } 86 87 func (lf *logdriverFactory) get(name string) (Creator, error) { 88 lf.m.Lock() 89 defer lf.m.Unlock() 90 91 c, ok := lf.registry[name] 92 if ok { 93 return c, nil 94 } 95 96 c, err := getPlugin(name, plugingetter.Acquire) 97 return c, errors.Wrapf(err, "logger: no log driver named '%s' is registered", name) 98 } 99 100 func (lf *logdriverFactory) getLogOptValidator(name string) LogOptValidator { 101 lf.m.Lock() 102 defer lf.m.Unlock() 103 104 c := lf.optValidator[name] 105 return c 106 } 107 108 var factory = &logdriverFactory{registry: make(map[string]Creator), optValidator: make(map[string]LogOptValidator)} // global factory instance 109 110 // RegisterLogDriver registers the given logging driver builder with given logging 111 // driver name. 112 func RegisterLogDriver(name string, c Creator) error { 113 return factory.register(name, c) 114 } 115 116 // RegisterLogOptValidator registers the logging option validator with 117 // the given logging driver name. 118 func RegisterLogOptValidator(name string, l LogOptValidator) error { 119 return factory.registerLogOptValidator(name, l) 120 } 121 122 // GetLogDriver provides the logging driver builder for a logging driver name. 123 func GetLogDriver(name string) (Creator, error) { 124 return factory.get(name) 125 } 126 127 var builtInLogOpts = map[string]bool{ 128 "mode": true, 129 "max-buffer-size": true, 130 } 131 132 // ValidateLogOpts checks the options for the given log driver. The 133 // options supported are specific to the LogDriver implementation. 134 func ValidateLogOpts(name string, cfg map[string]string) error { 135 if name == "none" { 136 return nil 137 } 138 139 switch containertypes.LogMode(cfg["mode"]) { 140 case containertypes.LogModeBlocking, containertypes.LogModeNonBlock, containertypes.LogModeUnset: 141 default: 142 return fmt.Errorf("logger: logging mode not supported: %s", cfg["mode"]) 143 } 144 145 if s, ok := cfg["max-buffer-size"]; ok { 146 if containertypes.LogMode(cfg["mode"]) != containertypes.LogModeNonBlock { 147 return fmt.Errorf("logger: max-buffer-size option is only supported with 'mode=%s'", containertypes.LogModeNonBlock) 148 } 149 if _, err := units.RAMInBytes(s); err != nil { 150 return errors.Wrap(err, "error parsing option max-buffer-size") 151 } 152 } 153 154 if err := validateExternal(cfg); err != nil { 155 return err 156 } 157 158 registered, err := factory.driverRegistered(name) 159 if err != nil { 160 return err 161 } 162 if !registered { 163 return fmt.Errorf("logger: no log driver named '%s' is registered", name) 164 } 165 166 filteredOpts := make(map[string]string, len(builtInLogOpts)) 167 for k, v := range cfg { 168 if !builtInLogOpts[k] { 169 filteredOpts[k] = v 170 } 171 } 172 173 validator := factory.getLogOptValidator(name) 174 if validator != nil { 175 return validator(filteredOpts) 176 } 177 return nil 178 }