diff --git a/logs/zap/entry_encoder_test.go b/logs/zap/entry_encoder_test.go
index c83656708d9aba2e4075acce9ad2d28b88dcbb39..f8dd454a32e930c3aaaa8cbb2a577242f3803d7c 100644
--- a/logs/zap/entry_encoder_test.go
+++ b/logs/zap/entry_encoder_test.go
@@ -35,7 +35,7 @@ func TestEntryEncoder_EncodeEntry(t *testing.T) {
 					logzap.Component("Items.Service"),
 					logzap.Event("Items.Create"),
 					logzap.Object("/spaces/WPNN/envs/9VGP/cols/GxNv/items/W0fl"),
-					logzap.Caller("/users/PHVz"),
+					logzap.Caller(nil, logzap.WithObject("/users/PHVz")),
 					logzap.Attr("any"),
 					logzap.Tags("tag1", "tag2", "tag3"),
 				},
@@ -70,7 +70,7 @@ func BenchmarkEntryEncoderSimple(b *testing.B) {
 	fields := []zapcore.Field{
 		logzap.Event(items.EventCreate),
 		logzap.Object(items.NewItem("WPNN", "9VGP", "GxNv", "W0fl", nil, nil)),
-		logzap.Caller("/system"),
+		logzap.Caller(nil, logzap.WithObject("/system")),
 		logzap.Tags("tag1", "tag2", "tag3"),
 	}
 
@@ -84,7 +84,7 @@ func BenchmarkEntryEncoderUnknownFields(b *testing.B) {
 	fields := []zapcore.Field{
 		logzap.Event(items.EventCreate),
 		logzap.Object(items.NewItem("WPNN", "9VGP", "GxNv", "W0fl", nil, nil)),
-		logzap.Caller("/system"),
+		logzap.Caller(nil, logzap.WithObject("/system")),
 		logzap.Tags("tag1", "tag2", "tag3"),
 	}
 
@@ -102,7 +102,7 @@ func BenchmarkEntryEncoderV2Simple(b *testing.B) {
 	fields := []zapcore.Field{
 		logzap.Event(items.EventCreate),
 		logzap.Object(items.NewItem("WPNN", "9VGP", "GxNv", "W0fl", nil, nil)),
-		logzap.Caller("/system"),
+		logzap.Caller(nil, logzap.WithObject("/system")),
 		logzap.Tags("tag1", "tag2", "tag3"),
 	}
 
@@ -116,7 +116,7 @@ func BenchmarkEntryEncoderV2UnknownFields(b *testing.B) {
 	fields := []zapcore.Field{
 		logzap.Event(items.EventCreate),
 		logzap.Object(items.NewItem("WPNN", "9VGP", "GxNv", "W0fl", nil, nil)),
-		logzap.Caller("/system"),
+		logzap.Caller(nil, logzap.WithObject("/system")),
 		logzap.Tags("tag1", "tag2", "tag3"),
 	}
 
diff --git a/logs/zap/example_test.go b/logs/zap/example_test.go
index 7e27fa307fcabe62ad45b6b2f465fdea1b9a2d21..dc182fb0fb764b9b7ca3a232678564c8878a72b0 100644
--- a/logs/zap/example_test.go
+++ b/logs/zap/example_test.go
@@ -77,7 +77,7 @@ func TestExample(t *testing.T) {
 		logger.Info("Item created",
 			logzap.Event(items.EventCreate),
 			logzap.Object(item),
-			logzap.CallerFromContext(ctx, item.SpaceID),
+			logzap.Caller(ctx, logzap.WithSpace(item.SpaceID)),
 			logzap.Tags("tag1", "tag2", "tag3"),
 		)
 
@@ -85,7 +85,7 @@ func TestExample(t *testing.T) {
 		logger.Warn("Item updated",
 			logzap.Event(items.EventUpdate),
 			logzap.Object(item),
-			logzap.CallerFromContext(ctx, item.SpaceID),
+			logzap.Caller(ctx, logzap.WithSpace(item.SpaceID)),
 			logzap.Attr(map[string]map[string]any{"title": {"old": "old title", "new": "new title"}}),
 		)
 	}
diff --git a/pkg/collections/middleware/logging_middleware.go b/pkg/collections/middleware/logging_middleware.go
index 14c28d1385e0476741f89086061b95ba788d15f3..0eca58657aad52da0644294bf5c3077e87cfa562 100644
--- a/pkg/collections/middleware/logging_middleware.go
+++ b/pkg/collections/middleware/logging_middleware.go
@@ -30,7 +30,7 @@ func (m *loggingMiddleware) Create(ctx context.Context, collection *collections.
 		spaceID = collection.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(collections.EventCollectionCreate),
 	)
 
@@ -46,7 +46,7 @@ func (m *loggingMiddleware) Create(ctx context.Context, collection *collections.
 
 func (m *loggingMiddleware) Delete(ctx context.Context, spaceId string, envId string, collectionId string) (err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 		logzap.Event(collections.EventCollectionDelete),
 		logzap.Object(id.NewCollectionId(spaceId, envId, collectionId)),
 	)
@@ -63,7 +63,7 @@ func (m *loggingMiddleware) Delete(ctx context.Context, spaceId string, envId st
 
 func (m *loggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, options ...*collections.GetOptions) (collection *collections.Collection, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 	)
 
 	collection, err = m.next.Get(ctx, spaceId, envId, collectionId, options...)
@@ -77,7 +77,7 @@ func (m *loggingMiddleware) Get(ctx context.Context, spaceId string, envId strin
 
 func (m *loggingMiddleware) List(ctx context.Context, spaceId string, envId string, filter *collections.Filter) (collections []*collections.Collection, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 	)
 
 	collections, err = m.next.List(ctx, spaceId, envId, filter)
@@ -91,7 +91,7 @@ func (m *loggingMiddleware) List(ctx context.Context, spaceId string, envId stri
 
 func (m *loggingMiddleware) SetSchema(ctx context.Context, spaceId string, envId string, collectionId string, schema *schema.Schema) (err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 		logzap.Event(collections.EventCollectionSetSchema),
 		logzap.Object(id.NewCollectionId(spaceId, envId, collectionId)),
 	)
@@ -108,7 +108,7 @@ func (m *loggingMiddleware) SetSchema(ctx context.Context, spaceId string, envId
 
 func (m *loggingMiddleware) SetState(ctx context.Context, spaceId string, envId string, collectionId string, state *collections.StateInfo) (err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 	)
 
 	err = m.next.SetState(ctx, spaceId, envId, collectionId, state)
@@ -127,7 +127,7 @@ func (m *loggingMiddleware) Update(ctx context.Context, coll *collections.Collec
 		spaceID = coll.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(collections.EventCollectionUpdate),
 		logzap.Object(coll),
 	)
diff --git a/pkg/items/middleware/logging_middleware.go b/pkg/items/middleware/logging_middleware.go
index c8271c58dd1e0c09862bcad7b7c8f60817346a40..1178719ee2ad0190e12316165b2536de67f1324e 100644
--- a/pkg/items/middleware/logging_middleware.go
+++ b/pkg/items/middleware/logging_middleware.go
@@ -26,7 +26,7 @@ func LoggingMiddleware(logger *zap.Logger) Middleware {
 
 func (m *loggingMiddleware) Aggregate(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregateOptions) (result map[string]interface{}, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 	)
 
 	result, err = m.next.Aggregate(ctx, spaceId, envId, collectionId, filter, options...)
@@ -40,7 +40,7 @@ func (m *loggingMiddleware) Aggregate(ctx context.Context, spaceId string, envId
 
 func (m *loggingMiddleware) AggregatePublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 	)
 
 	result, err = m.next.AggregatePublished(ctx, spaceId, envId, collectionId, filter, options...)
@@ -58,7 +58,7 @@ func (m *loggingMiddleware) Archive(ctx context.Context, item *items.Item, optio
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(items.EventArchive),
 		logzap.Object(item),
 	)
@@ -79,7 +79,7 @@ func (m *loggingMiddleware) Create(ctx context.Context, item *items.Item, opts .
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(items.EventCreate),
 	)
 
@@ -99,7 +99,7 @@ func (m *loggingMiddleware) Delete(ctx context.Context, item *items.Item, option
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(items.EventDelete),
 		logzap.Object(item),
 	)
@@ -116,7 +116,7 @@ func (m *loggingMiddleware) Delete(ctx context.Context, item *items.Item, option
 
 func (m *loggingMiddleware) Find(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindOptions) (items []*items.Item, total int, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 	)
 
 	items, total, err = m.next.Find(ctx, spaceId, envId, collectionId, filter, options...)
@@ -131,7 +131,7 @@ func (m *loggingMiddleware) Find(ctx context.Context, spaceId string, envId stri
 
 func (m *loggingMiddleware) FindArchived(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindArchivedOptions) (items []*items.Item, total int, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 	)
 
 	items, total, err = m.next.FindArchived(ctx, spaceId, envId, collectionId, filter, options...)
@@ -145,7 +145,7 @@ func (m *loggingMiddleware) FindArchived(ctx context.Context, spaceId string, en
 
 func (m *loggingMiddleware) FindPublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 	)
 
 	items, total, err = m.next.FindPublished(ctx, spaceId, envId, collectionId, filter, options...)
@@ -159,7 +159,7 @@ func (m *loggingMiddleware) FindPublished(ctx context.Context, spaceId string, e
 
 func (m *loggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetOptions) (item *items.Item, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 		logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)),
 	)
 
@@ -174,7 +174,7 @@ func (m *loggingMiddleware) Get(ctx context.Context, spaceId string, envId strin
 
 func (m *loggingMiddleware) GetPublished(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 		logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)),
 	)
 
@@ -189,7 +189,7 @@ func (m *loggingMiddleware) GetPublished(ctx context.Context, spaceId string, en
 
 func (m *loggingMiddleware) GetRevision(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, revisionId string, options ...*items.GetRevisionOptions) (item *items.Item, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 		logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)),
 	)
 
@@ -208,7 +208,7 @@ func (m *loggingMiddleware) Introspect(ctx context.Context, item *items.Item, op
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Object(item),
 	)
 
@@ -223,7 +223,7 @@ func (m *loggingMiddleware) Introspect(ctx context.Context, item *items.Item, op
 
 func (m *loggingMiddleware) ListRevisions(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.ListRevisionsOptions) (items []*items.Item, err error) {
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceId),
+		logzap.Caller(ctx, logzap.WithSpace(spaceId)),
 		logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)),
 	)
 
@@ -242,7 +242,7 @@ func (m *loggingMiddleware) Publish(ctx context.Context, item *items.Item, optio
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(items.EventPublish),
 		logzap.Object(item),
 	)
@@ -263,7 +263,7 @@ func (m *loggingMiddleware) Unarchive(ctx context.Context, item *items.Item, opt
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(items.EventUnarchive),
 		logzap.Object(item),
 	)
@@ -284,7 +284,7 @@ func (m *loggingMiddleware) Undelete(ctx context.Context, item *items.Item, opti
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(items.EventUndelete),
 		logzap.Object(item),
 	)
@@ -305,7 +305,7 @@ func (m *loggingMiddleware) Unpublish(ctx context.Context, item *items.Item, opt
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(items.EventUnpublish),
 		logzap.Object(item),
 	)
@@ -326,7 +326,7 @@ func (m *loggingMiddleware) Update(ctx context.Context, item *items.Item, option
 		spaceID = item.SpaceID
 	}
 	logger := m.logger.With(
-		logzap.CallerFromContext(ctx, spaceID),
+		logzap.Caller(ctx, logzap.WithSpace(spaceID)),
 		logzap.Event(items.EventUpdate),
 		logzap.Object(item),
 	)
diff --git a/zap/field.go b/zap/field.go
index 4e5ec75e7f5fffbd6f1af83fd44c6a434d3190c3..d687bacc49c8e9599611e88590093c5756771896 100644
--- a/zap/field.go
+++ b/zap/field.go
@@ -2,7 +2,6 @@ package zap
 
 import (
 	"context"
-
 	"git.perx.ru/perxis/perxis-go/id"
 	_ "git.perx.ru/perxis/perxis-go/id/system" // регистрируем обработчики для системных объектов
 	"git.perx.ru/perxis/perxis-go/pkg/auth"
@@ -47,22 +46,42 @@ func Object(v any) zap.Field {
 	return zap.Reflect("object", oid)
 }
 
-// Caller возвращает поле и устанавливает передаваемый аргумент в качестве "вызывающего" в формате ObjectId.
-// Поддерживает типы в формате ObjectId: id.Descriptor, string, map[string]any, системные объекты.
-func Caller(v any) zap.Field {
-	oid, _ := id.NewObjectId(v)
-	return zap.Reflect("caller", oid)
+type callerConfig struct {
+	object  any
+	spaceID string
 }
 
-// CallerFromContext извлекает auth.Principal из контекста и устанавливает его в качестве "вызывающего" в формате Object.
-// Вторым параметром передается идентификатор пространства, который требуется, если вызывающий является auth.SpaceAccessor.
-// Если вызывающий не связан с пространством, следует передать пустую строку.
-func CallerFromContext(ctx context.Context, spaceID string) zap.Field {
-	principal := auth.GetPrincipal(ctx)
-	if accessor, ok := principal.(auth.SpaceAccessor); ok && spaceID != "" {
-		principal = accessor.Space(spaceID)
+type CallerOption func(c *callerConfig)
+
+func WithObject(object any) CallerOption {
+	return func(c *callerConfig) {
+		c.object = object
 	}
-	return Caller(principal)
+}
+
+func WithSpace(spaceID string) CallerOption {
+	return func(c *callerConfig) {
+		c.spaceID = spaceID
+	}
+}
+
+// Caller возвращает поле и устанавливает в зависимости от переданных опций "вызывающего" в формате ObjectId.
+func Caller(ctx context.Context, options ...CallerOption) zap.Field {
+	c := new(callerConfig)
+	for _, o := range options {
+		o(c)
+	}
+	var oid *id.ObjectId
+	if c.object != nil {
+		oid, _ = id.NewObjectId(c.object)
+	} else if ctx != nil {
+		principal := auth.GetPrincipal(ctx)
+		if accessor, ok := principal.(auth.SpaceAccessor); ok && c.spaceID != "" {
+			principal = accessor.Space(c.spaceID)
+		}
+		oid, _ = id.NewObjectId(principal)
+	}
+	return zap.Reflect("caller", oid)
 }
 
 func Attr(attr any) zap.Field {
diff --git a/zap/field_test.go b/zap/field_test.go
index 1e050bdcdc95a031cc00980309b650eac98c283b..d2559d5e3e7059fdbfc457cdc0111a7c41d44c80 100644
--- a/zap/field_test.go
+++ b/zap/field_test.go
@@ -132,43 +132,19 @@ func TestCaller(t *testing.T) {
 
 	oid := id.MustObjectId(user)
 	userId := id.NewUserId(user.ID)
-
-	tests := []struct {
-		name  string
-		field zap.Field
-		want  zap.Field
-	}{
-		{name: "system object", field: Caller(user), want: zap.Reflect("caller", oid)},
-		{name: "object id", field: Caller(userId), want: zap.Reflect("caller", oid)},
-		{name: "string", field: Caller(oid.String()), want: zap.Reflect("caller", oid)},
-		{name: "invalid", field: Caller(nil), want: zap.Reflect("caller", (*id.ObjectId)(nil))},
-	}
-
-	for _, tc := range tests {
-		t.Run(tc.name, func(t *testing.T) {
-			wantObjectId, ok1 := tc.want.Interface.(*id.ObjectId)
-			fieldObjectId, ok2 := tc.field.Interface.(*id.ObjectId)
-
-			if ok1 && ok2 && wantObjectId != nil && fieldObjectId != nil {
-				assert.Equal(t, wantObjectId.String(), fieldObjectId.String())
-			} else {
-				assert.Equal(t, tc.want.Interface, tc.field.Interface)
-			}
-		})
-	}
-}
-
-func TestCallerFromContext(t *testing.T) {
 	ctx := auth.WithSystem(context.Background())
-	oid := id.MustObjectId(auth.GetPrincipal(ctx))
 
 	tests := []struct {
 		name  string
 		field zap.Field
 		want  zap.Field
 	}{
-		{name: "ok", field: CallerFromContext(ctx, ""), want: zap.Reflect("caller", oid)},
-		{name: "invalid", field: CallerFromContext(context.TODO(), ""), want: zap.Reflect("caller", (*id.ObjectId)(nil))},
+		{name: "system object", field: Caller(nil, WithObject(user)), want: zap.Reflect("caller", oid)},
+		{name: "object id", field: Caller(nil, WithObject(userId)), want: zap.Reflect("caller", oid)},
+		{name: "string", field: Caller(nil, WithObject(oid.String())), want: zap.Reflect("caller", oid)},
+		{name: "invalid", field: Caller(nil), want: zap.Reflect("caller", (*id.ObjectId)(nil))},
+		{name: "context", field: Caller(ctx), want: zap.Reflect("caller", id.MustObjectId(auth.GetPrincipal(ctx)))},
+		{name: "invalid context", field: Caller(context.TODO()), want: zap.Reflect("caller", (*id.ObjectId)(nil))},
 	}
 
 	for _, tc := range tests {