1package logger // import "github.com/docker/docker/daemon/logger"
2
3import (
4	"fmt"
5	"os"
6	"regexp"
7	"strings"
8	"time"
9)
10
11// Info provides enough information for a logging driver to do its function.
12type Info struct {
13	Config              map[string]string
14	ContainerID         string
15	ContainerName       string
16	ContainerEntrypoint string
17	ContainerArgs       []string
18	ContainerImageID    string
19	ContainerImageName  string
20	ContainerCreated    time.Time
21	ContainerEnv        []string
22	ContainerLabels     map[string]string
23	LogPath             string
24	DaemonName          string
25}
26
27// ExtraAttributes returns the user-defined extra attributes (labels,
28// environment variables) in key-value format. This can be used by log drivers
29// that support metadata to add more context to a log.
30func (info *Info) ExtraAttributes(keyMod func(string) string) (map[string]string, error) {
31	extra := make(map[string]string)
32	labels, ok := info.Config["labels"]
33	if ok && len(labels) > 0 {
34		for _, l := range strings.Split(labels, ",") {
35			if v, ok := info.ContainerLabels[l]; ok {
36				if keyMod != nil {
37					l = keyMod(l)
38				}
39				extra[l] = v
40			}
41		}
42	}
43
44	labelsRegex, ok := info.Config["labels-regex"]
45	if ok && len(labelsRegex) > 0 {
46		re, err := regexp.Compile(labelsRegex)
47		if err != nil {
48			return nil, err
49		}
50		for k, v := range info.ContainerLabels {
51			if re.MatchString(k) {
52				if keyMod != nil {
53					k = keyMod(k)
54				}
55				extra[k] = v
56			}
57		}
58	}
59
60	envMapping := make(map[string]string)
61	for _, e := range info.ContainerEnv {
62		if kv := strings.SplitN(e, "=", 2); len(kv) == 2 {
63			envMapping[kv[0]] = kv[1]
64		}
65	}
66
67	env, ok := info.Config["env"]
68	if ok && len(env) > 0 {
69		for _, l := range strings.Split(env, ",") {
70			if v, ok := envMapping[l]; ok {
71				if keyMod != nil {
72					l = keyMod(l)
73				}
74				extra[l] = v
75			}
76		}
77	}
78
79	envRegex, ok := info.Config["env-regex"]
80	if ok && len(envRegex) > 0 {
81		re, err := regexp.Compile(envRegex)
82		if err != nil {
83			return nil, err
84		}
85		for k, v := range envMapping {
86			if re.MatchString(k) {
87				if keyMod != nil {
88					k = keyMod(k)
89				}
90				extra[k] = v
91			}
92		}
93	}
94
95	return extra, nil
96}
97
98// Hostname returns the hostname from the underlying OS.
99func (info *Info) Hostname() (string, error) {
100	hostname, err := os.Hostname()
101	if err != nil {
102		return "", fmt.Errorf("logger: can not resolve hostname: %v", err)
103	}
104	return hostname, nil
105}
106
107// Command returns the command that the container being logged was
108// started with. The Entrypoint is prepended to the container
109// arguments.
110func (info *Info) Command() string {
111	terms := []string{info.ContainerEntrypoint}
112	terms = append(terms, info.ContainerArgs...)
113	command := strings.Join(terms, " ")
114	return command
115}
116
117// ID Returns the Container ID shortened to 12 characters.
118func (info *Info) ID() string {
119	return info.ContainerID[:12]
120}
121
122// FullID is an alias of ContainerID.
123func (info *Info) FullID() string {
124	return info.ContainerID
125}
126
127// Name returns the ContainerName without a preceding '/'.
128func (info *Info) Name() string {
129	return strings.TrimPrefix(info.ContainerName, "/")
130}
131
132// ImageID returns the ContainerImageID shortened to 12 characters.
133func (info *Info) ImageID() string {
134	return info.ContainerImageID[:12]
135}
136
137// ImageFullID is an alias of ContainerImageID.
138func (info *Info) ImageFullID() string {
139	return info.ContainerImageID
140}
141
142// ImageName is an alias of ContainerImageName
143func (info *Info) ImageName() string {
144	return info.ContainerImageName
145}
146