Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for hex-encoded bytes #42

Merged
merged 3 commits into from
Mar 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions array.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ func (a *Array) Bytes(val []byte) *Array {
return a
}

// Hex append the val as a hex string to the array.
func (a *Array) Hex(val []byte) *Array {
a.buf = json.AppendHex(append(a.buf, ','), val)
return a
}

// Err append the err as a string to the array.
func (a *Array) Err(err error) *Array {
a.buf = json.AppendError(append(a.buf, ','), err)
Expand Down
4 changes: 3 additions & 1 deletion array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ func TestArray(t *testing.T) {
Float32(11).
Float64(12).
Str("a").
Bytes([]byte("b")).
Hex([]byte{0x1f}).
Time(time.Time{}).
Dur(0)
want := `[true,1,2,3,4,5,6,7,8,9,10,11,12,"a","0001-01-01T00:00:00Z",0]`
want := `[true,1,2,3,4,5,6,7,8,9,10,11,12,"a","b","1f","0001-01-01T00:00:00Z",0]`
if got := string(a.write([]byte{})); got != want {
t.Errorf("Array.write()\ngot: %s\nwant: %s", got, want)
}
Expand Down
6 changes: 6 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ func (c Context) Bytes(key string, val []byte) Context {
return c
}

// Hex adds the field key with val as a hex string to the logger context.
func (c Context) Hex(key string, val []byte) Context {
c.l.context = json.AppendHex(json.AppendKey(c.l.context, key), val)
return c
}

// RawJSON adds already encoded JSON to context.
//
// No sanity check is performed on b; it must not contain carriage returns and
Expand Down
9 changes: 9 additions & 0 deletions event.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,15 @@ func (e *Event) Bytes(key string, val []byte) *Event {
return e
}

// Hex adds the field key with val as a hex string to the *Event context.
func (e *Event) Hex(key string, val []byte) *Event {
if e == nil {
return e
}
e.buf = json.AppendHex(json.AppendKey(e.buf, key), val)
return e
}

// RawJSON adds already encoded JSON to the log line under key.
//
// No sanity check is performed on b; it must not contain carriage returns and
Expand Down
5 changes: 5 additions & 0 deletions internal/json/base.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package json

// AppendKey appends a new key to the output JSON.
func AppendKey(dst []byte, key string) []byte {
if len(dst) > 1 {
dst = append(dst, ',')
Expand All @@ -8,13 +9,17 @@ func AppendKey(dst []byte, key string) []byte {
return append(dst, ':')
}

// AppendError encodes the error string to json and appends
// the encoded string to the input byte slice.
func AppendError(dst []byte, err error) []byte {
if err == nil {
return append(dst, `null`...)
}
return AppendString(dst, err.Error())
}

// AppendErrors encodes the error strings to json and
// appends the encoded string list to the input byte slice.
func AppendErrors(dst []byte, errs []error) []byte {
if len(errs) == 0 {
return append(dst, '[', ']')
Expand Down
15 changes: 15 additions & 0 deletions internal/json/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import "unicode/utf8"

const hex = "0123456789abcdef"

// AppendStrings encodes the input strings to json and
// appends the encoded string list to the input byte slice.
func AppendStrings(dst []byte, vals []string) []byte {
if len(vals) == 0 {
return append(dst, '[', ']')
Expand Down Expand Up @@ -123,6 +125,19 @@ func AppendBytes(dst, s []byte) []byte {
return append(dst, '"')
}

// AppendHex encodes the input bytes to a hex string and appends
// the encoded string to the input byte slice.
//
// The operation loops though each byte and encodes it as hex using
// the hex lookup table.
func AppendHex(dst, s []byte) []byte {
dst = append(dst, '"')
for _, v := range s {
dst = append(dst, hex[v>>4], hex[v&0x0f])
}
return append(dst, '"')
}

// appendBytesComplex is a mirror of the appendStringComplex
// with []byte arg
func appendBytesComplex(dst, s []byte, i int) []byte {
Expand Down
28 changes: 24 additions & 4 deletions internal/json/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,18 @@ var encodeStringTests = []struct {
{"emoji \u2764\ufe0f!", `"emoji ❤️!"`},
}

func TestappendString(t *testing.T) {
var encodeHexTests = []struct {
in byte
out string
}{
{0x00, `"00"`},
{0x0f, `"0f"`},
{0x10, `"10"`},
{0xf0, `"f0"`},
{0xff, `"ff"`},
}

func TestAppendString(t *testing.T) {
for _, tt := range encodeStringTests {
b := AppendString([]byte{}, tt.in)
if got, want := string(b), tt.out; got != want {
Expand All @@ -62,7 +73,7 @@ func TestappendString(t *testing.T) {
}
}

func TestappendBytes(t *testing.T) {
func TestAppendBytes(t *testing.T) {
for _, tt := range encodeStringTests {
b := AppendBytes([]byte{}, []byte(tt.in))
if got, want := string(b), tt.out; got != want {
Expand All @@ -71,6 +82,15 @@ func TestappendBytes(t *testing.T) {
}
}

func TestAppendHex(t *testing.T) {
for _, tt := range encodeHexTests {
b := AppendHex([]byte{}, []byte{tt.in})
if got, want := string(b), tt.out; got != want {
t.Errorf("appendHex(%x) = %s, want %s", tt.in, got, want)
}
}
}

func TestStringBytes(t *testing.T) {
t.Parallel()
// Test that encodeState.stringBytes and encodeState.string use the same encoding.
Expand Down Expand Up @@ -108,7 +128,7 @@ func TestStringBytes(t *testing.T) {
}
}

func BenchmarkappendString(b *testing.B) {
func BenchmarkAppendString(b *testing.B) {
tests := map[string]string{
"NoEncoding": `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
"EncodingFirst": `"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
Expand All @@ -128,7 +148,7 @@ func BenchmarkappendString(b *testing.B) {
}
}

func BenchmarkappendBytes(b *testing.B) {
func BenchmarkAppendBytes(b *testing.B) {
tests := map[string]string{
"NoEncoding": `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
"EncodingFirst": `"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
Expand Down
8 changes: 8 additions & 0 deletions internal/json/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import (
"time"
)

// AppendTime formats the input time with the given format
// and appends the encoded string to the input byte slice.
func AppendTime(dst []byte, t time.Time, format string) []byte {
if format == "" {
return AppendInt64(dst, t.Unix())
}
return append(t.AppendFormat(append(dst, '"'), format), '"')
}

// AppendTimes converts the input times with the given format
// and appends the encoded string list to the input byte slice.
func AppendTimes(dst []byte, vals []time.Time, format string) []byte {
if format == "" {
return appendUnixTimes(dst, vals)
Expand Down Expand Up @@ -45,13 +49,17 @@ func appendUnixTimes(dst []byte, vals []time.Time) []byte {
return dst
}

// AppendDuration formats the input duration with the given unit & format
// and appends the encoded string to the input byte slice.
func AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
if useInt {
return strconv.AppendInt(dst, int64(d/unit), 10)
}
return AppendFloat64(dst, float64(d)/float64(unit))
}

// AppendDurations formats the input durations with the given unit & format
// and appends the encoded string list to the input byte slice.
func AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
if len(vals) == 0 {
return append(dst, '[', ']')
Expand Down
Loading