diff options
Diffstat (limited to 'vendor/github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus/text_formatter.go')
-rw-r--r-- | vendor/github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus/text_formatter.go | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus/text_formatter.go new file mode 100644 index 0000000..06ef202 --- /dev/null +++ b/vendor/github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus/text_formatter.go | |||
@@ -0,0 +1,161 @@ | |||
1 | package logrus | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "fmt" | ||
6 | "runtime" | ||
7 | "sort" | ||
8 | "strings" | ||
9 | "time" | ||
10 | ) | ||
11 | |||
12 | const ( | ||
13 | nocolor = 0 | ||
14 | red = 31 | ||
15 | green = 32 | ||
16 | yellow = 33 | ||
17 | blue = 34 | ||
18 | gray = 37 | ||
19 | ) | ||
20 | |||
21 | var ( | ||
22 | baseTimestamp time.Time | ||
23 | isTerminal bool | ||
24 | ) | ||
25 | |||
26 | func init() { | ||
27 | baseTimestamp = time.Now() | ||
28 | isTerminal = IsTerminal() | ||
29 | } | ||
30 | |||
31 | func miniTS() int { | ||
32 | return int(time.Since(baseTimestamp) / time.Second) | ||
33 | } | ||
34 | |||
35 | type TextFormatter struct { | ||
36 | // Set to true to bypass checking for a TTY before outputting colors. | ||
37 | ForceColors bool | ||
38 | |||
39 | // Force disabling colors. | ||
40 | DisableColors bool | ||
41 | |||
42 | // Disable timestamp logging. useful when output is redirected to logging | ||
43 | // system that already adds timestamps. | ||
44 | DisableTimestamp bool | ||
45 | |||
46 | // Enable logging the full timestamp when a TTY is attached instead of just | ||
47 | // the time passed since beginning of execution. | ||
48 | FullTimestamp bool | ||
49 | |||
50 | // TimestampFormat to use for display when a full timestamp is printed | ||
51 | TimestampFormat string | ||
52 | |||
53 | // The fields are sorted by default for a consistent output. For applications | ||
54 | // that log extremely frequently and don't use the JSON formatter this may not | ||
55 | // be desired. | ||
56 | DisableSorting bool | ||
57 | } | ||
58 | |||
59 | func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { | ||
60 | var keys []string = make([]string, 0, len(entry.Data)) | ||
61 | for k := range entry.Data { | ||
62 | keys = append(keys, k) | ||
63 | } | ||
64 | |||
65 | if !f.DisableSorting { | ||
66 | sort.Strings(keys) | ||
67 | } | ||
68 | |||
69 | b := &bytes.Buffer{} | ||
70 | |||
71 | prefixFieldClashes(entry.Data) | ||
72 | |||
73 | isColorTerminal := isTerminal && (runtime.GOOS != "windows") | ||
74 | isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors | ||
75 | |||
76 | timestampFormat := f.TimestampFormat | ||
77 | if timestampFormat == "" { | ||
78 | timestampFormat = DefaultTimestampFormat | ||
79 | } | ||
80 | if isColored { | ||
81 | f.printColored(b, entry, keys, timestampFormat) | ||
82 | } else { | ||
83 | if !f.DisableTimestamp { | ||
84 | f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat)) | ||
85 | } | ||
86 | f.appendKeyValue(b, "level", entry.Level.String()) | ||
87 | if entry.Message != "" { | ||
88 | f.appendKeyValue(b, "msg", entry.Message) | ||
89 | } | ||
90 | for _, key := range keys { | ||
91 | f.appendKeyValue(b, key, entry.Data[key]) | ||
92 | } | ||
93 | } | ||
94 | |||
95 | b.WriteByte('\n') | ||
96 | return b.Bytes(), nil | ||
97 | } | ||
98 | |||
99 | func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { | ||
100 | var levelColor int | ||
101 | switch entry.Level { | ||
102 | case DebugLevel: | ||
103 | levelColor = gray | ||
104 | case WarnLevel: | ||
105 | levelColor = yellow | ||
106 | case ErrorLevel, FatalLevel, PanicLevel: | ||
107 | levelColor = red | ||
108 | default: | ||
109 | levelColor = blue | ||
110 | } | ||
111 | |||
112 | levelText := strings.ToUpper(entry.Level.String())[0:4] | ||
113 | |||
114 | if !f.FullTimestamp { | ||
115 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message) | ||
116 | } else { | ||
117 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message) | ||
118 | } | ||
119 | for _, k := range keys { | ||
120 | v := entry.Data[k] | ||
121 | fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v) | ||
122 | } | ||
123 | } | ||
124 | |||
125 | func needsQuoting(text string) bool { | ||
126 | for _, ch := range text { | ||
127 | if !((ch >= 'a' && ch <= 'z') || | ||
128 | (ch >= 'A' && ch <= 'Z') || | ||
129 | (ch >= '0' && ch <= '9') || | ||
130 | ch == '-' || ch == '.') { | ||
131 | return false | ||
132 | } | ||
133 | } | ||
134 | return true | ||
135 | } | ||
136 | |||
137 | func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { | ||
138 | |||
139 | b.WriteString(key) | ||
140 | b.WriteByte('=') | ||
141 | |||
142 | switch value := value.(type) { | ||
143 | case string: | ||
144 | if needsQuoting(value) { | ||
145 | b.WriteString(value) | ||
146 | } else { | ||
147 | fmt.Fprintf(b, "%q", value) | ||
148 | } | ||
149 | case error: | ||
150 | errmsg := value.Error() | ||
151 | if needsQuoting(errmsg) { | ||
152 | b.WriteString(errmsg) | ||
153 | } else { | ||
154 | fmt.Fprintf(b, "%q", value) | ||
155 | } | ||
156 | default: | ||
157 | fmt.Fprint(b, value) | ||
158 | } | ||
159 | |||
160 | b.WriteByte(' ') | ||
161 | } | ||