factory.go 4.2 KB

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