package logger import ( "fmt" "os" "strings" "sync" "time" ) // Creator builds a logging driver instance with given context. type Creator func(Context) (Logger, error) // LogOptValidator checks the options specific to the underlying // logging implementation. type LogOptValidator func(cfg map[string]string) error // Context provides enough information for a logging driver to do its function. type Context struct { Config map[string]string ContainerID string ContainerName string ContainerEntrypoint string ContainerArgs []string ContainerImageID string ContainerImageName string ContainerCreated time.Time LogPath string } // Hostname returns the hostname from the underlying OS. func (ctx *Context) Hostname() (string, error) { hostname, err := os.Hostname() if err != nil { return "", fmt.Errorf("logger: can not resolve hostname: %v", err) } return hostname, nil } // Command returns the command that the container being logged was // started with. The Entrypoint is prepended to the container // arguments. func (ctx *Context) Command() string { terms := []string{ctx.ContainerEntrypoint} for _, arg := range ctx.ContainerArgs { terms = append(terms, arg) } command := strings.Join(terms, " ") return command } type logdriverFactory struct { registry map[string]Creator optValidator map[string]LogOptValidator m sync.Mutex } func (lf *logdriverFactory) register(name string, c Creator) error { lf.m.Lock() defer lf.m.Unlock() if _, ok := lf.registry[name]; ok { return fmt.Errorf("logger: log driver named '%s' is already registered", name) } lf.registry[name] = c return 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, fmt.Errorf("logger: no log driver named '%s' is registered", name) } return c, nil } 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) } // 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 { l := factory.getLogOptValidator(name) if l != nil { return l(cfg) } return nil }