зеркало из https://github.com/microsoft/docker.git
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:
Родитель
656cdbb0e9
Коммит
5794a0190d
|
@ -22,6 +22,44 @@ type Context struct {
|
|||
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.
|
||||
func (ctx *Context) Hostname() (string, error) {
|
||||
hostname, err := os.Hostname()
|
||||
|
|
|
@ -21,20 +21,10 @@ import (
|
|||
const name = "gelf"
|
||||
|
||||
type gelfLogger struct {
|
||||
writer *gelf.Writer
|
||||
ctx logger.Context
|
||||
fields gelfFields
|
||||
}
|
||||
|
||||
type gelfFields struct {
|
||||
hostname string
|
||||
containerID string
|
||||
containerName string
|
||||
imageID string
|
||||
imageName string
|
||||
command string
|
||||
tag string
|
||||
created time.Time
|
||||
writer *gelf.Writer
|
||||
ctx logger.Context
|
||||
hostname string
|
||||
extra map[string]interface{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -71,15 +61,24 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
fields := gelfFields{
|
||||
hostname: hostname,
|
||||
containerID: ctx.ContainerID,
|
||||
containerName: string(containerName),
|
||||
imageID: ctx.ContainerImageID,
|
||||
imageName: ctx.ContainerImageName,
|
||||
command: ctx.Command(),
|
||||
tag: tag,
|
||||
created: ctx.ContainerCreated,
|
||||
extra := map[string]interface{}{
|
||||
"_container_id": ctx.ContainerID,
|
||||
"_container_name": string(containerName),
|
||||
"_image_id": ctx.ContainerImageID,
|
||||
"_image_name": ctx.ContainerImageName,
|
||||
"_command": ctx.Command(),
|
||||
"_tag": tag,
|
||||
"_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
|
||||
|
@ -89,9 +88,10 @@ func New(ctx logger.Context) (logger.Logger, error) {
|
|||
}
|
||||
|
||||
return &gelfLogger{
|
||||
writer: gelfWriter,
|
||||
ctx: ctx,
|
||||
fields: fields,
|
||||
writer: gelfWriter,
|
||||
ctx: ctx,
|
||||
hostname: hostname,
|
||||
extra: extra,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -106,19 +106,11 @@ func (s *gelfLogger) Log(msg *logger.Message) error {
|
|||
|
||||
m := gelf.Message{
|
||||
Version: "1.1",
|
||||
Host: s.fields.hostname,
|
||||
Host: s.hostname,
|
||||
Short: string(short),
|
||||
TimeUnix: float64(msg.Timestamp.UnixNano()/int64(time.Millisecond)) / 1000.0,
|
||||
Level: level,
|
||||
Extra: map[string]interface{}{
|
||||
"_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,
|
||||
},
|
||||
Extra: s.extra,
|
||||
}
|
||||
|
||||
if err := s.writer.WriteMessage(&m); err != nil {
|
||||
|
@ -143,6 +135,8 @@ func ValidateLogOpt(cfg map[string]string) error {
|
|||
case "gelf-address":
|
||||
case "gelf-tag":
|
||||
case "tag":
|
||||
case "labels":
|
||||
case "env":
|
||||
default:
|
||||
return fmt.Errorf("unknown log opt '%s' for gelf log driver", key)
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче