| package logger | |
| import ( | |
| "fmt" | |
| "sort" | |
| "sync" | |
| "github.com/docker/go-units" | |
| containertypes "github.com/moby/moby/api/types/container" | |
| "github.com/moby/moby/v2/pkg/plugingetter" | |
| "github.com/pkg/errors" | |
| ) | |
| // Creator builds a logging driver instance with given context. | |
| type Creator func(Info) (Logger, error) | |
| // LogOptValidator checks the options specific to the underlying | |
| // logging implementation. | |
| type LogOptValidator func(cfg map[string]string) error | |
| type logdriverFactory struct { | |
| registry map[string]Creator | |
| optValidator map[string]LogOptValidator | |
| m sync.Mutex | |
| } | |
| func (lf *logdriverFactory) list() []string { | |
| ls := make([]string, 0, len(lf.registry)) | |
| lf.m.Lock() | |
| for name := range lf.registry { | |
| ls = append(ls, name) | |
| } | |
| lf.m.Unlock() | |
| sort.Strings(ls) | |
| return ls | |
| } | |
| // ListDrivers gets the list of registered log driver names | |
| func ListDrivers() []string { | |
| return factory.list() | |
| } | |
| func (lf *logdriverFactory) register(name string, c Creator) error { | |
| registered, err := lf.driverRegistered(name) | |
| if err != nil { | |
| return err | |
| } | |
| if registered { | |
| return fmt.Errorf("logger: log driver named '%s' is already registered", name) | |
| } | |
| lf.m.Lock() | |
| lf.registry[name] = c | |
| lf.m.Unlock() | |
| return nil | |
| } | |
| func (lf *logdriverFactory) driverRegistered(name string) (bool, error) { | |
| lf.m.Lock() | |
| _, ok := lf.registry[name] | |
| lf.m.Unlock() | |
| if !ok { | |
| if pluginGetter != nil { // this can be nil when the init functions are running | |
| l, err := getPlugin(name, plugingetter.Lookup) | |
| if err != nil { | |
| return false, err | |
| } | |
| if l != nil { | |
| return true, nil | |
| } | |
| } | |
| } | |
| return ok, nil | |
| } | |
| func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidator) error { | |
| lf.m.Lock() | |
| defer lf.m.Unlock() | |
| if _, ok := lf.optValidator[name]; ok { | |
| return fmt.Errorf("logger: log validator named '%s' is already registered", name) | |
| } | |
| lf.optValidator[name] = l | |
| return nil | |
| } | |
| func (lf *logdriverFactory) get(name string) (Creator, error) { | |
| lf.m.Lock() | |
| defer lf.m.Unlock() | |
| c, ok := lf.registry[name] | |
| if ok { | |
| return c, nil | |
| } | |
| c, err := getPlugin(name, plugingetter.Acquire) | |
| return c, errors.Wrapf(err, "logger: no log driver named '%s' is registered", name) | |
| } | |
| func (lf *logdriverFactory) getLogOptValidator(name string) LogOptValidator { | |
| lf.m.Lock() | |
| defer lf.m.Unlock() | |
| c := lf.optValidator[name] | |
| return c | |
| } | |
| var factory = &logdriverFactory{registry: make(map[string]Creator), optValidator: make(map[string]LogOptValidator)} // global factory instance | |
| // RegisterLogDriver registers the given logging driver builder with given logging | |
| // driver name. | |
| func RegisterLogDriver(name string, c Creator) error { | |
| return factory.register(name, c) | |
| } | |
| // RegisterLogOptValidator registers the logging option validator with | |
| // the given logging driver name. | |
| func RegisterLogOptValidator(name string, l LogOptValidator) error { | |
| return factory.registerLogOptValidator(name, l) | |
| } | |
| // GetLogDriver provides the logging driver builder for a logging driver name. | |
| func GetLogDriver(name string) (Creator, error) { | |
| return factory.get(name) | |
| } | |
| var builtInLogOpts = map[string]bool{ | |
| "mode": true, | |
| "max-buffer-size": true, | |
| } | |
| // ValidateLogOpts checks the options for the given log driver. The | |
| // options supported are specific to the LogDriver implementation. | |
| func ValidateLogOpts(name string, cfg map[string]string) error { | |
| if name == "none" { | |
| return nil | |
| } | |
| switch containertypes.LogMode(cfg["mode"]) { | |
| case containertypes.LogModeBlocking, containertypes.LogModeNonBlock, containertypes.LogModeUnset: | |
| default: | |
| return fmt.Errorf("logger: logging mode not supported: %s", cfg["mode"]) | |
| } | |
| if s, ok := cfg["max-buffer-size"]; ok { | |
| if containertypes.LogMode(cfg["mode"]) != containertypes.LogModeNonBlock { | |
| return fmt.Errorf("logger: max-buffer-size option is only supported with 'mode=%s'", containertypes.LogModeNonBlock) | |
| } | |
| if _, err := units.RAMInBytes(s); err != nil { | |
| return errors.Wrap(err, "error parsing option max-buffer-size") | |
| } | |
| } | |
| if err := validateExternal(cfg); err != nil { | |
| return err | |
| } | |
| registered, err := factory.driverRegistered(name) | |
| if err != nil { | |
| return err | |
| } | |
| if !registered { | |
| return fmt.Errorf("logger: no log driver named '%s' is registered", name) | |
| } | |
| filteredOpts := make(map[string]string, len(builtInLogOpts)) | |
| for k, v := range cfg { | |
| if !builtInLogOpts[k] { | |
| filteredOpts[k] = v | |
| } | |
| } | |
| validator := factory.getLogOptValidator(name) | |
| if validator != nil { | |
| return validator(filteredOpts) | |
| } | |
| return nil | |
| } |