Selaa lähdekoodia

log driver - add ability to interpolate container context into the log tag field

Signed-off-by: Philip Monroe <phil@philmonroe.com>
Philip Monroe 10 vuotta sitten
vanhempi
commit
3be7146e14

+ 72 - 0
daemon/logger/context.go

@@ -0,0 +1,72 @@
+package logger
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"time"
+)
+
+// 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
+}
+
+// ID Returns the Container ID shortened to 12 characters.
+func (ctx *Context) ID() string {
+	return ctx.ContainerID[:12]
+}
+
+// FullID is an alias of ContainerID.
+func (ctx *Context) FullID() string {
+	return ctx.ContainerID
+}
+
+// Name returns the ContainerName without a preceding '/'.
+func (ctx *Context) Name() string {
+	return ctx.ContainerName[1:]
+}
+
+// ImageID returns the ContainerImageID shortened to 12 characters.
+func (ctx *Context) ImageID() string {
+	return ctx.ContainerImageID[:12]
+}
+
+// ImageFullID is an alias of ContainerID.
+func (ctx *Context) ImageFullID() string {
+	return ctx.ContainerImageID
+}
+
+// ImageName is an alias of ContainerImageName
+func (ctx *Context) ImageName() string {
+	return ctx.ContainerImageName
+}

+ 0 - 37
daemon/logger/factory.go

@@ -2,10 +2,7 @@ package logger
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"os"
-	"strings"
 	"sync"
 	"sync"
-	"time"
 )
 )
 
 
 // Creator builds a logging driver instance with given context.
 // Creator builds a logging driver instance with given context.
@@ -15,40 +12,6 @@ type Creator func(Context) (Logger, error)
 // logging implementation.
 // 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.
