github.com/fabiokung/docker@v0.11.2-0.20170222101415-4534dcd49497/daemon/logger/factory.go (about) 1 package logger 2 3 import ( 4 "fmt" 5 "sync" 6 7 containertypes "github.com/docker/docker/api/types/container" 8 units "github.com/docker/go-units" 9 "github.com/pkg/errors" 10 ) 11 12 // Creator builds a logging driver instance with given context. 13 type Creator func(Info) (Logger, error) 14 15 // LogOptValidator checks the options specific to the underlying 16 // logging implementation. 17 type LogOptValidator func(cfg map[string]string) error 18 19 type logdriverFactory struct { 20 registry map[string]Creator 21 optValidator map[string]LogOptValidator 22 m sync.Mutex 23 } 24 25 func (lf *logdriverFactory) register(name string, c Creator) error { 26 if lf.driverRegistered(name) { 27 return fmt.Errorf("logger: log driver named '%s' is already registered", name) 28 } 29 30 lf.m.Lock() 31 lf.registry[name] = c 32 lf.m.Unlock() 33 return nil 34 } 35 36 func (lf *logdriverFactory) driverRegistered(name string) bool { 37 lf.m.Lock() 38 _, ok := lf.registry[name] 39 lf.m.Unlock() 40 return ok 41 } 42 43 func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidator) error { 44 lf.m.Lock() 45 defer lf.m.Unlock() 46 47 if _, ok := lf.optValidator[name]; ok { 48 return fmt.Errorf("logger: log validator named '%s' is already registered", name) 49 } 50 lf.optValidator[name] = l 51 return nil 52 } 53 54 func (lf *logdriverFactory) get(name string) (Creator, error) { 55 lf.m.Lock() 56 defer lf.m.Unlock() 57 58 c, ok := lf.registry[name] 59 if !ok { 60 return c, fmt.Errorf("logger: no log driver named '%s' is registered", name) 61 } 62 return c, nil 63 } 64 65 func (lf *logdriverFactory) getLogOptValidator(name string) LogOptValidator { 66 lf.m.Lock() 67 defer lf.m.Unlock() 68 69 c, _ := lf.optValidator[name] 70 return c 71 } 72 73 var factory = &logdriverFactory{registry: make(map[string]Creator), optValidator: make(map[string]LogOptValidator)} // global factory instance 74 75 // RegisterLogDriver registers the given logging driver builder with given logging 76 // driver name. 77 func RegisterLogDriver(name string, c Creator) error { 78 return factory.register(name, c) 79 } 80 81 // RegisterLogOptValidator registers the logging option validator with 82 // the given logging driver name. 83 func RegisterLogOptValidator(name string, l LogOptValidator) error { 84 return factory.registerLogOptValidator(name, l) 85 } 86 87 // GetLogDriver provides the logging driver builder for a logging driver name. 88 func GetLogDriver(name string) (Creator, error) { 89 return factory.get(name) 90 } 91 92 var builtInLogOpts = map[string]bool{ 93 "mode": true, 94 "max-buffer-size": true, 95 } 96 97 // ValidateLogOpts checks the options for the given log driver. The 98 // options supported are specific to the LogDriver implementation. 99 func ValidateLogOpts(name string, cfg map[string]string) error { 100 if name == "none" { 101 return nil 102 } 103 104 switch containertypes.LogMode(cfg["mode"]) { 105 case containertypes.LogModeBlocking, containertypes.LogModeNonBlock, containertypes.LogModeUnset: 106 default: 107 return fmt.Errorf("logger: logging mode not supported: %s", cfg["mode"]) 108 } 109 110 if s, ok := cfg["max-buffer-size"]; ok { 111 if containertypes.LogMode(cfg["mode"]) != containertypes.LogModeNonBlock { 112 return fmt.Errorf("logger: max-buffer-size option is only supported with 'mode=%s'", containertypes.LogModeNonBlock) 113 } 114 if _, err := units.RAMInBytes(s); err != nil { 115 return errors.Wrap(err, "error parsing option max-buffer-size") 116 } 117 } 118 119 if !factory.driverRegistered(name) { 120 return fmt.Errorf("logger: no log driver named '%s' is registered", name) 121 } 122 123 filteredOpts := make(map[string]string, len(builtInLogOpts)) 124 for k, v := range cfg { 125 if !builtInLogOpts[k] { 126 filteredOpts[k] = v 127 } 128 } 129 130 validator := factory.getLogOptValidator(name) 131 if validator != nil { 132 return validator(filteredOpts) 133 } 134 return nil 135 }