diff --git a/exp/zapfield/doc.go b/exp/zapfield/doc.go new file mode 100644 index 000000000..1f2621e45 --- /dev/null +++ b/exp/zapfield/doc.go @@ -0,0 +1,2 @@ +// Package zapfield provides experimental zap.Field helpers whose APIs may be unstable. +package zapfield diff --git a/exp/zapfield/zapfield.go b/exp/zapfield/zapfield.go index 729082498..1512cf061 100644 --- a/exp/zapfield/zapfield.go +++ b/exp/zapfield/zapfield.go @@ -18,7 +18,6 @@ // 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 ( @@ -26,7 +25,78 @@ import ( "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)) } @@ -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)) } diff --git a/exp/zapfield/zapfield_test.go b/exp/zapfield/zapfield_test.go index 0efa647b2..961cebf48 100644 --- a/exp/zapfield/zapfield_test.go +++ b/exp/zapfield/zapfield_test.go @@ -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"), } ) @@ -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) + }) } }