- downcase and privatize exported variables that were unused
- make accurate an error message
- added package comments
- remove unused var ReadLogsNotSupported
- enable linter
- some spelling corrections
Signed-off-by: Morgan Bauer <mbauer@us.ibm.com>
| ... | ... |
@@ -8,13 +8,14 @@ import ( |
| 8 | 8 |
"time" |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 |
-// Creator is a method that builds a logging driver instance with given context |
|
| 11 |
+// Creator builds a logging driver instance with given context. |
|
| 12 | 12 |
type Creator func(Context) (Logger, error) |
| 13 | 13 |
|
| 14 |
-//LogOptValidator is a method that validates the log opts provided |
|
| 14 |
+// LogOptValidator checks the options specific to the underlying |
|
| 15 |
+// logging implementation. |
|
| 15 | 16 |
type LogOptValidator func(cfg map[string]string) error |
| 16 | 17 |
|
| 17 |
-// Context provides enough information for a logging driver to do its function |
|
| 18 |
+// Context provides enough information for a logging driver to do its function. |
|
| 18 | 19 |
type Context struct {
|
| 19 | 20 |
Config map[string]string |
| 20 | 21 |
ContainerID string |
| ... | ... |
@@ -27,7 +28,7 @@ type Context struct {
|
| 27 | 27 |
LogPath string |
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 |
-// Hostname returns the hostname from the underlying OS |
|
| 30 |
+// Hostname returns the hostname from the underlying OS. |
|
| 31 | 31 |
func (ctx *Context) Hostname() (string, error) {
|
| 32 | 32 |
hostname, err := os.Hostname() |
| 33 | 33 |
if err != nil {
|
| ... | ... |
@@ -36,7 +37,9 @@ func (ctx *Context) Hostname() (string, error) {
|
| 36 | 36 |
return hostname, nil |
| 37 | 37 |
} |
| 38 | 38 |
|
| 39 |
-// Command returns the command that the container being logged was started with |
|
| 39 |
+// Command returns the command that the container being logged was |
|
| 40 |
+// started with. The Entrypoint is prepended to the container |
|
| 41 |
+// arguments. |
|
| 40 | 42 |
func (ctx *Context) Command() string {
|
| 41 | 43 |
terms := []string{ctx.ContainerEntrypoint}
|
| 42 | 44 |
for _, arg := range ctx.ContainerArgs {
|
| ... | ... |
@@ -68,7 +71,7 @@ func (lf *logdriverFactory) registerLogOptValidator(name string, l LogOptValidat |
| 68 | 68 |
defer lf.m.Unlock() |
| 69 | 69 |
|
| 70 | 70 |
if _, ok := lf.optValidator[name]; ok {
|
| 71 |
- return fmt.Errorf("logger: log driver named '%s' is already registered", name)
|
|
| 71 |
+ return fmt.Errorf("logger: log validator named '%s' is already registered", name)
|
|
| 72 | 72 |
} |
| 73 | 73 |
lf.optValidator[name] = l |
| 74 | 74 |
return nil |
| ... | ... |
@@ -101,6 +104,8 @@ func RegisterLogDriver(name string, c Creator) error {
|
| 101 | 101 |
return factory.register(name, c) |
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 |
+// RegisterLogOptValidator registers the logging option validator with |
|
| 105 |
+// the given logging driver name. |
|
| 104 | 106 |
func RegisterLogOptValidator(name string, l LogOptValidator) error {
|
| 105 | 107 |
return factory.registerLogOptValidator(name, l) |
| 106 | 108 |
} |
| ... | ... |
@@ -110,6 +115,8 @@ func GetLogDriver(name string) (Creator, error) {
|
| 110 | 110 |
return factory.get(name) |
| 111 | 111 |
} |
| 112 | 112 |
|
| 113 |
+// ValidateLogOpts checks the options for the given log driver. The |
|
| 114 |
+// options supported are specific to the LogDriver implementation. |
|
| 113 | 115 |
func ValidateLogOpts(name string, cfg map[string]string) error {
|
| 114 | 116 |
l := factory.getLogOptValidator(name) |
| 115 | 117 |
if l != nil {
|
| ... | ... |
@@ -1,3 +1,5 @@ |
| 1 |
+// Package fluentd provides the log driver for forwarding server logs |
|
| 2 |
+// to fluentd endpoints. |
|
| 1 | 3 |
package fluentd |
| 2 | 4 |
|
| 3 | 5 |
import ( |
| ... | ... |
@@ -14,14 +16,14 @@ import ( |
| 14 | 14 |
"github.com/fluent/fluent-logger-golang/fluent" |
| 15 | 15 |
) |
| 16 | 16 |
|
| 17 |
-type Fluentd struct {
|
|
| 17 |
+type fluentd struct {
|
|
| 18 | 18 |
tag string |
| 19 | 19 |
containerID string |
| 20 | 20 |
containerName string |
| 21 | 21 |
writer *fluent.Fluent |
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 |
-type Receiver struct {
|
|
| 24 |
+type receiver struct {
|
|
| 25 | 25 |
ID string |
| 26 | 26 |
FullID string |
| 27 | 27 |
Name string |
| ... | ... |
@@ -67,7 +69,7 @@ func parseConfig(ctx logger.Context) (string, int, string, error) {
|
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 | 69 |
if config["fluentd-tag"] != "" {
|
| 70 |
- receiver := &Receiver{
|
|
| 70 |
+ receiver := &receiver{
|
|
| 71 | 71 |
ID: ctx.ContainerID[:12], |
| 72 | 72 |
FullID: ctx.ContainerID, |
| 73 | 73 |
Name: ctx.ContainerName, |
| ... | ... |
@@ -86,6 +88,9 @@ func parseConfig(ctx logger.Context) (string, int, string, error) {
|
| 86 | 86 |
return host, port, tag, nil |
| 87 | 87 |
} |
| 88 | 88 |
|
| 89 |
+// New creates a fluentd logger using the configuration passed in on |
|
| 90 |
+// the context. Supported context configuration variables are |
|
| 91 |
+// fluentd-address & fluentd-tag. |
|
| 89 | 92 |
func New(ctx logger.Context) (logger.Logger, error) {
|
| 90 | 93 |
host, port, tag, err := parseConfig(ctx) |
| 91 | 94 |
if err != nil {
|
| ... | ... |
@@ -99,7 +104,7 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
| 99 | 99 |
if err != nil {
|
| 100 | 100 |
return nil, err |
| 101 | 101 |
} |
| 102 |
- return &Fluentd{
|
|
| 102 |
+ return &fluentd{
|
|
| 103 | 103 |
tag: tag, |
| 104 | 104 |
containerID: ctx.ContainerID, |
| 105 | 105 |
containerName: ctx.ContainerName, |
| ... | ... |
@@ -107,7 +112,7 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
| 107 | 107 |
}, nil |
| 108 | 108 |
} |
| 109 | 109 |
|
| 110 |
-func (f *Fluentd) Log(msg *logger.Message) error {
|
|
| 110 |
+func (f *fluentd) Log(msg *logger.Message) error {
|
|
| 111 | 111 |
data := map[string]string{
|
| 112 | 112 |
"container_id": f.containerID, |
| 113 | 113 |
"container_name": f.containerName, |
| ... | ... |
@@ -119,6 +124,7 @@ func (f *Fluentd) Log(msg *logger.Message) error {
|
| 119 | 119 |
return f.writer.PostWithTime(f.tag, msg.Timestamp, data) |
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 |
+// ValidateLogOpt looks for fluentd specific log options fluentd-address & fluentd-tag. |
|
| 122 | 123 |
func ValidateLogOpt(cfg map[string]string) error {
|
| 123 | 124 |
for key := range cfg {
|
| 124 | 125 |
switch key {
|
| ... | ... |
@@ -131,10 +137,10 @@ func ValidateLogOpt(cfg map[string]string) error {
|
| 131 | 131 |
return nil |
| 132 | 132 |
} |
| 133 | 133 |
|
| 134 |
-func (f *Fluentd) Close() error {
|
|
| 134 |
+func (f *fluentd) Close() error {
|
|
| 135 | 135 |
return f.writer.Close() |
| 136 | 136 |
} |
| 137 | 137 |
|
| 138 |
-func (f *Fluentd) Name() string {
|
|
| 138 |
+func (f *fluentd) Name() string {
|
|
| 139 | 139 |
return name |
| 140 | 140 |
} |
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 | 1 |
// +build linux |
| 2 | 2 |
|
| 3 |
+// Package gelf provides the log driver for forwarding server logs to |
|
| 4 |
+// endpoints that support the Graylog Extended Log Format. |
|
| 3 | 5 |
package gelf |
| 4 | 6 |
|
| 5 | 7 |
import ( |
| ... | ... |
@@ -17,17 +19,17 @@ import ( |
| 17 | 17 |
|
| 18 | 18 |
const name = "gelf" |
| 19 | 19 |
|
| 20 |
-type GelfLogger struct {
|
|
| 20 |
+type gelfLogger struct {
|
|
| 21 | 21 |
writer *gelf.Writer |
| 22 | 22 |
ctx logger.Context |
| 23 |
- fields GelfFields |
|
| 23 |
+ fields gelfFields |
|
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 |
-type GelfFields struct {
|
|
| 26 |
+type gelfFields struct {
|
|
| 27 | 27 |
hostname string |
| 28 |
- containerId string |
|
| 28 |
+ containerID string |
|
| 29 | 29 |
containerName string |
| 30 |
- imageId string |
|
| 30 |
+ imageID string |
|
| 31 | 31 |
imageName string |
| 32 | 32 |
command string |
| 33 | 33 |
tag string |
| ... | ... |
@@ -43,6 +45,9 @@ func init() {
|
| 43 | 43 |
} |
| 44 | 44 |
} |
| 45 | 45 |
|
| 46 |
+// New creates a gelf logger using the configuration passed in on the |
|
| 47 |
+// context. Supported context configuration variables are |
|
| 48 |
+// gelf-address, & gelf-tag. |
|
| 46 | 49 |
func New(ctx logger.Context) (logger.Logger, error) {
|
| 47 | 50 |
// parse gelf address |
| 48 | 51 |
address, err := parseAddress(ctx.Config["gelf-address"]) |
| ... | ... |
@@ -59,11 +64,11 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
| 59 | 59 |
// remove trailing slash from container name |
| 60 | 60 |
containerName := bytes.TrimLeft([]byte(ctx.ContainerName), "/") |
| 61 | 61 |
|
| 62 |
- fields := GelfFields{
|
|
| 62 |
+ fields := gelfFields{
|
|
| 63 | 63 |
hostname: hostname, |
| 64 |
- containerId: ctx.ContainerID, |
|
| 64 |
+ containerID: ctx.ContainerID, |
|
| 65 | 65 |
containerName: string(containerName), |
| 66 |
- imageId: ctx.ContainerImageID, |
|
| 66 |
+ imageID: ctx.ContainerImageID, |
|
| 67 | 67 |
imageName: ctx.ContainerImageName, |
| 68 | 68 |
command: ctx.Command(), |
| 69 | 69 |
tag: ctx.Config["gelf-tag"], |
| ... | ... |
@@ -76,14 +81,14 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
| 76 | 76 |
return nil, fmt.Errorf("gelf: cannot connect to GELF endpoint: %s %v", address, err)
|
| 77 | 77 |
} |
| 78 | 78 |
|
| 79 |
- return &GelfLogger{
|
|
| 79 |
+ return &gelfLogger{
|
|
| 80 | 80 |
writer: gelfWriter, |
| 81 | 81 |
ctx: ctx, |
| 82 | 82 |
fields: fields, |
| 83 | 83 |
}, nil |
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 |
-func (s *GelfLogger) Log(msg *logger.Message) error {
|
|
| 86 |
+func (s *gelfLogger) Log(msg *logger.Message) error {
|
|
| 87 | 87 |
// remove trailing and leading whitespace |
| 88 | 88 |
short := bytes.TrimSpace([]byte(msg.Line)) |
| 89 | 89 |
|
| ... | ... |
@@ -99,9 +104,9 @@ func (s *GelfLogger) Log(msg *logger.Message) error {
|
| 99 | 99 |
TimeUnix: float64(msg.Timestamp.UnixNano()/int64(time.Millisecond)) / 1000.0, |
| 100 | 100 |
Level: level, |
| 101 | 101 |
Extra: map[string]interface{}{
|
| 102 |
- "_container_id": s.fields.containerId, |
|
| 102 |
+ "_container_id": s.fields.containerID, |
|
| 103 | 103 |
"_container_name": s.fields.containerName, |
| 104 |
- "_image_id": s.fields.imageId, |
|
| 104 |
+ "_image_id": s.fields.imageID, |
|
| 105 | 105 |
"_image_name": s.fields.imageName, |
| 106 | 106 |
"_command": s.fields.command, |
| 107 | 107 |
"_tag": s.fields.tag, |
| ... | ... |
@@ -115,14 +120,16 @@ func (s *GelfLogger) Log(msg *logger.Message) error {
|
| 115 | 115 |
return nil |
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 |
-func (s *GelfLogger) Close() error {
|
|
| 118 |
+func (s *gelfLogger) Close() error {
|
|
| 119 | 119 |
return s.writer.Close() |
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 |
-func (s *GelfLogger) Name() string {
|
|
| 122 |
+func (s *gelfLogger) Name() string {
|
|
| 123 | 123 |
return name |
| 124 | 124 |
} |
| 125 | 125 |
|
| 126 |
+// ValidateLogOpt looks for gelf specific log options gelf-address, & |
|
| 127 |
+// gelf-tag. |
|
| 126 | 128 |
func ValidateLogOpt(cfg map[string]string) error {
|
| 127 | 129 |
for key := range cfg {
|
| 128 | 130 |
switch key {
|
| ... | ... |
@@ -1,5 +1,7 @@ |
| 1 | 1 |
// +build linux |
| 2 | 2 |
|
| 3 |
+// Package journald provides the log driver for forwarding server logs |
|
| 4 |
+// to endpoints that receive the systemd format. |
|
| 3 | 5 |
package journald |
| 4 | 6 |
|
| 5 | 7 |
import ( |
| ... | ... |
@@ -12,7 +14,7 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
const name = "journald" |
| 14 | 14 |
|
| 15 |
-type Journald struct {
|
|
| 15 |
+type journald struct {
|
|
| 16 | 16 |
Jmap map[string]string |
| 17 | 17 |
} |
| 18 | 18 |
|
| ... | ... |
@@ -22,6 +24,9 @@ func init() {
|
| 22 | 22 |
} |
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 |
+// New creates a journald logger using the configuration passed in on |
|
| 26 |
+// the context. Supported context configuration variables are |
|
| 27 |
+// syslog-address, syslog-facility, & syslog-tag. |
|
| 25 | 28 |
func New(ctx logger.Context) (logger.Logger, error) {
|
| 26 | 29 |
if !journal.Enabled() {
|
| 27 | 30 |
return nil, fmt.Errorf("journald is not enabled on this host")
|
| ... | ... |
@@ -36,20 +41,20 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
| 36 | 36 |
"CONTAINER_ID": ctx.ContainerID[:12], |
| 37 | 37 |
"CONTAINER_ID_FULL": ctx.ContainerID, |
| 38 | 38 |
"CONTAINER_NAME": name} |
| 39 |
- return &Journald{Jmap: jmap}, nil
|
|
| 39 |
+ return &journald{Jmap: jmap}, nil
|
|
| 40 | 40 |
} |
| 41 | 41 |
|
| 42 |
-func (s *Journald) Log(msg *logger.Message) error {
|
|
| 42 |
+func (s *journald) Log(msg *logger.Message) error {
|
|
| 43 | 43 |
if msg.Source == "stderr" {
|
| 44 | 44 |
return journal.Send(string(msg.Line), journal.PriErr, s.Jmap) |
| 45 | 45 |
} |
| 46 | 46 |
return journal.Send(string(msg.Line), journal.PriInfo, s.Jmap) |
| 47 | 47 |
} |
| 48 | 48 |
|
| 49 |
-func (s *Journald) Close() error {
|
|
| 49 |
+func (s *journald) Close() error {
|
|
| 50 | 50 |
return nil |
| 51 | 51 |
} |
| 52 | 52 |
|
| 53 |
-func (s *Journald) Name() string {
|
|
| 53 |
+func (s *journald) Name() string {
|
|
| 54 | 54 |
return name |
| 55 | 55 |
} |
| ... | ... |
@@ -1,3 +1,6 @@ |
| 1 |
+// Package jsonfilelog provides the default Logger implementation for |
|
| 2 |
+// Docker logging. This logger logs to files on the host server in the |
|
| 3 |
+// JSON format. |
|
| 1 | 4 |
package jsonfilelog |
| 2 | 5 |
|
| 3 | 6 |
import ( |
| ... | ... |
@@ -23,12 +26,12 @@ import ( |
| 23 | 23 |
) |
| 24 | 24 |
|
| 25 | 25 |
const ( |
| 26 |
+ // Name is the name of the file that the jsonlogger logs to. |
|
| 26 | 27 |
Name = "json-file" |
| 27 | 28 |
maxJSONDecodeRetry = 10 |
| 28 | 29 |
) |
| 29 | 30 |
|
| 30 |
-// JSONFileLogger is Logger implementation for default docker logging: |
|
| 31 |
-// JSON objects to file |
|
| 31 |
+// JSONFileLogger is Logger implementation for default Docker logging. |
|
| 32 | 32 |
type JSONFileLogger struct {
|
| 33 | 33 |
buf *bytes.Buffer |
| 34 | 34 |
f *os.File // store for closing |
| ... | ... |
@@ -49,7 +52,8 @@ func init() {
|
| 49 | 49 |
} |
| 50 | 50 |
} |
| 51 | 51 |
|
| 52 |
-// New creates new JSONFileLogger which writes to filename |
|
| 52 |
+// New creates new JSONFileLogger which writes to filename passed in |
|
| 53 |
+// on given context. |
|
| 53 | 54 |
func New(ctx logger.Context) (logger.Logger, error) {
|
| 54 | 55 |
log, err := os.OpenFile(ctx.LogPath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600) |
| 55 | 56 |
if err != nil {
|
| ... | ... |
@@ -63,14 +67,14 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
| 63 | 63 |
return nil, err |
| 64 | 64 |
} |
| 65 | 65 |
} |
| 66 |
- var maxFiles int = 1 |
|
| 66 |
+ var maxFiles = 1 |
|
| 67 | 67 |
if maxFileString, ok := ctx.Config["max-file"]; ok {
|
| 68 | 68 |
maxFiles, err = strconv.Atoi(maxFileString) |
| 69 | 69 |
if err != nil {
|
| 70 | 70 |
return nil, err |
| 71 | 71 |
} |
| 72 | 72 |
if maxFiles < 1 {
|
| 73 |
- return nil, fmt.Errorf("max-files cannot be less than 1.")
|
|
| 73 |
+ return nil, fmt.Errorf("max-files cannot be less than 1")
|
|
| 74 | 74 |
} |
| 75 | 75 |
} |
| 76 | 76 |
return &JSONFileLogger{
|
| ... | ... |
@@ -84,7 +88,7 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
| 84 | 84 |
}, nil |
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 |
-// Log converts logger.Message to jsonlog.JSONLog and serializes it to file |
|
| 87 |
+// Log converts logger.Message to jsonlog.JSONLog and serializes it to file. |
|
| 88 | 88 |
func (l *JSONFileLogger) Log(msg *logger.Message) error {
|
| 89 | 89 |
l.mu.Lock() |
| 90 | 90 |
defer l.mu.Unlock() |
| ... | ... |
@@ -153,6 +157,7 @@ func rotate(name string, n int) error {
|
| 153 | 153 |
return nil |
| 154 | 154 |
} |
| 155 | 155 |
|
| 156 |
+// backup renames a file from curr to old, creating an empty file curr if it does not exist. |
|
| 156 | 157 |
func backup(old, curr string) error {
|
| 157 | 158 |
if _, err := os.Stat(old); !os.IsNotExist(err) {
|
| 158 | 159 |
err := os.Remove(old) |
| ... | ... |
@@ -170,6 +175,7 @@ func backup(old, curr string) error {
|
| 170 | 170 |
return os.Rename(curr, old) |
| 171 | 171 |
} |
| 172 | 172 |
|
| 173 |
+// ValidateLogOpt looks for json specific log options max-file & max-size. |
|
| 173 | 174 |
func ValidateLogOpt(cfg map[string]string) error {
|
| 174 | 175 |
for key := range cfg {
|
| 175 | 176 |
switch key {
|
| ... | ... |
@@ -182,11 +188,12 @@ func ValidateLogOpt(cfg map[string]string) error {
|
| 182 | 182 |
return nil |
| 183 | 183 |
} |
| 184 | 184 |
|
| 185 |
+// LogPath returns the location the given json logger logs to. |
|
| 185 | 186 |
func (l *JSONFileLogger) LogPath() string {
|
| 186 | 187 |
return l.ctx.LogPath |
| 187 | 188 |
} |
| 188 | 189 |
|
| 189 |
-// Close closes underlying file and signals all readers to stop |
|
| 190 |
+// Close closes underlying file and signals all readers to stop. |
|
| 190 | 191 |
func (l *JSONFileLogger) Close() error {
|
| 191 | 192 |
l.mu.Lock() |
| 192 | 193 |
err := l.f.Close() |
| ... | ... |
@@ -198,7 +205,7 @@ func (l *JSONFileLogger) Close() error {
|
| 198 | 198 |
return err |
| 199 | 199 |
} |
| 200 | 200 |
|
| 201 |
-// Name returns name of this logger |
|
| 201 |
+// Name returns name of this logger. |
|
| 202 | 202 |
func (l *JSONFileLogger) Name() string {
|
| 203 | 203 |
return Name |
| 204 | 204 |
} |
| ... | ... |
@@ -216,7 +223,8 @@ func decodeLogLine(dec *json.Decoder, l *jsonlog.JSONLog) (*logger.Message, erro |
| 216 | 216 |
return msg, nil |
| 217 | 217 |
} |
| 218 | 218 |
|
| 219 |
-// Reads from the log file |
|
| 219 |
+// ReadLogs implements the logger's LogReader interface for the logs |
|
| 220 |
+// created by this driver. |
|
| 220 | 221 |
func (l *JSONFileLogger) ReadLogs(config logger.ReadConfig) *logger.LogWatcher {
|
| 221 | 222 |
logWatcher := logger.NewLogWatcher() |
| 222 | 223 |
|
| ... | ... |
@@ -326,7 +334,7 @@ func followLogs(f *os.File, logWatcher *logger.LogWatcher, notifyRotate chan int |
| 326 | 326 |
// try again because this shouldn't happen |
| 327 | 327 |
if _, ok := err.(*json.SyntaxError); ok && retries <= maxJSONDecodeRetry {
|
| 328 | 328 |
dec = json.NewDecoder(f) |
| 329 |
- retries += 1 |
|
| 329 |
+ retries++ |
|
| 330 | 330 |
continue |
| 331 | 331 |
} |
| 332 | 332 |
logWatcher.Err <- err |
| ... | ... |
@@ -1,3 +1,10 @@ |
| 1 |
+// Package logger defines interfaces that logger drivers implement to |
|
| 2 |
+// log messages. |
|
| 3 |
+// |
|
| 4 |
+// The other half of a logger driver is the implementation of the |
|
| 5 |
+// factory, which holds the contextual instance information that |
|
| 6 |
+// allows multiple loggers of the same type to perform different |
|
| 7 |
+// actions, such as logging to different locations. |
|
| 1 | 8 |
package logger |
| 2 | 9 |
|
| 3 | 10 |
import ( |
| ... | ... |
@@ -7,16 +14,16 @@ import ( |
| 7 | 7 |
"github.com/docker/docker/pkg/timeutils" |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 |
-// ErrReadLogsNotSupported is returned when the logger does not support reading logs |
|
| 10 |
+// ErrReadLogsNotSupported is returned when the logger does not support reading logs. |
|
| 11 | 11 |
var ErrReadLogsNotSupported = errors.New("configured logging reader does not support reading")
|
| 12 | 12 |
|
| 13 | 13 |
const ( |
| 14 |
- // TimeFormat is the time format used for timestamps sent to log readers |
|
| 14 |
+ // TimeFormat is the time format used for timestamps sent to log readers. |
|
| 15 | 15 |
TimeFormat = timeutils.RFC3339NanoFixed |
| 16 | 16 |
logWatcherBufferSize = 4096 |
| 17 | 17 |
) |
| 18 | 18 |
|
| 19 |
-// Message is datastructure that represents record from some container |
|
| 19 |
+// Message is datastructure that represents record from some container. |
|
| 20 | 20 |
type Message struct {
|
| 21 | 21 |
ContainerID string |
| 22 | 22 |
Line []byte |
| ... | ... |
@@ -24,31 +31,31 @@ type Message struct {
|
| 24 | 24 |
Timestamp time.Time |
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 |
-// Logger is the interface for docker logging drivers |
|
| 27 |
+// Logger is the interface for docker logging drivers. |
|
| 28 | 28 |
type Logger interface {
|
| 29 | 29 |
Log(*Message) error |
| 30 | 30 |
Name() string |
| 31 | 31 |
Close() error |
| 32 | 32 |
} |
| 33 | 33 |
|
| 34 |
-// ReadConfig is the configuration passed into ReadLogs |
|
| 34 |
+// ReadConfig is the configuration passed into ReadLogs. |
|
| 35 | 35 |
type ReadConfig struct {
|
| 36 | 36 |
Since time.Time |
| 37 | 37 |
Tail int |
| 38 | 38 |
Follow bool |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
-// LogReader is the interface for reading log messages for loggers that support reading |
|
| 41 |
+// LogReader is the interface for reading log messages for loggers that support reading. |
|
| 42 | 42 |
type LogReader interface {
|
| 43 | 43 |
// Read logs from underlying logging backend |
| 44 | 44 |
ReadLogs(ReadConfig) *LogWatcher |
| 45 | 45 |
} |
| 46 | 46 |
|
| 47 |
-// LogWatcher is used when consuming logs read from the LogReader interface |
|
| 47 |
+// LogWatcher is used when consuming logs read from the LogReader interface. |
|
| 48 | 48 |
type LogWatcher struct {
|
| 49 |
- // For sending log messages to a reader |
|
| 49 |
+ // For sending log messages to a reader. |
|
| 50 | 50 |
Msg chan *Message |
| 51 |
- // For sending error messages that occur while while reading logs |
|
| 51 |
+ // For sending error messages that occur while while reading logs. |
|
| 52 | 52 |
Err chan error |
| 53 | 53 |
closeNotifier chan struct{}
|
| 54 | 54 |
} |
| ... | ... |
@@ -62,13 +69,14 @@ func NewLogWatcher() *LogWatcher {
|
| 62 | 62 |
} |
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 |
-// Close notifies the underlying log reader to stop |
|
| 65 |
+// Close notifies the underlying log reader to stop. |
|
| 66 | 66 |
func (w *LogWatcher) Close() {
|
| 67 | 67 |
close(w.closeNotifier) |
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 |
-// WatchClose returns a channel receiver that receives notification when the watcher has been closed |
|
| 71 |
-// This should only be called from one goroutine |
|
| 70 |
+// WatchClose returns a channel receiver that receives notification |
|
| 71 |
+// when the watcher has been closed. This should only be called from |
|
| 72 |
+// one goroutine. |
|
| 72 | 73 |
func (w *LogWatcher) WatchClose() <-chan struct{} {
|
| 73 | 74 |
return w.closeNotifier |
| 74 | 75 |
} |
| ... | ... |
@@ -1,5 +1,6 @@ |
| 1 | 1 |
// +build linux |
| 2 | 2 |
|
| 3 |
+// Package syslog provides the logdriver for forwarding server logs to syslog endpoints. |
|
| 3 | 4 |
package syslog |
| 4 | 5 |
|
| 5 | 6 |
import ( |
| ... | ... |
@@ -43,7 +44,7 @@ var facilities = map[string]syslog.Priority{
|
| 43 | 43 |
"local7": syslog.LOG_LOCAL7, |
| 44 | 44 |
} |
| 45 | 45 |
|
| 46 |
-type Syslog struct {
|
|
| 46 |
+type syslogger struct {
|
|
| 47 | 47 |
writer *syslog.Writer |
| 48 | 48 |
} |
| 49 | 49 |
|
| ... | ... |
@@ -56,6 +57,9 @@ func init() {
|
| 56 | 56 |
} |
| 57 | 57 |
} |
| 58 | 58 |
|
| 59 |
+// New creates a syslog logger using the configuration passed in on |
|
| 60 |
+// the context. Supported context configuration variables are |
|
| 61 |
+// syslog-address, syslog-facility, & syslog-tag. |
|
| 59 | 62 |
func New(ctx logger.Context) (logger.Logger, error) {
|
| 60 | 63 |
tag := ctx.Config["syslog-tag"] |
| 61 | 64 |
if tag == "" {
|
| ... | ... |
@@ -82,23 +86,23 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
| 82 | 82 |
return nil, err |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 |
- return &Syslog{
|
|
| 85 |
+ return &syslogger{
|
|
| 86 | 86 |
writer: log, |
| 87 | 87 |
}, nil |
| 88 | 88 |
} |
| 89 | 89 |
|
| 90 |
-func (s *Syslog) Log(msg *logger.Message) error {
|
|
| 90 |
+func (s *syslogger) Log(msg *logger.Message) error {
|
|
| 91 | 91 |
if msg.Source == "stderr" {
|
| 92 | 92 |
return s.writer.Err(string(msg.Line)) |
| 93 | 93 |
} |
| 94 | 94 |
return s.writer.Info(string(msg.Line)) |
| 95 | 95 |
} |
| 96 | 96 |
|
| 97 |
-func (s *Syslog) Close() error {
|
|
| 97 |
+func (s *syslogger) Close() error {
|
|
| 98 | 98 |
return s.writer.Close() |
| 99 | 99 |
} |
| 100 | 100 |
|
| 101 |
-func (s *Syslog) Name() string {
|
|
| 101 |
+func (s *syslogger) Name() string {
|
|
| 102 | 102 |
return name |
| 103 | 103 |
} |
| 104 | 104 |
|
| ... | ... |
@@ -132,12 +136,14 @@ func parseAddress(address string) (string, string, error) {
|
| 132 | 132 |
return "", "", nil |
| 133 | 133 |
} |
| 134 | 134 |
|
| 135 |
+// ValidateLogOpt looks for syslog specific log options |
|
| 136 |
+// syslog-address, syslog-facility, & syslog-tag. |
|
| 135 | 137 |
func ValidateLogOpt(cfg map[string]string) error {
|
| 136 | 138 |
for key := range cfg {
|
| 137 | 139 |
switch key {
|
| 138 | 140 |
case "syslog-address": |
| 139 |
- case "syslog-tag": |
|
| 140 | 141 |
case "syslog-facility": |
| 142 |
+ case "syslog-tag": |
|
| 141 | 143 |
default: |
| 142 | 144 |
return fmt.Errorf("unknown log opt '%s' for syslog log driver", key)
|
| 143 | 145 |
} |
| ... | ... |
@@ -22,6 +22,12 @@ packages=( |
| 22 | 22 |
daemon/execdriver/native/template |
| 23 | 23 |
daemon/graphdriver/aufs |
| 24 | 24 |
daemon/graphdriver/devmapper |
| 25 |
+ daemon/logger |
|
| 26 |
+ daemon/logger/fluentd |
|
| 27 |
+ daemon/logger/gelf |
|
| 28 |
+ daemon/logger/journald |
|
| 29 |
+ daemon/logger/jsonfilelog |
|
| 30 |
+ daemon/logger/syslog |
|
| 25 | 31 |
daemon/network |
| 26 | 32 |
docker |
| 27 | 33 |
dockerinit |