-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 {
 type logdriverFactory struct {
 	registry     map[string]Creator
 	registry     map[string]Creator
 	optValidator map[string]LogOptValidator
 	optValidator map[string]LogOptValidator

+ 7 - 26
daemon/logger/fluentd/fluentd.go

@@ -3,16 +3,15 @@
 package fluentd
 package fluentd
 
 
 import (
 import (
-	"bytes"
 	"fmt"
 	"fmt"
 	"math"
 	"math"
 	"net"
 	"net"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
-	"text/template"
 
 
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/daemon/logger"
 	"github.com/docker/docker/daemon/logger"
+	"github.com/docker/docker/daemon/logger/loggerutils"
 	"github.com/fluent/fluent-logger-golang/fluent"
 	"github.com/fluent/fluent-logger-golang/fluent"
 )
 )
 
 
@@ -23,12 +22,6 @@ type fluentd struct {
 	writer        *fluent.Fluent
 	writer        *fluent.Fluent
 }
 }
 
 
-type receiver struct {
-	ID     string
-	FullID string
-	Name   string
-}
-
 const (
 const (
 	name             = "fluentd"
 	name             = "fluentd"
 	defaultHostName  = "localhost"
 	defaultHostName  = "localhost"
@@ -48,10 +41,14 @@ func init() {
 func parseConfig(ctx logger.Context) (string, int, string, error) {
 func parseConfig(ctx logger.Context) (string, int, string, error) {
 	host := defaultHostName
 	host := defaultHostName
 	port := defaultPort
 	port := defaultPort
-	tag := "docker." + ctx.ContainerID[:12]
 
 
 	config := ctx.Config
 	config := ctx.Config
 
 
+	tag, err := loggerutils.ParseLogTag(ctx, "docker.{{.ID}}")
+	if err != nil {
+		return "", 0, "", err
+	}
+
 	if address := config["fluentd-address"]; address != "" {
 	if address := config["fluentd-address"]; address != "" {
 		if h, p, err := net.SplitHostPort(address); err != nil {
 		if h, p, err := net.SplitHostPort(address); err != nil {
 			if !strings.Contains(err.Error(), "missing port in address") {
 			if !strings.Contains(err.Error(), "missing port in address") {
@@ -68,23 +65,6 @@ func parseConfig(ctx logger.Context) (string, int, string, error) {
 		}
 		}
 	}
 	}
 
 
-	if config["fluentd-tag"] != "" {
-		receiver := &receiver{
-			ID:     ctx.ContainerID[:12],
-			FullID: ctx.ContainerID,
-			Name:   ctx.ContainerName,
-		}
-		tmpl, err := template.New("tag").Parse(config["fluentd-tag"])
-		if err != nil {
-			return "", 0, "", err
-		}
-		buf := new(bytes.Buffer)
-		if err := tmpl.Execute(buf, receiver); err != nil {
-			return "", 0, "", err
-		}
-		tag = buf.String()
-	}
-
 	return host, port, tag, nil
 	return host, port, tag, nil
 }
 }
 
 
@@ -130,6 +110,7 @@ func ValidateLogOpt(cfg map[string]string) error {
 		switch key {
 		switch key {
 		case "fluentd-address":
 		case "fluentd-address":
 		case "fluentd-tag":
 		case "fluentd-tag":
+		case "tag":
 		default:
 		default:
 			return fmt.Errorf("unknown log opt '%s' for fluentd log driver", key)
 			return fmt.Errorf("unknown log opt '%s' for fluentd log driver", key)
 		}
 		}

+ 9 - 1
daemon/logger/gelf/gelf.go

@@ -14,6 +14,7 @@ import (
 	"github.com/Graylog2/go-gelf/gelf"
 	"github.com/Graylog2/go-gelf/gelf"
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/daemon/logger"
 	"github.com/docker/docker/daemon/logger"
+	"github.com/docker/docker/daemon/logger/loggerutils"
 	"github.com/docker/docker/pkg/urlutil"
 	"github.com/docker/docker/pkg/urlutil"
 )
 )
 
 
@@ -64,6 +65,12 @@ 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), "/")
 
 
+	// parse log tag
+	tag, err := loggerutils.ParseLogTag(ctx, "")
+	if err != nil {
+		return nil, err
+	}
+
 	fields := gelfFields{
 	fields := gelfFields{
 		hostname:      hostname,
 		hostname:      hostname,
 		containerID:   ctx.ContainerID,
 		containerID:   ctx.ContainerID,
@@ -71,7 +78,7 @@ func New(ctx logger.Context) (logger.Logger, error) {
 		imageID:       ctx.ContainerImageID,
 		imageID:       ctx.ContainerImageID,
 		imageName:     ctx.ContainerImageName,
 		imageName:     ctx.ContainerImageName,
 		command:       ctx.Command(),
 		command:       ctx.Command(),
-		tag:           ctx.Config["gelf-tag"],
+		tag:           tag,
 		created:       ctx.ContainerCreated,
 		created:       ctx.ContainerCreated,
 	}
 	}
 
 
@@ -135,6 +142,7 @@ func ValidateLogOpt(cfg map[string]string) error {
 		switch key {
 		switch key {
 		case "gelf-address":
 		case "gelf-address":
 		case "gelf-tag":
 		case "gelf-tag":
+		case "tag":
 		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)
 		}
 		}

+ 46 - 0
daemon/logger/loggerutils/log_tag.go

@@ -0,0 +1,46 @@
+package loggerutils
+
+import (
+	"bytes"
+	"fmt"
+	"text/template"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/daemon/logger"
+)
+
+// ParseLogTag generates a context aware tag for consistency across different
+// log drivers based on the context of the running container.
+func ParseLogTag(ctx logger.Context, defaultTemplate string) (string, error) {
+	tagTemplate := lookupTagTemplate(ctx, defaultTemplate)
+
+	tmpl, err := template.New("log-tag").Parse(tagTemplate)
+	if err != nil {
+		return "", err
+	}
+	buf := new(bytes.Buffer)
+	if err := tmpl.Execute(buf, &ctx); err != nil {
+		return "", err
+	}
+
+	return buf.String(), nil
+}
+
+func lookupTagTemplate(ctx logger.Context, defaultTemplate string) string {
+	tagTemplate := ctx.Config["tag"]
+
+	deprecatedConfigs := []string{"syslog-tag", "gelf-tag", "fluentd-tag"}
+	for i := 0; tagTemplate == "" && i < len(deprecatedConfigs); i++ {
+		cfg := deprecatedConfigs[i]
+		if ctx.Config[cfg] != "" {
+			tagTemplate = ctx.Config[cfg]
+			logrus.Warn(fmt.Sprintf("Using log tag from deprecated log-opt '%s'. Please use: --log-opt tag=\"%s\"", cfg, tagTemplate))
+		}
+	}
+
+	if tagTemplate == "" {
+		tagTemplate = defaultTemplate
+	}
+
+	return tagTemplate
+}

+ 58 - 0
daemon/logger/loggerutils/log_tag_test.go

@@ -0,0 +1,58 @@
+package loggerutils
+
+import (
+	"testing"
+
+	"github.com/docker/docker/daemon/logger"
+)
+
+func TestParseLogTagDefaultTag(t *testing.T) {
+	ctx := buildContext(map[string]string{})
+	tag, e := ParseLogTag(ctx, "{{.ID}}")
+	assertTag(t, e, tag, ctx.ID())
+}
+
+func TestParseLogTag(t *testing.T) {
+	ctx := buildContext(map[string]string{"tag": "{{.ImageName}}/{{.Name}}/{{.ID}}"})
+	tag, e := ParseLogTag(ctx, "{{.ID}}")
+	assertTag(t, e, tag, "test-image/test-container/container-ab")
+}
+
+func TestParseLogTagSyslogTag(t *testing.T) {
+	ctx := buildContext(map[string]string{"syslog-tag": "{{.ImageName}}/{{.Name}}/{{.ID}}"})
+	tag, e := ParseLogTag(ctx, "{{.ID}}")
+	assertTag(t, e, tag, "test-image/test-container/container-ab")
+}
+
+func TestParseLogTagGelfTag(t *testing.T) {
+	ctx := buildContext(map[string]string{"gelf-tag": "{{.ImageName}}/{{.Name}}/{{.ID}}"})
+	tag, e := ParseLogTag(ctx, "{{.ID}}")
+	assertTag(t, e, tag, "test-image/test-container/container-ab")
+}
+
+func TestParseLogTagFluentdTag(t *testing.T) {
+	ctx := buildContext(map[string]string{"fluentd-tag": "{{.ImageName}}/{{.Name}}/{{.ID}}"})
+	tag, e := ParseLogTag(ctx, "{{.ID}}")
+	assertTag(t, e, tag, "test-image/test-container/container-ab")
+}
+
+// Helpers
+
+func buildContext(cfg map[string]string) logger.Context {
+	return logger.Context{
+		ContainerID:        "container-abcdefghijklmnopqrstuvwxyz01234567890",
+		ContainerName:      "/test-container",
+		ContainerImageID:   "image-abcdefghijklmnopqrstuvwxyz01234567890",
+		ContainerImageName: "test-image",
+		Config:             cfg,
+	}
+}
+
+func assertTag(t *testing.T, e error, tag string, expected string) {
+	if e != nil {
+		t.Fatalf("Error generating tag: %q", e)
+	}
+	if tag != expected {
+		t.Fatalf("Wrong tag: %q, should be %q", tag, expected)
+	}
+}

+ 5 - 3
daemon/logger/syslog/syslog.go

@@ -16,6 +16,7 @@ import (
 
 
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/daemon/logger"
 	"github.com/docker/docker/daemon/logger"
+	"github.com/docker/docker/daemon/logger/loggerutils"
 	"github.com/docker/docker/pkg/urlutil"
 	"github.com/docker/docker/pkg/urlutil"
 )
 )
 
 
@@ -61,9 +62,9 @@ func init() {
 // the context. Supported context configuration variables are
 // the context. Supported context configuration variables are
 // syslog-address, syslog-facility, & syslog-tag.
 // 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"]
-	if tag == "" {
-		tag = ctx.ContainerID[:12]
+	tag, err := loggerutils.ParseLogTag(ctx, "{{.ID}}")
+	if err != nil {
+		return nil, err
 	}
 	}
 
 
 	proto, address, err := parseAddress(ctx.Config["syslog-address"])
 	proto, address, err := parseAddress(ctx.Config["syslog-address"])
@@ -146,6 +147,7 @@ func ValidateLogOpt(cfg map[string]string) error {
 		case "syslog-address":
 		case "syslog-address":
 		case "syslog-facility":
 		case "syslog-facility":
 		case "syslog-tag":
 		case "syslog-tag":
+		case "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)
 		}
 		}

+ 15 - 2
docs/misc/deprecated.md

@@ -12,13 +12,26 @@ parent = "mn_use_docker"
 
 
 The following list of features are deprecated.
 The following list of features are deprecated.
 
 
+### Driver Specific Log Tags
+**Deprecated In Release: v1.9**
+
+**Target For Removal In Release: v1.11**
+
+Log tags are now generated in a standard way across different logging drivers.
+Because of which, the driver specific log tag options `syslog-tag`, `gelf-tag` and
+`fluentd-tag` have been deprecated in favor of the generic `tag` option.
+
+    docker --log-driver=syslog --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}"
+
+
+
 ### LXC built-in exec driver
 ### LXC built-in exec driver
 **Deprecated In Release: v1.8**
 **Deprecated In Release: v1.8**
 
 
 **Target For Removal In Release: v1.10**
 **Target For Removal In Release: v1.10**
 
 
 The built-in LXC execution driver is deprecated for an external implementation.
 The built-in LXC execution driver is deprecated for an external implementation.
-The lxc-conf flag and API fields will also be removed. 
+The lxc-conf flag and API fields will also be removed.
 
 
 ### Old Command Line Options
 ### Old Command Line Options
 **Deprecated In Release: [v1.8.0](/release-notes/#docker-engine-1-8-0)**
 **Deprecated In Release: [v1.8.0](/release-notes/#docker-engine-1-8-0)**
@@ -29,7 +42,7 @@ The flags `-d` and `--daemon` are deprecated in favor of the `daemon` subcommand
 
 
     docker daemon -H ...
     docker daemon -H ...
 
 
-The following single-dash (`-opt`) variant of certain command line options 
+The following single-dash (`-opt`) variant of certain command line options
 are deprecated and replaced with double-dash options (`--opt`):
 are deprecated and replaced with double-dash options (`--opt`):
 
 
     docker attach -nostdin
     docker attach -nostdin

+ 6 - 17
docs/reference/logging/fluentd.md

@@ -5,6 +5,7 @@ description = "Describes how to use the fluentd logging driver."
 keywords = ["Fluentd, docker, logging, driver"]
 keywords = ["Fluentd, docker, logging, driver"]
 [menu.main]
 [menu.main]
 parent = "smn_logging"
 parent = "smn_logging"
+weight=2
 +++
 +++
 <![end-metadata]-->
 <![end-metadata]-->
 
 
@@ -32,7 +33,7 @@ The `docker logs` command is not available for this logging driver.
 Some options are supported by specifying `--log-opt` as many times as needed:
 Some options are supported by specifying `--log-opt` as many times as needed:
 
 
  - `fluentd-address`: specify `host:port` to connect `localhost:24224`
  - `fluentd-address`: specify `host:port` to connect `localhost:24224`
- - `fluentd-tag`: specify tag for fluentd message, which interpret some markup, ex `{{.ID}}`, `{{.FullID}}` or `{{.Name}}` `docker.{{.ID}}`
+ - `tag`: specify tag for fluentd message, which interpret some markup, ex `{{.ID}}`, `{{.FullID}}` or `{{.Name}}` `docker.{{.ID}}`
 
 
 
 
 Configure the default logging driver by passing the
 Configure the default logging driver by passing the
@@ -65,24 +66,12 @@ By default, the logging driver connects to `localhost:24224`. Supply the
 
 
     docker run --log-driver=fluentd --log-opt fluentd-address=myhost.local:24224
     docker run --log-driver=fluentd --log-opt fluentd-address=myhost.local:24224
 
 
-### fluentd-tag
+### tag
 
 
-Every Fluentd's event has a tag that indicates where the log comes from. By
-default, the driver uses the `docker.{{.ID}}` tag.  Use the `fluentd-tag` option
-to change this behavior.
+By default, Docker uses the first 12 characters of the container ID to tag log messages.
+Refer to the [log tag option documentation](/reference/logging/log_tags/) for customizing
+the log tag format.
 
 
-When specifying a `fluentd-tag` value, you can use the following markup tags:
-
- - `{{.ID}}`: short container id (12 characters)
- - `{{.FullID}}`: full container id
- - `{{.Name}}`: container name
-
-## Note regarding container names
-
-At startup time, the system sets the `container_name` field and `{{.Name}}`
-in the tags to their values at startup. If you use `docker rename` to rename a
-container, the new name is not be reflected in  `fluentd` messages. Instead,
-these messages continue to use the original container name.
 
 
 ## Fluentd daemon management with Docker
 ## Fluentd daemon management with Docker
 
 

+ 3 - 2
docs/reference/logging/index.md

@@ -1,7 +1,7 @@
 <!--[metadata]>
 <!--[metadata]>
 +++
 +++
-title = "Logging Drivers"
-description = "Logging Drivers"
+title = "Logging"
+description = "Logging and Logging Drivers"
 keywords = [" docker, logging, driver"]
 keywords = [" docker, logging, driver"]
 [menu.main]
 [menu.main]
 parent = "smn_administrate"
 parent = "smn_administrate"
@@ -14,6 +14,7 @@ weight=8
 # Logging Drivers
 # Logging Drivers
 
 
 * [Configuring logging drivers](overview)
 * [Configuring logging drivers](overview)
+* [Configuring log tags](log_tags)
 * [Fluentd logging driver](fluentd)
 * [Fluentd logging driver](fluentd)
 * [Journald logging driver](journald)
 * [Journald logging driver](journald)
 * [Amazon CloudWatch Logs logging driver](awslogs)
 * [Amazon CloudWatch Logs logging driver](awslogs)

+ 1 - 0
docs/reference/logging/journald.md

@@ -5,6 +5,7 @@ description = "Describes how to use the fluentd logging driver."
 keywords = ["Fluentd, docker, logging, driver"]
 keywords = ["Fluentd, docker, logging, driver"]
 [menu.main]
 [menu.main]
 parent = "smn_logging"
 parent = "smn_logging"
+weight = 2
 +++
 +++
 <![end-metadata]-->
 <![end-metadata]-->
 
 

+ 50 - 0
docs/reference/logging/log_tags.md

@@ -0,0 +1,50 @@
+<!--[metadata]>
++++
+title = "Log tags for logging driver"
+description = "Describes how to format tags for."
+keywords = ["docker, logging, driver, syslog, Fluentd, gelf"]
+[menu.main]
+parent = "smn_logging"
+weight = 1
++++
+<![end-metadata]-->
+
+# Log Tags
+
+The `tag` log option specifies how to format a tag that identifies the
+container's log messages. By default, the system uses the first 12 characters of
+the container id. To override this behavior, specify a `tag` option:
+
+```
+docker run --log-driver=fluentd --log-opt fluentd-address=myhost.local:24224 --log-opt tag="mailer"
+```
+
+Docker supports some special template markup you can use when specifying a tag's value:
+
+| Markup             | Description                                          |
+|--------------------|------------------------------------------------------|
+| `{{.ID}}`          | The first 12 characters of the container id.         |
+| `{{.FullID}}`      | The full container id.                               |
+| `{{.Name}}`        | The container name.                                  |
+| `{{.ImageID}}`     | The first 12 characters of the container's image id. |
+| `{{.ImageFullID}}` | The container's full image identifier.               |
+| `{{.ImageName}}`   | The name of the image used by the container.         |
+
+For example, specifying a `--log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}"` value yields `syslog` log lines like:
+
+```
+Aug  7 18:33:19 HOSTNAME docker/hello-world/foobar/5790672ab6a0[9103]: Hello from Docker.
+```
+
+At startup time, the system sets the `container_name` field and `{{.Name}}` in
+the tags. If you use `docker rename` to rename a container, the new name is not
+reflected in the log messages. Instead, these messages continue to use the
+original container name.
+
+For advanced usage, the generated tag's use [go
+templates](http://golang.org/pkg/text/template/) and the container's [logging
+context](https://github.com/docker/docker/blob/master/daemon/logger/context.go).
+
+>**Note**:The driver specific log options `syslog-tag`, `fluentd-tag` and
+>`gelf-tag` still work for backwards compatibility. However, going forward you
+>should standardize on using the generic `tag` log option instead.

+ 20 - 22
docs/reference/logging/overview.md

@@ -2,7 +2,7 @@
 +++
 +++
 title = "Configuring Logging Drivers"
 title = "Configuring Logging Drivers"
 description = "Configure logging driver."
 description = "Configure logging driver."
-keywords = ["Fluentd, docker, logging, driver"]
+keywords = ["docker, logging, driver, Fluentd"]
 [menu.main]
 [menu.main]
 parent = "smn_logging"
 parent = "smn_logging"
 weight=-1
 weight=-1
@@ -25,9 +25,9 @@ container's logging driver. The following options are supported:
 | `fluentd`   | Fluentd logging driver for Docker. Writes log messages to `fluentd` (forward input).                                          |
 | `fluentd`   | Fluentd logging driver for Docker. Writes log messages to `fluentd` (forward input).                                          |
 | `awslogs`   | Amazon CloudWatch Logs logging driver for Docker. Writes log messages to Amazon CloudWatch Logs.                              |
 | `awslogs`   | Amazon CloudWatch Logs logging driver for Docker. Writes log messages to Amazon CloudWatch Logs.                              |
 
 
-The `docker logs`command is available only for the `json-file` logging driver.  
+The `docker logs`command is available only for the `json-file` logging driver.
 
 
-### The json-file options
+## json-file options
 
 
 The following logging options are supported for the `json-file` logging driver:
 The following logging options are supported for the `json-file` logging driver:
 
 
@@ -39,16 +39,16 @@ Logs that reach `max-size` are rolled over. You can set the size in kilobytes(k)
 
 
 `max-file` specifies the maximum number of files that a log is rolled over before being discarded. eg `--log-opt max-file=100`. If `max-size` is not set, then `max-file` is not honored.
 `max-file` specifies the maximum number of files that a log is rolled over before being discarded. eg `--log-opt max-file=100`. If `max-size` is not set, then `max-file` is not honored.
 
 
-If `max-size` and `max-file` are set, `docker logs` only returns the log lines from the newest log file. 
+If `max-size` and `max-file` are set, `docker logs` only returns the log lines from the newest log file.
 
 
-### The syslog options
+## syslog options
 
 
 The following logging options are supported for the `syslog` logging driver:
 The following logging options are supported for the `syslog` logging driver:
 
 
     --log-opt syslog-address=[tcp|udp]://host:port
     --log-opt syslog-address=[tcp|udp]://host:port
     --log-opt syslog-address=unix://path
     --log-opt syslog-address=unix://path
     --log-opt syslog-facility=daemon
     --log-opt syslog-facility=daemon
-    --log-opt syslog-tag="mailer"
+    --log-opt tag="mailer"
 
 
 `syslog-address` specifies the remote syslog server address where the driver connects to.
 `syslog-address` specifies the remote syslog server address where the driver connects to.
 If not specified it defaults to the local unix socket of the running system.
 If not specified it defaults to the local unix socket of the running system.
@@ -83,22 +83,23 @@ the following named facilities:
 * `local6`
 * `local6`
 * `local7`
 * `local7`
 
 
-The `syslog-tag` specifies a tag that identifies the container's syslog messages. By default,
-the system uses the first 12 characters of the container id. To override this behavior, specify
-a `syslog-tag` option
+By default, Docker uses the first 12 characters of the container ID to tag log messages.
+Refer to the [log tag option documentation](/reference/logging/log_tags/) for customizing
+the log tag format.
 
 
-## Specify journald options
+
+## journald options
 
 
 The `journald` logging driver stores the container id in the journal's `CONTAINER_ID` field. For detailed information on
 The `journald` logging driver stores the container id in the journal's `CONTAINER_ID` field. For detailed information on
 working with this logging driver, see [the journald logging driver](/reference/logging/journald/)
 working with this logging driver, see [the journald logging driver](/reference/logging/journald/)
 reference documentation.
 reference documentation.
 
 
-## Specify gelf options
+## gelf options
 
 
 The GELF logging driver supports the following options:
 The GELF logging driver supports the following options:
 
 
     --log-opt gelf-address=udp://host:port
     --log-opt gelf-address=udp://host:port
-    --log-opt gelf-tag="database"
+    --log-opt tag="database"
 
 
 The `gelf-address` option specifies the remote GELF server address that the
 The `gelf-address` option specifies the remote GELF server address that the
 driver connects to. Currently, only `udp` is supported as the transport and you must
 driver connects to. Currently, only `udp` is supported as the transport and you must
@@ -107,24 +108,21 @@ driver to a GELF remote server at `192.168.0.42` on port `12201`
 
 
     $ docker run --log-driver=gelf --log-opt gelf-address=udp://192.168.0.42:12201
     $ docker run --log-driver=gelf --log-opt gelf-address=udp://192.168.0.42:12201
 
 
-The `gelf-tag` option specifies a tag for easy container identification.
+By default, Docker uses the first 12 characters of the container ID to tag log messages.
+Refer to the [log tag option documentation](/reference/logging/log_tags/) for customizing
+the log tag format.
+
 
 
-## Specify fluentd options
+## fluentd options
 
 
 You can use the `--log-opt NAME=VALUE` flag to specify these additional Fluentd logging driver options.
 You can use the `--log-opt NAME=VALUE` flag to specify these additional Fluentd logging driver options.
 
 
  - `fluentd-address`: specify `host:port` to connect [localhost:24224]
  - `fluentd-address`: specify `host:port` to connect [localhost:24224]
- - `fluentd-tag`: specify tag for `fluentd` message, 
-
-When specifying a `fluentd-tag` value, you can use the following markup tags:
-
- - `{{.ID}}`: short container id (12 characters)
- - `{{.FullID}}`: full container id
- - `{{.Name}}`: container name
+ - `tag`: specify tag for `fluentd` message,
 
 
 For example, to specify both additional options:
 For example, to specify both additional options:
 
 
-`docker run --log-driver=fluentd --log-opt fluentd-address=localhost:24224 --log-opt fluentd-tag=docker.{{.Name}}`
+`docker run --log-driver=fluentd --log-opt fluentd-address=localhost:24224 --log-opt tag=docker.{{.Name}}`
 
 
 If container cannot connect to the Fluentd daemon on the specified address,
 If container cannot connect to the Fluentd daemon on the specified address,
 the container stops immediately. For detailed information on working with this
 the container stops immediately. For detailed information on working with this