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

grow /exp/zapfield #1364

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions exp/zapfield/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package zapfield provides experimental zap.Field helpers whose APIs may be unstable.
package zapfield
81 changes: 78 additions & 3 deletions exp/zapfield/zapfield.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,85 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// Package zapfield provides experimental zap.Field helpers whose APIs may be unstable.
package zapfield

import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

// Str constructs a field with the given string-like key and value.
// Uint constructs a field with the given string-like key and uint-like value.
func Uint[K ~string, V ~uint](k K, v V) zap.Field {
return zap.Uint(string(k), uint(v))
}

// Uint64 constructs a field with the given string-like key and uint64-like value.
func Uint64[K ~string, V ~uint64](k K, v V) zap.Field {
return zap.Uint64(string(k), uint64(v))
}

// Uint32 constructs a field with the given string-like key and uint32-like value.
func Uint32[K ~string, V ~uint32](k K, v V) zap.Field {
return zap.Uint32(string(k), uint32(v))
}

// Uint16 constructs a field with the given string-like key and uint16-like value.
func Uint16[K ~string, V ~uint16](k K, v V) zap.Field {
return zap.Uint16(string(k), uint16(v))
}

// Uint8 constructs a field with the given string-like key and uint8-like value.
func Uint8[K ~string, V ~uint8](k K, v V) zap.Field {
return zap.Uint8(string(k), uint8(v))
}

// -----

// Int constructs a field with the given string-like key and int-like value.
func Int[K ~string, V ~int](k K, v V) zap.Field {
return zap.Int(string(k), int(v))
}

// Int64 constructs a field with the given string-like key and int64-like value.
func Int64[K ~string, V ~int64](k K, v V) zap.Field {
return zap.Int64(string(k), int64(v))
}

// Int32 constructs a field with the given string-like key and int32-like value.
func Int32[K ~string, V ~int32](k K, v V) zap.Field {
return zap.Int32(string(k), int32(v))
}

// Int16 constructs a field with the given string-like key and int16-like value.
func Int16[K ~string, V ~int16](k K, v V) zap.Field {
return zap.Int16(string(k), int16(v))
}

// Int8 constructs a field with the given string-like key and int8-like value.
func Int8[K ~string, V ~int8](k K, v V) zap.Field {
return zap.Int8(string(k), int8(v))
}

// -----

// Float64 constructs a field with the given string-like key and float64-like value.
func Float64[K ~string, V ~float64](k K, v V) zap.Field {
return zap.Float64(string(k), float64(v))
}

// Float32 constructs a field with the given string-like key and float32-like value.
func Float32[K ~string, V ~float32](k K, v V) zap.Field {
return zap.Float32(string(k), float32(v))
}

// -----

// String constructs a field with the given string-like key and value.
func String[K ~string, V ~string](k K, v V) zap.Field {
return zap.String(string(k), string(v))
}

// Str is an alias to String.
func Str[K ~string, V ~string](k K, v V) zap.Field {
return zap.String(string(k), string(v))
}
Expand All @@ -40,7 +110,12 @@ func (a stringArray[T]) MarshalLogArray(enc zapcore.ArrayEncoder) error {
return nil
}

// Strs constructs a field that carries a slice of string-like values.
// Strings constructs a field that carries a slice of string-like values.
func Strings[K ~string, V ~[]S, S ~string](k K, v V) zap.Field {
return zap.Array(string(k), stringArray[S](v))
}

