-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change log details encoding format and support details on service logs
URL query encode log details, so that characters like spaces don't make log parsing ambiguous. Add a helper function to parse these details to a map, if needed Add support for details on service logs Signed-off-by: Drew Erny <[email protected]>
- Loading branch information
Showing
8 changed files
with
156 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package client | ||
|
||
// parse_logs.go contains utility helpers for getting information out of docker | ||
// log lines. really, it only contains ParseDetails right now. maybe in the | ||
// future there will be some desire to parse log messages back into a struct? | ||
// that would go here if we did | ||
|
||
import ( | ||
"net/url" | ||
"strings" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
// ParseLogDetails takes a details string of key value pairs in the form | ||
// "k=v,l=w", where the keys and values are url query escaped, and each pair | ||
// is separated by a comma, returns a map. returns an error if the details | ||
// string is not in a valid format | ||
// the exact form of details encoding is implemented in | ||
// api/server/httputils/write_log_stream.go | ||
func ParseLogDetails(details string) (map[string]string, error) { | ||
pairs := strings.Split(details, ",") | ||
detailsMap := make(map[string]string, len(pairs)) | ||
for _, pair := range pairs { | ||
p := strings.SplitN(pair, "=", 2) | ||
// if there is no equals sign, we will only get 1 part back | ||
if len(p) != 2 { | ||
return nil, errors.New("invalid details format") | ||
} | ||
k, err := url.QueryUnescape(p[0]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
v, err := url.QueryUnescape(p[1]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
detailsMap[k] = v | ||
} | ||
return detailsMap, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package client | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
func TestParseLogDetails(t *testing.T) { | ||
testCases := []struct { | ||
line string | ||
expected map[string]string | ||
err error | ||
}{ | ||
{"key=value", map[string]string{"key": "value"}, nil}, | ||
{"key1=value1,key2=value2", map[string]string{"key1": "value1", "key2": "value2"}, nil}, | ||
{"key+with+spaces=value%3Dequals,asdf%2C=", map[string]string{"key with spaces": "value=equals", "asdf,": ""}, nil}, | ||
{"key=,=nothing", map[string]string{"key": "", "": "nothing"}, nil}, | ||
{"=", map[string]string{"": ""}, nil}, | ||
{"errors", nil, errors.New("invalid details format")}, | ||
} | ||
for _, tc := range testCases { | ||
tc := tc // capture range variable | ||
t.Run(tc.line, func(t *testing.T) { | ||
t.Parallel() | ||
res, err := ParseLogDetails(tc.line) | ||
if err != nil && (err.Error() != tc.err.Error()) { | ||
t.Fatalf("unexpected error parsing logs:\nExpected:\n\t%v\nActual:\n\t%v", tc.err, err) | ||
} | ||
if !reflect.DeepEqual(tc.expected, res) { | ||
t.Errorf("result does not match expected:\nExpected:\n\t%#v\nActual:\n\t%#v", tc.expected, res) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters