diff --git a/logs/zap/core.go b/logs/zap/core.go
index 0b54b5c38324e7ec18d1ad80497c3858ed246014..a6c1c2ecd7e9e2075d4a008bddb4e7911278d64d 100644
--- a/logs/zap/core.go
+++ b/logs/zap/core.go
@@ -28,14 +28,10 @@ func NewCore(writeSyncer WriteSyncer) *Core {
 }
 
 func (core *Core) With(fields []zapcore.Field) zapcore.Core {
-	clone := core.enc.Clone()
-	for i := range fields {
-		fields[i].AddTo(clone)
-	}
 	return &Core{
 		LevelEnabler: core.LevelEnabler,
 		ws:           core.ws,
-		enc:          clone,
+		enc:          core.enc.With(fields),
 	}
 }
 
@@ -47,11 +43,11 @@ func (core *Core) Check(entry zapcore.Entry, checkedEntry *zapcore.CheckedEntry)
 }
 
 func (core *Core) Write(entry zapcore.Entry, fields []zapcore.Field) error {
-	encodeEntry, err := core.enc.EncodeEntry(entry, fields)
+	encodedEntry, err := core.enc.EncodeEntry(entry, fields)
 	if err != nil {
 		return err
 	}
-	return core.ws.Write(encodeEntry)
+	return core.ws.Write(encodedEntry)
 }
 
 func (core *Core) Sync() error {
diff --git a/logs/zap/entry_encoder.go b/logs/zap/entry_encoder.go
index 0f5692852f59fbb620b476d982f61617dd476294..8fb66f37a2e2fc80124a3ade0f853fd386e9dd13 100644
--- a/logs/zap/entry_encoder.go
+++ b/logs/zap/entry_encoder.go
@@ -2,45 +2,37 @@ package zap
 
 import (
 	"fmt"
-	"maps"
+	"slices"
 
 	oid "git.perx.ru/perxis/perxis-go/id"
 	"git.perx.ru/perxis/perxis-go/logs"
 	"git.perx.ru/perxis/perxis-go/pkg/id"
+	"git.perx.ru/perxis/perxis-go/zap"
 	"go.uber.org/zap/zapcore"
 )
 
 type Encoder interface {
-	zapcore.ObjectEncoder
-
-	Clone() Encoder
+	With([]zapcore.Field) Encoder
 	EncodeEntry(zapcore.Entry, []zapcore.Field) (*logs.Entry, error)
 }
 
 type entryEncoder struct {
-	*zapcore.MapObjectEncoder
+	fields []zapcore.Field
 }
 
 func NewEntryEncoder() Encoder {
-	return &entryEncoder{MapObjectEncoder: zapcore.NewMapObjectEncoder()}
+	return &entryEncoder{}
 }
 
-func (enc *entryEncoder) Clone() Encoder {
-	return enc.clone()
+func (enc *entryEncoder) With(fields []zapcore.Field) Encoder {
+	return enc.with(fields)
 }
 
-func (enc *entryEncoder) clone() *entryEncoder {
-	objEnc := zapcore.NewMapObjectEncoder()
-	maps.Copy(objEnc.Fields, enc.MapObjectEncoder.Fields)
-	return &entryEncoder{MapObjectEncoder: objEnc}
+func (enc *entryEncoder) with(fields []zapcore.Field) *entryEncoder {
+	return &entryEncoder{fields: slices.Concat(enc.fields, fields)}
 }
 
 func (enc *entryEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*logs.Entry, error) {
-	clone := enc.clone()
-	for i := range fields {
-		fields[i].AddTo(clone)
-	}
-
 	ent := &logs.Entry{
 		ID:        id.GenerateNewID(),
 		Timestamp: entry.Time,
@@ -48,22 +40,31 @@ func (enc *entryEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field
 		Message:   entry.Message,
 	}
 
-	ent.Category, _ = clone.Fields["category"].(string)
-	ent.Component, _ = clone.Fields["component"].(string)
-	ent.Event, _ = clone.Fields["event"].(string)
-	ent.ObjectID, _ = clone.Fields["object"].(*oid.ObjectId)
-	ent.CallerID, _ = clone.Fields["caller"].(*oid.ObjectId)
-	ent.Attr = clone.Fields["attr"]
-
-	if err, _ := clone.Fields["error"].(error); err != nil {
-		ent.Message = fmt.Sprintf("%s. Error: %s", ent.Message, err.Error())
-	}
+	clone := enc.with(fields)
 
-	if tags, ok := clone.Fields["tags"].([]any); ok {
-		for i := range tags {
-			if tag, ok := tags[i].(string); ok {
-				ent.Tags = append(ent.Tags, tag)
+	for i := range clone.fields {
+		switch clone.fields[i].Key {
+		// При добавлении новых полей стоит учитывать, как zap хранит значения в структуре Field.
+		// Например:
+		// zap.Bool хранит bool как 1/0 в поле Field.Integer
+		case "category":
+			ent.Category = clone.fields[i].String
+		case "component":
+			ent.Component = clone.fields[i].String
+		case "event":
+			ent.Event = clone.fields[i].String
+		case "object":
+			ent.ObjectID, _ = clone.fields[i].Interface.(*oid.ObjectId)
+		case "caller":
+			ent.CallerID, _ = clone.fields[i].Interface.(*oid.ObjectId)
+		case "attr":
+			ent.Attr = clone.fields[i].Interface
+		case "error":
+			if err, _ := clone.fields[i].Interface.(error); err != nil {
+				ent.Message = fmt.Sprintf("%s. Error: %s", ent.Message, err.Error())
 			}
+		case "tags":
+			ent.Tags, _ = clone.fields[i].Interface.(zap.StringArray)
 		}
 	}
 
diff --git a/logs/zap/entry_encoder_slow.go b/logs/zap/entry_encoder_slow.go
new file mode 100644
index 0000000000000000000000000000000000000000..303b5c4c80f16ebe02eab7cf2b6f9731f33b9ec5
--- /dev/null
+++ b/logs/zap/entry_encoder_slow.go
@@ -0,0 +1,71 @@
+package zap
+
+import (
+	"fmt"
+	"maps"
+
+	oid "git.perx.ru/perxis/perxis-go/id"
+	"git.perx.ru/perxis/perxis-go/logs"
+	"git.perx.ru/perxis/perxis-go/pkg/id"
+	"go.uber.org/zap/zapcore"
+)
+
+type EncoderSlow interface {
+	zapcore.ObjectEncoder
+
+	Clone() EncoderSlow
+	EncodeEntry(zapcore.Entry, []zapcore.Field) (*logs.Entry, error)
+}
+
+type entryEncoderSlow struct {
+	*zapcore.MapObjectEncoder
+}
+
+func NewEntryEncoderSlow() EncoderSlow {
+	return &entryEncoderSlow{MapObjectEncoder: zapcore.NewMapObjectEncoder()}
+}
+
+func (enc *entryEncoderSlow) Clone() EncoderSlow {
+	return enc.clone()
+}
+
+func (enc *entryEncoderSlow) clone() *entryEncoderSlow {
+	objEnc := zapcore.NewMapObjectEncoder()
+	maps.Copy(objEnc.Fields, enc.MapObjectEncoder.Fields)
+	return &entryEncoderSlow{MapObjectEncoder: objEnc}
+}
+
+func (enc *entryEncoderSlow) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*logs.Entry, error) {
+	clone := enc.clone()
+	for i := range fields {
+		fields[i].AddTo(clone)
+	}
+
+	ent := &logs.Entry{
+		ID:        id.GenerateNewID(),
+		Timestamp: entry.Time,
+		LogLevel:  logs.Level(entry.Level),
+		Message:   entry.Message,
+	}
+
+	ent.Category, _ = clone.Fields["category"].(string)
+	ent.Component, _ = clone.Fields["component"].(string)
+	ent.Event, _ = clone.Fields["event"].(string)
+	ent.ObjectID, _ = clone.Fields["object"].(*oid.ObjectId)
+	ent.CallerID, _ = clone.Fields["caller"].(*oid.ObjectId)
+	ent.Attr = clone.Fields["attr"]
+
+	if err, _ := clone.Fields["error"].(error); err != nil {
+		ent.Message = fmt.Sprintf("%s. Error: %s", ent.Message, err.Error())
+	}
+
+	if tags, ok := clone.Fields["tags"].([]any); ok {
+		for i := range tags {
+			if tag, ok := tags[i].(string); ok {
+				ent.Tags = append(ent.Tags, tag)
+			}
+		}
+	}
+
+	return ent, nil
+}
diff --git a/logs/zap/entry_encoder_test.go b/logs/zap/entry_encoder_test.go
index 052b13f7f85fc2f2a2848427767d3445077ac3b1..ee21e0fe63c78c1b94de26ac1b3b47cd859e8bc8 100644
--- a/logs/zap/entry_encoder_test.go
+++ b/logs/zap/entry_encoder_test.go
@@ -4,12 +4,68 @@ import (
 	"fmt"
 	"testing"
 
+	"git.perx.ru/perxis/perxis-go/id"
+	"git.perx.ru/perxis/perxis-go/logs"
 	"git.perx.ru/perxis/perxis-go/pkg/items"
 	logzap "git.perx.ru/perxis/perxis-go/zap"
+	"github.com/stretchr/testify/require"
 	"go.uber.org/zap"
 	"go.uber.org/zap/zapcore"
 )
 
+func TestEntryEncoder_EncodeEntry(t *testing.T) {
+	tests := []struct {
+		name  string
+		input struct {
+			entry  zapcore.Entry
+			fields []zapcore.Field
+		}
+		want *logs.Entry
+	}{
+		{
+			name: "simple",
+			input: struct {
+				entry  zapcore.Entry
+				fields []zapcore.Field
+			}{
+				entry: zapcore.Entry{Level: zapcore.InfoLevel, Message: "создан элемент коллекции"},
+				fields: []zapcore.Field{
+					zap.String("key", "val"), // будет проигнорировано
+					logzap.Category("create"),
+					logzap.Component("Items.Service"),
+					logzap.Event("Items.Create"),
+					logzap.Object("/spaces/WPNN/envs/9VGP/cols/GxNv/items/W0fl"),
+					logzap.Caller("/users/PHVz"),
+					logzap.Attr("any"),
+					logzap.Tags("tag1", "tag2", "tag3"),
+				},
+			},
+			want: &logs.Entry{
+				LogLevel:  logs.Level(zapcore.InfoLevel),
+				Message:   "создан элемент коллекции",
+				Category:  "create",
+				Component: "Items.Service",
+				Event:     "Items.Create",
+				ObjectID:  id.MustObjectId("/spaces/WPNN/envs/9VGP/cols/GxNv/items/W0fl"),
+				CallerID:  id.MustObjectId("/users/PHVz"),
+				Attr:      "any",
+				Tags:      []string{"tag1", "tag2", "tag3"},
+			},
+		},
+	}
+
+	enc := NewEntryEncoder()
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			got, _ := enc.EncodeEntry(tc.input.entry, tc.input.fields)
+			got.ID = tc.want.ID               // игнорируем ID
+			got.Timestamp = tc.want.Timestamp // игнорируем Timestamp
+			require.Equal(t, tc.want, got)
+		})
+	}
+}
+
 func BenchmarkEntryEncoderSimple(b *testing.B) {
 	fields := []zapcore.Field{
 		logzap.Event(items.EventCreateItem),
@@ -18,7 +74,7 @@ func BenchmarkEntryEncoderSimple(b *testing.B) {
 		logzap.Tags("tag1", "tag2", "tag3"),
 	}
 
-	enc := NewEntryEncoder()
+	enc := NewEntryEncoderSlow()
 	for i := 0; i < b.N; i++ {
 		_, _ = enc.EncodeEntry(zapcore.Entry{Message: fmt.Sprintf("Msg: %d", i)}, fields)
 	}
@@ -36,7 +92,7 @@ func BenchmarkEntryEncoderUnknownFields(b *testing.B) {
 		fields = append(fields, zap.String(fmt.Sprintf("Key: %d", i), fmt.Sprintf("Value: %d", i)))
 	}
 
-	enc := NewEntryEncoder()
+	enc := NewEntryEncoderSlow()
 	for i := 0; i < b.N; i++ {
 		_, _ = enc.EncodeEntry(zapcore.Entry{Message: fmt.Sprintf("Msg: %d", i)}, fields)
 	}
@@ -50,7 +106,7 @@ func BenchmarkEntryEncoderV2Simple(b *testing.B) {
 		logzap.Tags("tag1", "tag2", "tag3"),
 	}
 
-	enc := NewEntryEncoderV2()
+	enc := NewEntryEncoder()
 	for i := 0; i < b.N; i++ {
 		_, _ = enc.EncodeEntry(zapcore.Entry{Message: fmt.Sprintf("Msg: %d", i)}, fields)
 	}
@@ -68,7 +124,7 @@ func BenchmarkEntryEncoderV2UnknownFields(b *testing.B) {
 		fields = append(fields, zap.String(fmt.Sprintf("Key: %d", i), fmt.Sprintf("Value: %d", i)))
 	}
 
-	enc := NewEntryEncoderV2()
+	enc := NewEntryEncoder()
 	for i := 0; i < b.N; i++ {
 		_, _ = enc.EncodeEntry(zapcore.Entry{Message: fmt.Sprintf("Msg: %d", i)}, fields)
 	}
diff --git a/logs/zap/entry_encoder_v2.go b/logs/zap/entry_encoder_v2.go
deleted file mode 100644
index a73be0930a2a082e4bcc27f9218850e6d3e9395c..0000000000000000000000000000000000000000
--- a/logs/zap/entry_encoder_v2.go
+++ /dev/null
@@ -1,69 +0,0 @@
-package zap
-
-import (
-	"fmt"
-	"slices"
-
-	oid "git.perx.ru/perxis/perxis-go/id"
-	"git.perx.ru/perxis/perxis-go/logs"
-	"git.perx.ru/perxis/perxis-go/pkg/id"
-	"git.perx.ru/perxis/perxis-go/zap"
-	"go.uber.org/zap/zapcore"
-)
-
-type EncoderV2 interface {
-	With([]zapcore.Field) EncoderV2
-	EncodeEntry(zapcore.Entry, []zapcore.Field) (*logs.Entry, error)
-}
-
-type entryEncoderV2 struct {
-	fields []zapcore.Field
-}
-
-func NewEntryEncoderV2() EncoderV2 {
-	return &entryEncoderV2{}
-}
-
-func (enc *entryEncoderV2) With(fields []zapcore.Field) EncoderV2 {
-	return enc.with(fields)
-}
-
-func (enc *entryEncoderV2) with(fields []zapcore.Field) *entryEncoderV2 {
-	return &entryEncoderV2{fields: slices.Concat(enc.fields, fields)}
-}
-
-func (enc *entryEncoderV2) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*logs.Entry, error) {
-	ent := &logs.Entry{
-		ID:        id.GenerateNewID(),
-		Timestamp: entry.Time,
-		LogLevel:  logs.Level(entry.Level),
-		Message:   entry.Message,
-	}
-
-	clone := enc.with(fields)
-
-	for i := range clone.fields {
-		switch clone.fields[i].Key {
-		case "category":
-			ent.Category = clone.fields[i].String
-		case "component":
-			ent.Component = clone.fields[i].String
-		case "event":
-			ent.Event = clone.fields[i].String
-		case "object":
-			ent.ObjectID, _ = clone.fields[i].Interface.(*oid.ObjectId)
-		case "caller":
-			ent.CallerID, _ = clone.fields[i].Interface.(*oid.ObjectId)
-		case "attr":
-			ent.Attr = clone.fields[i].Interface
-		case "error":
-			if err, _ := clone.fields[i].Interface.(error); err != nil {
-				ent.Message = fmt.Sprintf("%s. Error: %s", ent.Message, err.Error())
-			}
-		case "tags":
-			ent.Tags, _ = clone.fields[i].Interface.(zap.StringArray)
-		}
-	}
-
-	return ent, nil
-}
diff --git a/zap/field.go b/zap/field.go
index bccee93496f88404f2ca90332fcf3f1b89909104..f967504c6c9e797fd75eb7185fa718609e82151b 100644
--- a/zap/field.go
+++ b/zap/field.go
@@ -60,7 +60,7 @@ func CallerFromContext(ctx context.Context) zap.Field {
 }
 
 func Attr(attr any) zap.Field {
-	return zap.Any("attr", attr)
+	return zap.Reflect("attr", attr)
 }
 
 func Tags(tags ...string) zap.Field {