diff --git a/pkg/log/zap/field.go b/pkg/log/zap/field.go
new file mode 100644
index 0000000000000000000000000000000000000000..e0de88be61059c325821ff68afe0bcbc7b88b6ba
--- /dev/null
+++ b/pkg/log/zap/field.go
@@ -0,0 +1,79 @@
+package zap
+
+import (
+	"context"
+	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/id"
+	"git.perx.ru/perxis/perxis-go/pkg/auth"
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+const (
+	unknownObject = "unknown"
+	unknownCaller = "unknown"
+)
+
+func Category(category string) zapcore.Field {
+	return zap.String("category", category)
+}
+
+func Component(component string) zapcore.Field {
+	return zap.String("component", component)
+}
+
+func Event(event string) zapcore.Field {
+	return zap.String("event", event)
+}
+
+// Object возвращает поле и устанавливает передаваемый аргумент в качестве идентификатора объекта в формате ObjectID.
+// Поддерживаемые типы: string, fmt.Stringer.
+// Если передан аргумент другого типа, будет произведена попытка привести переданное значение к ObjectID.
+func Object(v any) zapcore.Field {
+	var object = unknownObject
+	switch value := v.(type) {
+	case string:
+		object = value
+	case fmt.Stringer:
+		object = value.String()
+	default:
+		oid, err := id.FromObject(v)
+		if err == nil {
+			object = oid.String()
+		}
+	}
+	return zap.String("object", object)
+}
+
+// Caller возвращает поле и устанавливает передаваемый аргумент в качестве "вызывающего" в формате ObjectID.
+// Поддерживаемые типы: string, fmt.Stringer.
+// Если передан аргумент другого типа, будет произведена попытка привести переданное значение к ObjectID.
+func Caller(v any) zapcore.Field {
+	var caller = unknownCaller
+	switch value := v.(type) {
+	case string:
+		caller = value
+	case fmt.Stringer:
+		caller = value.String()
+	default:
+		oid, err := id.FromObject(v)
+		if err == nil {
+			caller = oid.String()
+		}
+	}
+	return zap.String("caller", caller)
+}
+
+// CallerFromContext извлекает auth.Principal из контекста и устанавливает его в качестве "вызывающего" в формате ObjectID.
+func CallerFromContext(ctx context.Context) zapcore.Field {
+	return Caller(auth.GetPrincipal(ctx))
+}
+
+func Attr(attr any) zapcore.Field {
+	return zap.Any("attr", attr)
+}
+
+func Tags(tags ...string) zapcore.Field {
+	return zap.Strings("tags", tags)
+}