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  }