github.com/lazyboychen7/engine@v17.12.1-ce-rc2+incompatible/daemon/logger/factory.go (about) 1 package 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 if lf.driverRegistered(name) { 45 return fmt.Errorf("logger: log driver named '%s' is already registered", name) 46 } 47 48 lf.m.Lock() 49 lf.registry[name] = c 50 lf.m.Unlock() 51 return nil 52 } 53 54 func (lf *logdriverFactory) driverRegistered(name string) bool { 55 lf.m.Lock() 56 _, ok := lf.registry[name] 57 lf.m.Unlock() 58 if !ok { 59 if pluginGetter != nil { // this can be nil when the init functions are running 60 if l, _ := getPlugin(name, plugingetter.Lookup); l != nil { 61 return true 62 } 63 } 64 } 65 return ok 66 } 67 68 func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidator) error { 69 lf.m.Lock() 70 defer lf.m.Unlock() 71 72 if _, ok := lf.optValidator[name]; ok { 73 return fmt.Errorf("logger: log validator named '%s' is already registered", name) 74 } 75 lf.optValidator[name] = l 76 return nil 77 } 78 79 func (lf *logdriverFactory) get(name string) (Creator, error) { 80 lf.m.Lock() 81 defer lf.m.Unlock() 82 83 c, ok := lf.registry[name] 84 if ok { 85 return c, nil 86 } 87 88 c, err := getPlugin(name, plugingetter.Acquire) 89 return c, errors.Wrapf(err, "logger: no log driver named '%s' is registered", name) 90 } 91 92 func (lf *logdriverFactory) getLogOptValidator(name string) LogOptValidator { 93 lf.m.Lock() 94 defer lf.m.Unlock() 95 96 c := lf.optValidator[name] 97 return c 98 } 99 100 var factory = &logdriverFactory{registry: make(map[string]Creator), optValidator: make(map[string]LogOptValidator)} // global factory instance 101 102 // RegisterLogDriver registers the given logging driver builder with given logging 103 // driver name. 104 func RegisterLogDriver(name string, c Creator) error { 105 return factory.register(name, c) 106 } 107 108 // RegisterLogOptValidator registers the logging option validator with 109 // the given logging driver name. 110 func RegisterLogOptValidator(name string, l LogOptValidator) error { 111 return factory.registerLogOptValidator(name, l) 112 } 113 114 // GetLogDriver provides the logging driver builder for a logging driver name. 115 func GetLogDriver(name string) (Creator, error) { 116 return factory.get(name) 117 } 118 119 var builtInLogOpts = map[string]bool{ 120 "mode": true, 121 "max-buffer-size": true, 122 } 123 124 // ValidateLogOpts checks the options for the given log driver. The 125 // options supported are specific to the LogDriver implementation. 126 func ValidateLogOpts(name string, cfg map[string]string) error { 127 if name == "none" { 128 return nil 129 } 130 131 switch containertypes.LogMode(cfg["mode"]) { 132 case containertypes.LogModeBlocking, containertypes.LogModeNonBlock, containertypes.LogModeUnset: 133 default: 134 return fmt.Errorf("logger: logging mode not supported: %s", cfg["mode"]) 135 } 136 137 if s, ok := cfg["max-buffer-size"]; ok { 138 if containertypes.LogMode(cfg["mode"]) != containertypes.LogModeNonBlock { 139 return fmt.Errorf("logger: max-buffer-size option is only supported with 'mode=%s'", containertypes.LogModeNonBlock) 140 } 141 if _, err := units.RAMInBytes(s); err != nil { 142 return errors.Wrap(err, "error parsing option max-buffer-size") 143 } 144 } 145 146 if !factory.driverRegistered(name) { 147 return fmt.Errorf("logger: no log driver named '%s' is registered", name) 148 } 149 150 filteredOpts := make(map[string]string, len(builtInLogOpts)) 151 for k, v := range cfg { 152 if !builtInLogOpts[k] { 153 filteredOpts[k] = v 154 } 155 } 156 157 validator := factory.getLogOptValidator(name) 158 if validator != nil { 159 return validator(filteredOpts) 160 } 161 return nil 162 }