1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

add labels/env log option for gelf

this allows gelf logger to collect extra metadata from containers with
`--log-opt labels=label1,label2 --log-opt env=env1,env2`

Additional log field will be prefixed with `_` as per gelf protocol
https://www.graylog.org/resources/gelf/

Signed-off-by: Daniel Dao <dqminh@cloudflare.com>
This commit is contained in:
Daniel Dao 2015-10-04 21:03:11 +00:00 committed by Vincent Demeester
parent 656cdbb0e9
commit 5794a0190d
2 changed files with 68 additions and 36 deletions

View file

@ -22,6 +22,44 @@ type Context struct {
LogPath string LogPath string
} }
// ExtraAttributes returns the user-defined extra attributes (labels,
// environment variables) in key-value format. This can be used by log drivers
// that support metadata to add more context to a log.
func (ctx *Context) ExtraAttributes(keyMod func(string) string) map[string]string {
extra := make(map[string]string)
labels, ok := ctx.Config["labels"]
if ok && len(labels) > 0 {
for _, l := range strings.Split(labels, ",") {
if v, ok := ctx.ContainerLabels[l]; ok {
if keyMod != nil {
l = keyMod(l)
}
extra[l] = v
}
}
}
env, ok := ctx.Config["env"]
if ok && len(env) > 0 {
envMapping := make(map[string]string)
for _, e := range ctx.ContainerEnv {
if kv := strings.SplitN(e, "=", 2); len(kv) == 2 {
envMapping[kv[0]] = kv[1]
}
}
for _, l := range strings.Split(env, ",") {
if v, ok := envMapping[l]; ok {
if keyMod != nil {
l = keyMod(l)
}
extra[l] = v
}
}
}
return extra
}
// 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()

View file

@ -23,18 +23,8 @@ const name = "gelf"
type gelfLogger struct { type gelfLogger struct {
writer *gelf.Writer writer *gelf.Writer
ctx logger.Context ctx logger.Context
fields gelfFields
}
type gelfFields struct {
hostname string hostname string
containerID string extra map[string]interface{}
containerName string
imageID string
imageName string
command string
tag string
created time.Time
} }
func init() { func init() {
@ -71,15 +61,24 @@ func New(ctx logger.Context) (logger.Logger, error) {
return nil, err return nil, err
} }
fields := gelfFields{ extra := map[string]interface{}{
hostname: hostname, "_container_id": ctx.ContainerID,
containerID: ctx.ContainerID, "_container_name": string(containerName),
containerName: string(containerName), "_image_id": ctx.ContainerImageID,
imageID: ctx.ContainerImageID, "_image_name": ctx.ContainerImageName,
imageName: ctx.ContainerImageName, "_command": ctx.Command(),
command: ctx.Command(), "_tag": tag,
tag: tag, "_created": ctx.ContainerCreated,
created: ctx.ContainerCreated, }
extraAttrs := ctx.ExtraAttributes(func(key string) string {
if key[0] == '_' {
return key
}
return "_" + key
})
for k, v := range extraAttrs {
extra[k] = v
} }
// create new gelfWriter // create new gelfWriter
@ -91,7 +90,8 @@ func New(ctx logger.Context) (logger.Logger, error) {
return &gelfLogger{ return &gelfLogger{
writer: gelfWriter, writer: gelfWriter,
ctx: ctx, ctx: ctx,
fields: fields, hostname: hostname,
extra: extra,
}, nil }, nil
} }
@ -106,19 +106,11 @@ func (s *gelfLogger) Log(msg *logger.Message) error {
m := gelf.Message{ m := gelf.Message{
Version: "1.1", Version: "1.1",
Host: s.fields.hostname, Host: s.hostname,
Short: string(short), Short: string(short),
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: s.extra,
"_container_id": s.fields.containerID,
"_container_name": s.fields.containerName,
"_image_id": s.fields.imageID,
"_image_name": s.fields.imageName,
"_command": s.fields.command,
"_tag": s.fields.tag,
"_created": s.fields.created,
},
} }
if err := s.writer.WriteMessage(&m); err != nil { if err := s.writer.WriteMessage(&m); err != nil {
@ -143,6 +135,8 @@ func ValidateLogOpt(cfg map[string]string) error {
case "gelf-address": case "gelf-address":
case "gelf-tag": case "gelf-tag":
case "tag": case "tag":
case "labels":
case "env":
default: default:
return fmt.Errorf("unknown log opt '%s' for gelf log driver", key) return fmt.Errorf("unknown log opt '%s' for gelf log driver", key)
} }