mirror of
https://github.com/docker/cli.git
synced 2026-09-24 15:30:10 -05:00
Avoid using a map for log attributes
Having a map per log entry seemed heavier than necessary. These attributes end up being sorted and serialized, so storing them in a map doesn't add anything (there's no random access element). In SwarmKit, they originate as a slice, so there's an unnecessary conversion to a map and back. This also fixes the sort comparator, which used to inefficiently split the string on each comparison. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com> Upstream-commit: b642b3f21f17cf50c79e464d3aedc93b2dbf0fb0 Component: engine
This commit is contained in:
@@ -5,7 +5,6 @@ import (
|
||||
"io"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
@@ -53,7 +52,8 @@ func WriteLogStream(ctx context.Context, w io.Writer, msgs <-chan *backend.LogMe
|
||||
}
|
||||
logLine := msg.Line
|
||||
if config.Details {
|
||||
logLine = append([]byte(stringAttrs(msg.Attrs)+" "), logLine...)
|
||||
logLine = append(attrsByteSlice(msg.Attrs), ' ')
|
||||
logLine = append(logLine, msg.Line...)
|
||||
}
|
||||
if config.Timestamps {
|
||||
// TODO(dperny) the format is defined in
|
||||
@@ -71,24 +71,26 @@ func WriteLogStream(ctx context.Context, w io.Writer, msgs <-chan *backend.LogMe
|
||||
}
|
||||
}
|
||||
|
||||
type byKey []string
|
||||
type byKey []backend.LogAttr
|
||||
|
||||
func (s byKey) Len() int { return len(s) }
|
||||
func (s byKey) Less(i, j int) bool {
|
||||
keyI := strings.Split(s[i], "=")
|
||||
keyJ := strings.Split(s[j], "=")
|
||||
return keyI[0] < keyJ[0]
|
||||
}
|
||||
func (s byKey) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
func (b byKey) Len() int { return len(b) }
|
||||
func (b byKey) Less(i, j int) bool { return b[i].Key < b[j].Key }
|
||||
func (b byKey) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
|
||||
func stringAttrs(a backend.LogAttributes) string {
|
||||
var ss byKey
|
||||
for k, v := range a {
|
||||
k, v := url.QueryEscape(k), url.QueryEscape(v)
|
||||
ss = append(ss, k+"="+v)
|
||||
func attrsByteSlice(a []backend.LogAttr) []byte {
|
||||
// Note this sorts "a" in-place. That is fine here - nothing else is
|
||||
// going to use Attrs or care about the order.
|
||||
sort.Sort(byKey(a))
|
||||
|
||||
var ret []byte
|
||||
for i, pair := range a {
|
||||
k, v := url.QueryEscape(pair.Key), url.QueryEscape(pair.Value)
|
||||
ret = append(ret, []byte(k)...)
|
||||
ret = append(ret, '=')
|
||||
ret = append(ret, []byte(v)...)
|
||||
if i != len(a)-1 {
|
||||
ret = append(ret, ',')
|
||||
}
|
||||
}
|
||||
sort.Sort(ss)
|
||||
return strings.Join(ss, ",")
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ type LogMessage struct {
|
||||
Line []byte
|
||||
Source string
|
||||
Timestamp time.Time
|
||||
Attrs LogAttributes
|
||||
Attrs []LogAttr
|
||||
Partial bool
|
||||
|
||||
// Err is an error associated with a message. Completeness of a message
|
||||
@@ -44,9 +44,11 @@ type LogMessage struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
// LogAttributes is used to hold the extra attributes available in the log message
|
||||
// Primarily used for converting the map type to string and sorting.
|
||||
type LogAttributes map[string]string
|
||||
// LogAttr is used to hold the extra attributes available in the log message.
|
||||
type LogAttr struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
// LogSelector is a list of services and tasks that should be returned as part
|
||||
// of a log stream. It is similar to swarmapi.LogSelector, with the difference
|
||||
|
||||
Reference in New Issue
Block a user