mirror of https://github.com/docker/docs.git
Merge pull request #14843 from MHBauer/demonlogger-lint
golint fixes for daemon/logger/*
This commit is contained in:
commit
6a274e48dc
|
@ -8,13 +8,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Creator is a method that builds a logging driver instance with given context
|
// Creator builds a logging driver instance with given context.
|
||||||
type Creator func(Context) (Logger, error)
|
type Creator func(Context) (Logger, error)
|
||||||
|
|
||||||
//LogOptValidator is a method that validates the log opts provided
|
// LogOptValidator checks the options specific to the underlying
|
||||||
|
// logging implementation.
|
||||||
type LogOptValidator func(cfg map[string]string) error
|
type LogOptValidator func(cfg map[string]string) error
|
||||||
|
|
||||||
// Context provides enough information for a logging driver to do its function
|
// Context provides enough information for a logging driver to do its function.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
Config map[string]string
|
Config map[string]string
|
||||||
ContainerID string
|
ContainerID string
|
||||||
|
@ -27,7 +28,7 @@ type Context struct {
|
||||||
LogPath string
|
LogPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hostname returns the hostname from the underlying OS
|
// Hostname returns the hostname from the underlying OS.
|
||||||
func (ctx *Context) Hostname() (string, error) {
|
func (ctx *Context) Hostname() (string, error) {
|
||||||
hostname, err := os.Hostname()
|
hostname, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -36,7 +37,9 @@ func (ctx *Context) Hostname() (string, error) {
|
||||||
return hostname, nil
|
return hostname, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the command that the container being logged was started with
|
// 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 {
|
func (ctx *Context) Command() string {
|
||||||
terms := []string{ctx.ContainerEntrypoint}
|
terms := []string{ctx.ContainerEntrypoint}
|
||||||
for _, arg := range ctx.ContainerArgs {
|
for _, arg := range ctx.ContainerArgs {
|
||||||
|
@ -68,7 +71,7 @@ func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidat
|
||||||
defer lf.m.Unlock()
|
defer lf.m.Unlock()
|
||||||
|
|
||||||
if _, ok := lf.optValidator[name]; ok {
|
if _, ok := lf.optValidator[name]; ok {
|
||||||
return fmt.Errorf("logger: log driver named '%s' is already registered", name)
|
return fmt.Errorf("logger: log validator named '%s' is already registered", name)
|
||||||
}
|
}
|
||||||
lf.optValidator[name] = l
|
lf.optValidator[name] = l
|
||||||
return nil
|
return nil
|
||||||
|
@ -101,6 +104,8 @@ func RegisterLogDriver(name string, c Creator) error {
|
||||||
return factory.register(name, c)
|
return factory.register(name, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterLogOptValidator registers the logging option validator with
|
||||||
|
// the given logging driver name.
|
||||||
func RegisterLogOptValidator(name string, l LogOptValidator) error {
|
func RegisterLogOptValidator(name string, l LogOptValidator) error {
|
||||||
return factory.registerLogOptValidator(name, l)
|
return factory.registerLogOptValidator(name, l)
|
||||||
}
|
}
|
||||||
|
@ -110,6 +115,8 @@ func GetLogDriver(name string) (Creator, error) {
|
||||||
return factory.get(name)
|
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 {
|
func ValidateLogOpts(name string, cfg map[string]string) error {
|
||||||
l := factory.getLogOptValidator(name)
|
l := factory.getLogOptValidator(name)
|
||||||
if l != nil {
|
if l != nil {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// Package fluentd provides the log driver for forwarding server logs
|
||||||
|
// to fluentd endpoints.
|
||||||
package fluentd
|
package fluentd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -14,14 +16,14 @@ import (
|
||||||
"github.com/fluent/fluent-logger-golang/fluent"
|
"github.com/fluent/fluent-logger-golang/fluent"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Fluentd struct {
|
type fluentd struct {
|
||||||
tag string
|
tag string
|
||||||
containerID string
|
containerID string
|
||||||
containerName string
|
containerName string
|
||||||
writer *fluent.Fluent
|
writer *fluent.Fluent
|
||||||
}
|
}
|
||||||
|
|
||||||
type Receiver struct {
|
type receiver struct {
|
||||||
ID string
|
ID string
|
||||||
FullID string
|
FullID string
|
||||||
Name string
|
Name string
|
||||||
|
@ -67,7 +69,7 @@ func parseConfig(ctx logger.Context) (string, int, string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if config["fluentd-tag"] != "" {
|
if config["fluentd-tag"] != "" {
|
||||||
receiver := &Receiver{
|
receiver := &receiver{
|
||||||
ID: ctx.ContainerID[:12],
|
ID: ctx.ContainerID[:12],
|
||||||
FullID: ctx.ContainerID,
|
FullID: ctx.ContainerID,
|
||||||
Name: ctx.ContainerName,
|
Name: ctx.ContainerName,
|
||||||
|
@ -86,6 +88,9 @@ func parseConfig(ctx logger.Context) (string, int, string, error) {
|
||||||
return host, port, tag, nil
|
return host, port, tag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a fluentd logger using the configuration passed in on
|
||||||
|
// the context. Supported context configuration variables are
|
||||||
|
// fluentd-address & fluentd-tag.
|
||||||
func New(ctx logger.Context) (logger.Logger, error) {
|
func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
host, port, tag, err := parseConfig(ctx)
|
host, port, tag, err := parseConfig(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -99,7 +104,7 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Fluentd{
|
return &fluentd{
|
||||||
tag: tag,
|
tag: tag,
|
||||||
containerID: ctx.ContainerID,
|
containerID: ctx.ContainerID,
|
||||||
containerName: ctx.ContainerName,
|
containerName: ctx.ContainerName,
|
||||||
|
@ -107,7 +112,7 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fluentd) Log(msg *logger.Message) error {
|
func (f *fluentd) Log(msg *logger.Message) error {
|
||||||
data := map[string]string{
|
data := map[string]string{
|
||||||
"container_id": f.containerID,
|
"container_id": f.containerID,
|
||||||
"container_name": f.containerName,
|
"container_name": f.containerName,
|
||||||
|
@ -119,6 +124,7 @@ func (f *Fluentd) Log(msg *logger.Message) error {
|
||||||
return f.writer.PostWithTime(f.tag, msg.Timestamp, data)
|
return f.writer.PostWithTime(f.tag, msg.Timestamp, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateLogOpt looks for fluentd specific log options fluentd-address & fluentd-tag.
|
||||||
func ValidateLogOpt(cfg map[string]string) error {
|
func ValidateLogOpt(cfg map[string]string) error {
|
||||||
for key := range cfg {
|
for key := range cfg {
|
||||||
switch key {
|
switch key {
|
||||||
|
@ -131,10 +137,10 @@ func ValidateLogOpt(cfg map[string]string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fluentd) Close() error {
|
func (f *fluentd) Close() error {
|
||||||
return f.writer.Close()
|
return f.writer.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fluentd) Name() string {
|
func (f *fluentd) Name() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
|
// Package gelf provides the log driver for forwarding server logs to
|
||||||
|
// endpoints that support the Graylog Extended Log Format.
|
||||||
package gelf
|
package gelf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -17,17 +19,17 @@ import (
|
||||||
|
|
||||||
const name = "gelf"
|
const name = "gelf"
|
||||||
|
|
||||||
type GelfLogger struct {
|
type gelfLogger struct {
|
||||||
writer *gelf.Writer
|
writer *gelf.Writer
|
||||||
ctx logger.Context
|
ctx logger.Context
|
||||||
fields GelfFields
|
fields gelfFields
|
||||||
}
|
}
|
||||||
|
|
||||||
type GelfFields struct {
|
type gelfFields struct {
|
||||||
hostname string
|
hostname string
|
||||||
containerId string
|
containerID string
|
||||||
containerName string
|
containerName string
|
||||||
imageId string
|
imageID string
|
||||||
imageName string
|
imageName string
|
||||||
command string
|
command string
|
||||||
tag string
|
tag string
|
||||||
|
@ -43,6 +45,9 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a gelf logger using the configuration passed in on the
|
||||||
|
// context. Supported context configuration variables are
|
||||||
|
// gelf-address, & gelf-tag.
|
||||||
func New(ctx logger.Context) (logger.Logger, error) {
|
func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
// parse gelf address
|
// parse gelf address
|
||||||
address, err := parseAddress(ctx.Config["gelf-address"])
|
address, err := parseAddress(ctx.Config["gelf-address"])
|
||||||
|
@ -59,11 +64,11 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
// remove trailing slash from container name
|
// remove trailing slash from container name
|
||||||
containerName := bytes.TrimLeft([]byte(ctx.ContainerName), "/")
|
containerName := bytes.TrimLeft([]byte(ctx.ContainerName), "/")
|
||||||
|
|
||||||
fields := GelfFields{
|
fields := gelfFields{
|
||||||
hostname: hostname,
|
hostname: hostname,
|
||||||
containerId: ctx.ContainerID,
|
containerID: ctx.ContainerID,
|
||||||
containerName: string(containerName),
|
containerName: string(containerName),
|
||||||
imageId: ctx.ContainerImageID,
|
imageID: ctx.ContainerImageID,
|
||||||
imageName: ctx.ContainerImageName,
|
imageName: ctx.ContainerImageName,
|
||||||
command: ctx.Command(),
|
command: ctx.Command(),
|
||||||
tag: ctx.Config["gelf-tag"],
|
tag: ctx.Config["gelf-tag"],
|
||||||
|
@ -76,14 +81,14 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
return nil, fmt.Errorf("gelf: cannot connect to GELF endpoint: %s %v", address, err)
|
return nil, fmt.Errorf("gelf: cannot connect to GELF endpoint: %s %v", address, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &GelfLogger{
|
return &gelfLogger{
|
||||||
writer: gelfWriter,
|
writer: gelfWriter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
fields: fields,
|
fields: fields,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GelfLogger) Log(msg *logger.Message) error {
|
func (s *gelfLogger) Log(msg *logger.Message) error {
|
||||||
// remove trailing and leading whitespace
|
// remove trailing and leading whitespace
|
||||||
short := bytes.TrimSpace([]byte(msg.Line))
|
short := bytes.TrimSpace([]byte(msg.Line))
|
||||||
|
|
||||||
|
@ -99,9 +104,9 @@ func (s *GelfLogger) Log(msg *logger.Message) error {
|
||||||
TimeUnix: float64(msg.Timestamp.UnixNano()/int64(time.Millisecond)) / 1000.0,
|
TimeUnix: float64(msg.Timestamp.UnixNano()/int64(time.Millisecond)) / 1000.0,
|
||||||
Level: level,
|
Level: level,
|
||||||
Extra: map[string]interface{}{
|
Extra: map[string]interface{}{
|
||||||
"_container_id": s.fields.containerId,
|
"_container_id": s.fields.containerID,
|
||||||
"_container_name": s.fields.containerName,
|
"_container_name": s.fields.containerName,
|
||||||
"_image_id": s.fields.imageId,
|
"_image_id": s.fields.imageID,
|
||||||
"_image_name": s.fields.imageName,
|
"_image_name": s.fields.imageName,
|
||||||
"_command": s.fields.command,
|
"_command": s.fields.command,
|
||||||
"_tag": s.fields.tag,
|
"_tag": s.fields.tag,
|
||||||
|
@ -115,14 +120,16 @@ func (s *GelfLogger) Log(msg *logger.Message) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GelfLogger) Close() error {
|
func (s *gelfLogger) Close() error {
|
||||||
return s.writer.Close()
|
return s.writer.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GelfLogger) Name() string {
|
func (s *gelfLogger) Name() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateLogOpt looks for gelf specific log options gelf-address, &
|
||||||
|
// gelf-tag.
|
||||||
func ValidateLogOpt(cfg map[string]string) error {
|
func ValidateLogOpt(cfg map[string]string) error {
|
||||||
for key := range cfg {
|
for key := range cfg {
|
||||||
switch key {
|
switch key {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
|
// Package journald provides the log driver for forwarding server logs
|
||||||
|
// to endpoints that receive the systemd format.
|
||||||
package journald
|
package journald
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -12,7 +14,7 @@ import (
|
||||||
|
|
||||||
const name = "journald"
|
const name = "journald"
|
||||||
|
|
||||||
type Journald struct {
|
type journald struct {
|
||||||
Jmap map[string]string
|
Jmap map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +24,9 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a journald logger using the configuration passed in on
|
||||||
|
// the context. Supported context configuration variables are
|
||||||
|
// syslog-address, syslog-facility, & syslog-tag.
|
||||||
func New(ctx logger.Context) (logger.Logger, error) {
|
func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
if !journal.Enabled() {
|
if !journal.Enabled() {
|
||||||
return nil, fmt.Errorf("journald is not enabled on this host")
|
return nil, fmt.Errorf("journald is not enabled on this host")
|
||||||
|
@ -36,20 +41,20 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
"CONTAINER_ID": ctx.ContainerID[:12],
|
"CONTAINER_ID": ctx.ContainerID[:12],
|
||||||
"CONTAINER_ID_FULL": ctx.ContainerID,
|
"CONTAINER_ID_FULL": ctx.ContainerID,
|
||||||
"CONTAINER_NAME": name}
|
"CONTAINER_NAME": name}
|
||||||
return &Journald{Jmap: jmap}, nil
|
return &journald{Jmap: jmap}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Journald) Log(msg *logger.Message) error {
|
func (s *journald) Log(msg *logger.Message) error {
|
||||||
if msg.Source == "stderr" {
|
if msg.Source == "stderr" {
|
||||||
return journal.Send(string(msg.Line), journal.PriErr, s.Jmap)
|
return journal.Send(string(msg.Line), journal.PriErr, s.Jmap)
|
||||||
}
|
}
|
||||||
return journal.Send(string(msg.Line), journal.PriInfo, s.Jmap)
|
return journal.Send(string(msg.Line), journal.PriInfo, s.Jmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Journald) Close() error {
|
func (s *journald) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Journald) Name() string {
|
func (s *journald) Name() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// Package jsonfilelog provides the default Logger implementation for
|
||||||
|
// Docker logging. This logger logs to files on the host server in the
|
||||||
|
// JSON format.
|
||||||
package jsonfilelog
|
package jsonfilelog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -23,12 +26,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// Name is the name of the file that the jsonlogger logs to.
|
||||||
Name = "json-file"
|
Name = "json-file"
|
||||||
maxJSONDecodeRetry = 10
|
maxJSONDecodeRetry = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
// JSONFileLogger is Logger implementation for default docker logging:
|
// JSONFileLogger is Logger implementation for default Docker logging.
|
||||||
// JSON objects to file
|
|
||||||
type JSONFileLogger struct {
|
type JSONFileLogger struct {
|
||||||
buf *bytes.Buffer
|
buf *bytes.Buffer
|
||||||
f *os.File // store for closing
|
f *os.File // store for closing
|
||||||
|
@ -49,7 +52,8 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates new JSONFileLogger which writes to filename
|
// New creates new JSONFileLogger which writes to filename passed in
|
||||||
|
// on given context.
|
||||||
func New(ctx logger.Context) (logger.Logger, error) {
|
func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
log, err := os.OpenFile(ctx.LogPath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600)
|
log, err := os.OpenFile(ctx.LogPath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -63,14 +67,14 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var maxFiles int = 1
|
var maxFiles = 1
|
||||||
if maxFileString, ok := ctx.Config["max-file"]; ok {
|
if maxFileString, ok := ctx.Config["max-file"]; ok {
|
||||||
maxFiles, err = strconv.Atoi(maxFileString)
|
maxFiles, err = strconv.Atoi(maxFileString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if maxFiles < 1 {
|
if maxFiles < 1 {
|
||||||
return nil, fmt.Errorf("max-files cannot be less than 1.")
|
return nil, fmt.Errorf("max-files cannot be less than 1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &JSONFileLogger{
|
return &JSONFileLogger{
|
||||||
|
@ -84,7 +88,7 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log converts logger.Message to jsonlog.JSONLog and serializes it to file
|
// Log converts logger.Message to jsonlog.JSONLog and serializes it to file.
|
||||||
func (l *JSONFileLogger) Log(msg *logger.Message) error {
|
func (l *JSONFileLogger) Log(msg *logger.Message) error {
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
defer l.mu.Unlock()
|
defer l.mu.Unlock()
|
||||||
|
@ -153,6 +157,7 @@ func rotate(name string, n int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// backup renames a file from curr to old, creating an empty file curr if it does not exist.
|
||||||
func backup(old, curr string) error {
|
func backup(old, curr string) error {
|
||||||
if _, err := os.Stat(old); !os.IsNotExist(err) {
|
if _, err := os.Stat(old); !os.IsNotExist(err) {
|
||||||
err := os.Remove(old)
|
err := os.Remove(old)
|
||||||
|
@ -170,6 +175,7 @@ func backup(old, curr string) error {
|
||||||
return os.Rename(curr, old)
|
return os.Rename(curr, old)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateLogOpt looks for json specific log options max-file & max-size.
|
||||||
func ValidateLogOpt(cfg map[string]string) error {
|
func ValidateLogOpt(cfg map[string]string) error {
|
||||||
for key := range cfg {
|
for key := range cfg {
|
||||||
switch key {
|
switch key {
|
||||||
|
@ -182,11 +188,12 @@ func ValidateLogOpt(cfg map[string]string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogPath returns the location the given json logger logs to.
|
||||||
func (l *JSONFileLogger) LogPath() string {
|
func (l *JSONFileLogger) LogPath() string {
|
||||||
return l.ctx.LogPath
|
return l.ctx.LogPath
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes underlying file and signals all readers to stop
|
// Close closes underlying file and signals all readers to stop.
|
||||||
func (l *JSONFileLogger) Close() error {
|
func (l *JSONFileLogger) Close() error {
|
||||||
l.mu.Lock()
|
l.mu.Lock()
|
||||||
err := l.f.Close()
|
err := l.f.Close()
|
||||||
|
@ -198,7 +205,7 @@ func (l *JSONFileLogger) Close() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns name of this logger
|
// Name returns name of this logger.
|
||||||
func (l *JSONFileLogger) Name() string {
|
func (l *JSONFileLogger) Name() string {
|
||||||
return Name
|
return Name
|
||||||
}
|
}
|
||||||
|
@ -216,7 +223,8 @@ func decodeLogLine(dec *json.Decoder, l *jsonlog.JSONLog) (*logger.Message, erro
|
||||||
return msg, nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads from the log file
|
// ReadLogs implements the logger's LogReader interface for the logs
|
||||||
|
// created by this driver.
|
||||||
func (l *JSONFileLogger) ReadLogs(config logger.ReadConfig) *logger.LogWatcher {
|
func (l *JSONFileLogger) ReadLogs(config logger.ReadConfig) *logger.LogWatcher {
|
||||||
logWatcher := logger.NewLogWatcher()
|
logWatcher := logger.NewLogWatcher()
|
||||||
|
|
||||||
|
@ -326,7 +334,7 @@ func followLogs(f *os.File, logWatcher *logger.LogWatcher, notifyRotate chan int
|
||||||
// try again because this shouldn't happen
|
// try again because this shouldn't happen
|
||||||
if _, ok := err.(*json.SyntaxError); ok && retries <= maxJSONDecodeRetry {
|
if _, ok := err.(*json.SyntaxError); ok && retries <= maxJSONDecodeRetry {
|
||||||
dec = json.NewDecoder(f)
|
dec = json.NewDecoder(f)
|
||||||
retries += 1
|
retries++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logWatcher.Err <- err
|
logWatcher.Err <- err
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
// Package logger defines interfaces that logger drivers implement to
|
||||||
|
// log messages.
|
||||||
|
//
|
||||||
|
// The other half of a logger driver is the implementation of the
|
||||||
|
// factory, which holds the contextual instance information that
|
||||||
|
// allows multiple loggers of the same type to perform different
|
||||||
|
// actions, such as logging to different locations.
|
||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -7,16 +14,16 @@ import (
|
||||||
"github.com/docker/docker/pkg/timeutils"
|
"github.com/docker/docker/pkg/timeutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrReadLogsNotSupported is returned when the logger does not support reading logs
|
// ErrReadLogsNotSupported is returned when the logger does not support reading logs.
|
||||||
var ErrReadLogsNotSupported = errors.New("configured logging reader does not support reading")
|
var ErrReadLogsNotSupported = errors.New("configured logging reader does not support reading")
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TimeFormat is the time format used for timestamps sent to log readers
|
// TimeFormat is the time format used for timestamps sent to log readers.
|
||||||
TimeFormat = timeutils.RFC3339NanoFixed
|
TimeFormat = timeutils.RFC3339NanoFixed
|
||||||
logWatcherBufferSize = 4096
|
logWatcherBufferSize = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
// Message is datastructure that represents record from some container
|
// Message is datastructure that represents record from some container.
|
||||||
type Message struct {
|
type Message struct {
|
||||||
ContainerID string
|
ContainerID string
|
||||||
Line []byte
|
Line []byte
|
||||||
|
@ -24,31 +31,31 @@ type Message struct {
|
||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logger is the interface for docker logging drivers
|
// Logger is the interface for docker logging drivers.
|
||||||
type Logger interface {
|
type Logger interface {
|
||||||
Log(*Message) error
|
Log(*Message) error
|
||||||
Name() string
|
Name() string
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadConfig is the configuration passed into ReadLogs
|
// ReadConfig is the configuration passed into ReadLogs.
|
||||||
type ReadConfig struct {
|
type ReadConfig struct {
|
||||||
Since time.Time
|
Since time.Time
|
||||||
Tail int
|
Tail int
|
||||||
Follow bool
|
Follow bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogReader is the interface for reading log messages for loggers that support reading
|
// LogReader is the interface for reading log messages for loggers that support reading.
|
||||||
type LogReader interface {
|
type LogReader interface {
|
||||||
// Read logs from underlying logging backend
|
// Read logs from underlying logging backend
|
||||||
ReadLogs(ReadConfig) *LogWatcher
|
ReadLogs(ReadConfig) *LogWatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogWatcher is used when consuming logs read from the LogReader interface
|
// LogWatcher is used when consuming logs read from the LogReader interface.
|
||||||
type LogWatcher struct {
|
type LogWatcher struct {
|
||||||
// For sending log messages to a reader
|
// For sending log messages to a reader.
|
||||||
Msg chan *Message
|
Msg chan *Message
|
||||||
// For sending error messages that occur while while reading logs
|
// For sending error messages that occur while while reading logs.
|
||||||
Err chan error
|
Err chan error
|
||||||
closeNotifier chan struct{}
|
closeNotifier chan struct{}
|
||||||
}
|
}
|
||||||
|
@ -62,13 +69,14 @@ func NewLogWatcher() *LogWatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close notifies the underlying log reader to stop
|
// Close notifies the underlying log reader to stop.
|
||||||
func (w *LogWatcher) Close() {
|
func (w *LogWatcher) Close() {
|
||||||
close(w.closeNotifier)
|
close(w.closeNotifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WatchClose returns a channel receiver that receives notification when the watcher has been closed
|
// WatchClose returns a channel receiver that receives notification
|
||||||
// This should only be called from one goroutine
|
// when the watcher has been closed. This should only be called from
|
||||||
|
// one goroutine.
|
||||||
func (w *LogWatcher) WatchClose() <-chan struct{} {
|
func (w *LogWatcher) WatchClose() <-chan struct{} {
|
||||||
return w.closeNotifier
|
return w.closeNotifier
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
|
// Package syslog provides the logdriver for forwarding server logs to syslog endpoints.
|
||||||
package syslog
|
package syslog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -43,7 +44,7 @@ var facilities = map[string]syslog.Priority{
|
||||||
"local7": syslog.LOG_LOCAL7,
|
"local7": syslog.LOG_LOCAL7,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Syslog struct {
|
type syslogger struct {
|
||||||
writer *syslog.Writer
|
writer *syslog.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +57,9 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a syslog logger using the configuration passed in on
|
||||||
|
// the context. Supported context configuration variables are
|
||||||
|
// syslog-address, syslog-facility, & syslog-tag.
|
||||||
func New(ctx logger.Context) (logger.Logger, error) {
|
func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
tag := ctx.Config["syslog-tag"]
|
tag := ctx.Config["syslog-tag"]
|
||||||
if tag == "" {
|
if tag == "" {
|
||||||
|
@ -82,23 +86,23 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Syslog{
|
return &syslogger{
|
||||||
writer: log,
|
writer: log,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Syslog) Log(msg *logger.Message) error {
|
func (s *syslogger) Log(msg *logger.Message) error {
|
||||||
if msg.Source == "stderr" {
|
if msg.Source == "stderr" {
|
||||||
return s.writer.Err(string(msg.Line))
|
return s.writer.Err(string(msg.Line))
|
||||||
}
|
}
|
||||||
return s.writer.Info(string(msg.Line))
|
return s.writer.Info(string(msg.Line))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Syslog) Close() error {
|
func (s *syslogger) Close() error {
|
||||||
return s.writer.Close()
|
return s.writer.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Syslog) Name() string {
|
func (s *syslogger) Name() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,12 +136,14 @@ func parseAddress(address string) (string, string, error) {
|
||||||
return "", "", nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateLogOpt looks for syslog specific log options
|
||||||
|
// syslog-address, syslog-facility, & syslog-tag.
|
||||||
func ValidateLogOpt(cfg map[string]string) error {
|
func ValidateLogOpt(cfg map[string]string) error {
|
||||||
for key := range cfg {
|
for key := range cfg {
|
||||||
switch key {
|
switch key {
|
||||||
case "syslog-address":
|
case "syslog-address":
|
||||||
case "syslog-tag":
|
|
||||||
case "syslog-facility":
|
case "syslog-facility":
|
||||||
|
case "syslog-tag":
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown log opt '%s' for syslog log driver", key)
|
return fmt.Errorf("unknown log opt '%s' for syslog log driver", key)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,12 @@ packages=(
|
||||||
daemon/execdriver/native/template
|
daemon/execdriver/native/template
|
||||||
daemon/graphdriver/aufs
|
daemon/graphdriver/aufs
|
||||||
daemon/graphdriver/devmapper
|
daemon/graphdriver/devmapper
|
||||||
|
daemon/logger
|
||||||
|
daemon/logger/fluentd
|
||||||
|
daemon/logger/gelf
|
||||||
|
daemon/logger/journald
|
||||||
|
daemon/logger/jsonfilelog
|
||||||
|
daemon/logger/syslog
|
||||||
daemon/network
|
daemon/network
|
||||||
docker
|
docker
|
||||||
dockerinit
|
dockerinit
|
||||||
|
|
Loading…
Reference in New Issue