// Strs is an alias to Strings.
func Strs[K ~string, V ~[]S, S ~string](k K, v V) zap.Field {
return zap.Array(string(k), stringArray[S](v))
}
80 changes: 66 additions & 14 deletions exp/zapfield/zapfield_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,56 @@ import (
"testing"

"github.com/stretchr/testify/assert"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

type (
MyKey string
MyValue string
MyValues []MyValue
EmbeddedStringKey string

EmbeddedUint uint
EmbeddedUint64 uint64
EmbeddedUint32 uint32
EmbeddedUint16 uint16
EmbeddedUint8 uint8

EmbeddedInt int
EmbeddedInt64 int64
EmbeddedInt32 int32
EmbeddedInt16 int16
EmbeddedInt8 int8

EmbeddedFloat64 float64
EmbeddedFloat32 float32

EmbeddedString string
EmbeddedStrings []EmbeddedString
)

func TestFieldConstructors(t *testing.T) {
var (
key = MyKey("test key")
value = MyValue("test value")
values = []MyValue{
MyValue("test value 1"),
MyValue("test value 2"),
key = EmbeddedStringKey("test key")

uintValue = EmbeddedUint(1)
uint64Value = EmbeddedUint64(2)
uint32Value = EmbeddedUint32(3)
uint16Value = EmbeddedUint16(4)
uint8Value = EmbeddedUint8(5)

intValue = EmbeddedInt(-1)
int64Value = EmbeddedInt64(20)
int32Value = EmbeddedInt32(-300)
int16Value = EmbeddedInt16(4000)
int8Value = EmbeddedInt8(-54)

float64Value = EmbeddedFloat64(123.45)
float32Value = EmbeddedFloat32(-54.321)

stringValue = EmbeddedString("test value")
stringsValue = EmbeddedStrings{
EmbeddedString("test value 1"),
EmbeddedString("test value 2"),
}
)

Expand All @@ -50,15 +83,34 @@ func TestFieldConstructors(t *testing.T) {
expect zap.Field
field zap.Field
}{
{"Str", zap.Field{Type: zapcore.StringType, Key: "test key", String: "test value"}, Str(key, value)},
{"Strs", zap.Array("test key", stringArray[MyValue]{"test value 1", "test value 2"}), Strs(key, values)},
{"Uint", zap.Field{Type: zapcore.Uint64Type, Key: "test key", Integer: 1}, Uint(key, uintValue)},
{"Uint64", zap.Field{Type: zapcore.Uint64Type, Key: "test key", Integer: 2}, Uint64(key, uint64Value)},
{"Uint32", zap.Field{Type: zapcore.Uint32Type, Key: "test key", Integer: 3}, Uint32(key, uint32Value)},
{"Uint16", zap.Field{Type: zapcore.Uint16Type, Key: "test key", Integer: 4}, Uint16(key, uint16Value)},
{"Uint8", zap.Field{Type: zapcore.Uint8Type, Key: "test key", Integer: 5}, Uint8(key, uint8Value)},

{"Int", zap.Field{Type: zapcore.Int64Type, Key: "test key", Integer: -1}, Int(key, intValue)},
{"Int64", zap.Field{Type: zapcore.Int64Type, Key: "test key", Integer: 20}, Int64(key, int64Value)},
{"Int32", zap.Field{Type: zapcore.Int32Type, Key: "test key", Integer: -300}, Int32(key, int32Value)},
{"Int16", zap.Field{Type: zapcore.Int16Type, Key: "test key", Integer: 4000}, Int16(key, int16Value)},
{"Int8", zap.Field{Type: zapcore.Int8Type, Key: "test key", Integer: -54}, Int8(key, int8Value)},

{"Float64", zap.Field{Type: zapcore.Float64Type, Key: "test key", Integer: 4638387438405602509}, Float64(key, float64Value)},
{"Float32", zap.Field{Type: zapcore.Float32Type, Key: "test key", Integer: 3260631220}, Float32(key, float32Value)},

{"String", zap.Field{Type: zapcore.StringType, Key: "test key", String: "test value"}, String(key, stringValue)},
{"Str", zap.Field{Type: zapcore.StringType, Key: "test key", String: "test value"}, Str(key, stringValue)},
{"Strings", zap.Array("test key", stringArray[EmbeddedString]{"test value 1", "test value 2"}), Strings(key, stringsValue)},
{"Strs", zap.Array("test key", stringArray[EmbeddedString]{"test value 1", "test value 2"}), Strs(key, stringsValue)},
}

for _, tt := range tests {
if !assert.Equal(t, tt.expect, tt.field, "Unexpected output from convenience field constructor %s.", tt.name) {
t.Logf("type expected: %T\nGot: %T", tt.expect.Interface, tt.field.Interface)
}
assertCanBeReused(t, tt.field)
t.Run(tt.name, func(t *testing.T) {
if !assert.Equal(t, tt.expect, tt.field, "Unexpected output from convenience field constructor %s.", tt.name) {
t.Logf("type expected: %T\nGot: %T", tt.expect.Interface, tt.field.Interface)
}
assertCanBeReused(t, tt.field)
})
}

}
Expand Down