diff --git a/log/log.go b/log/log.go
index fb22b272af5a982684271044a3ce52ee712a4fad..e3a9f110bb8be6f7d85a9494a493f7090c3b6aac 100644
--- a/log/log.go
+++ b/log/log.go
@@ -1,10 +1,11 @@
 package log
 
 import (
+	"maps"
 	"time"
 
+	"git.perx.ru/perxis/perxis-go/id"
 	pb "git.perx.ru/perxis/perxis-go/proto/log"
-	"github.com/mitchellh/mapstructure"
 	"google.golang.org/protobuf/types/known/timestamppb"
 )
 
@@ -34,8 +35,8 @@ type Entry struct {
 	Category  string      `json:"category,omitempty" bson:"category,omitempty" mapstructure:"category,omitempty"`
 	Component string      `json:"component,omitempty" bson:"component,omitempty" mapstructure:"component,omitempty"`
 	Event     string      `json:"event,omitempty" bson:"event,omitempty" mapstructure:"event,omitempty"`
-	Object    string      `json:"object,omitempty" bson:"object,omitempty" mapstructure:"object,omitempty"`
-	Caller    string      `json:"caller,omitempty" bson:"caller,omitempty" mapstructure:"caller,omitempty"`
+	ObjectID  *id.ID      `json:"object_id,omitempty" bson:"object_id,omitempty" mapstructure:"object_id,omitempty"`
+	CallerID  *id.ID      `json:"caller_id,omitempty" bson:"caller_id,omitempty" mapstructure:"caller_id,omitempty"`
 	Attr      interface{} `json:"attr,omitempty" bson:"attr,omitempty" mapstructure:"attr,omitempty"`
 	Tags      []string    `json:"tags,omitempty" bson:"tags,omitempty" mapstructure:"tags,omitempty"`
 }
@@ -59,16 +60,21 @@ func EntryToPB(entry *Entry) *pb.LogEntry {
 		Category:  entry.Category,
 		Component: entry.Component,
 		Event:     entry.Event,
-		Object:    entry.Object,
-		Caller:    entry.Caller,
 		Attr:      nil, //implement
 		Tags:      entry.Tags,
 	}
+	if entry.ObjectID != nil {
+		logEntry.ObjectId = entry.ObjectID.String()
+	}
+	if entry.CallerID != nil {
+		logEntry.CallerId = entry.CallerID.String()
+	}
+
 	return logEntry
 }
 
 func EntryFromPB(request *pb.LogEntry) *Entry {
-	return &Entry{
+	logEntry := &Entry{
 		ID:        request.Id,
 		Timestamp: request.Timestamp.AsTime(),
 		LogLevel:  Level(request.Level),
@@ -76,15 +82,46 @@ func EntryFromPB(request *pb.LogEntry) *Entry {
 		Category:  request.Category,
 		Component: request.Component,
 		Event:     request.Event,
-		Object:    request.Object,
-		Caller:    request.Caller,
-		Attr:      request.Attr, // todo: как с этим работать?
-		Tags:      request.Tags,
 	}
+
+	if request.ObjectId != "" {
+		logEntry.ObjectID, _ = id.Parse(request.ObjectId)
+	}
+	if request.CallerId != "" {
+		logEntry.CallerID, _ = id.Parse(request.CallerId)
+	}
+	if request.Attr != nil {
+		logEntry.Attr = request.Attr // todo: как с этим работать?
+	}
+	if request.Tags != nil {
+		logEntry.Tags = request.Tags
+	}
+
+	return logEntry
 }
 
-func (e *Entry) ToMap() map[string]interface{} {
-	res := make(map[string]interface{})
-	_ = mapstructure.Decode(e, &res)
+func (e *Entry) ToMap() map[string]any {
+	res := map[string]any{
+		"id":        e.ID,
+		"timestamp": e.Timestamp,
+		"log_level": e.LogLevel,
+		"message":   e.Message,
+		"category":  e.Category,
+		"component": e.Component,
+		"event":     e.Event,
+	}
+	if e.ObjectID != nil {
+		res["object_id"] = e.ObjectID.String()
+		maps.Copy(res, e.ObjectID.ToMap())
+	}
+	if e.CallerID != nil {
+		res["caller_id"] = e.CallerID.String()
+	}
+	if e.Attr != nil {
+		res["attr"] = e.Attr
+	}
+	if e.Tags != nil {
+		res["tags"] = e.Tags
+	}
 	return res
 }
diff --git a/log/log_test.go b/log/log_test.go
index 2f63f5353a1c3a3a0b1cc3dfcc807e52c0b13a28..52fea5be0c1f661b99cfc2f5883e476ee32282b4 100644
--- a/log/log_test.go
+++ b/log/log_test.go
@@ -4,6 +4,7 @@ import (
 	"testing"
 	"time"
 
+	"git.perx.ru/perxis/perxis-go/id"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -16,8 +17,8 @@ func TestEntry_ToMap(t *testing.T) {
 		Category  string
 		Component string
 		Event     string
-		Object    string
-		Caller    string
+		ObjectId  *id.ID
+		CallerId  *id.ID
 		Attr      interface{}
 		Tags      []string
 	}
@@ -29,19 +30,19 @@ func TestEntry_ToMap(t *testing.T) {
 		{
 			"#1",
 			fields{
-				ID:        "1",
-				Timestamp: time.Time{},
-				Message:   "message",
-				Object:    "/spaces/<space_id>/envs/<env_id>",
-				Caller:    "/users/<user_id>",
-			},
-			map[string]interface{}{
-				"id":        "1",
-				"timestamp": map[string]interface{}{},
-				"message":   "message",
-				"object":    "/spaces/<space_id>/envs/<env_id>",
-				"caller":    "/users/<user_id>",
+				"1",
+				time.Time{},
+				0,
+				"message",
+				"",
+				"",
+				"",
+				id.NewEnvironmentID("<space_id>", "<env_id>"),
+				id.NewUserID("<user_id>"),
+				nil,
+				nil,
 			},
+			map[string]interface{}{"caller_id": "/users/<user_id>", "category": "", "component": "", "event": "", "id": "1", "log_level": Level(0), "message": "message", "object_id": "/spaces/<space_id>/envs/<env_id>", "timestamp": time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC)},
 		},
 	}
 	for _, tt := range tests {
@@ -54,12 +55,12 @@ func TestEntry_ToMap(t *testing.T) {
 				Category:  tt.fields.Category,
 				Component: tt.fields.Component,
 				Event:     tt.fields.Event,
-				Object:    tt.fields.Object,
-				Caller:    tt.fields.Caller,
+				ObjectID:  tt.fields.ObjectId,
+				CallerID:  tt.fields.CallerId,
 				Attr:      tt.fields.Attr,
 				Tags:      tt.fields.Tags,
 			}
-			assert.Equal(t, e.ToMap(), tt.want)
+			assert.Equal(t, tt.want, e.ToMap())
 		})
 	}
 }
diff --git a/perxis-proto b/perxis-proto
index 63410745d6008eaa9d9b00626b5f5b6891ac9189..78fe6a1ea7e2fe588e4107bf14ac85293b201163 160000
--- a/perxis-proto
+++ b/perxis-proto
@@ -1 +1 @@
-Subproject commit 63410745d6008eaa9d9b00626b5f5b6891ac9189
+Subproject commit 78fe6a1ea7e2fe588e4107bf14ac85293b201163
diff --git a/proto/log/log.pb.go b/proto/log/log.pb.go
index 14cf7c042aec8364a2883ff5d42555da012ede6e..e25f01596081236521333ed1f2167a967ebea583 100644
--- a/proto/log/log.pb.go
+++ b/proto/log/log.pb.go
@@ -133,14 +133,14 @@ type LogEntry struct {
 	// /orgs/<org_id> - организация
 	// /users/<user_id> - пользователь
 	// /services/<service_id> - сервис
-	Object string `protobuf:"bytes,8,opt,name=object,proto3" json:"object,omitempty"`
+	ObjectId string `protobuf:"bytes,8,opt,name=object_id,json=objectId,proto3" json:"object_id,omitempty"`
 	// caller содержит идентификатор сущности вызвавшей событиe, аналогично полю object
 	//
 	// Примеры:
 	// /users/<user_id> - пользователь
 	// /spaces/<space_id>/clients/<client_id> - клиент
 	// /services/<service_id> - сервис
-	Caller string `protobuf:"bytes,9,opt,name=caller,proto3" json:"caller,omitempty"`
+	CallerId string `protobuf:"bytes,9,opt,name=caller_id,json=callerId,proto3" json:"caller_id,omitempty"`
 	// attr содержит дополнительные связанные с событием атрибуты в формате Any
 	// позволяет добавить дополнительные данные в событие
 	Attr *anypb.Any `protobuf:"bytes,10,opt,name=attr,proto3" json:"attr,omitempty"`
@@ -229,16 +229,16 @@ func (x *LogEntry) GetEvent() string {
 	return ""
 }
 
-func (x *LogEntry) GetObject() string {
+func (x *LogEntry) GetObjectId() string {
 	if x != nil {
-		return x.Object
+		return x.ObjectId
 	}
 	return ""
 }
 
-func (x *LogEntry) GetCaller() string {
+func (x *LogEntry) GetCallerId() string {
 	if x != nil {
-		return x.Caller
+		return x.CallerId
 	}
 	return ""
 }
@@ -266,7 +266,7 @@ var file_log_log_proto_rawDesc = []byte{
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
 	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 	0x1a, 0x12, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd1, 0x02, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72,
+	0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdb, 0x02, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72,
 	0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
 	0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02,
 	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
@@ -280,22 +280,22 @@ var file_log_log_proto_rawDesc = []byte{
 	0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e,
 	0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
 	0x6e, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x62,
-	0x6a, 0x65, 0x63, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65,
-	0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x04, 0x61, 0x74,
-	0x74, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04,
-	0x61, 0x74, 0x74, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x03,
-	0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x2a, 0x45, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c,
-	0x65, 0x76, 0x65, 0x6c, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12, 0x0b,
-	0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45,
-	0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43,
-	0x41, 0x4c, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x42,
-	0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x2e, 0x70, 0x65, 0x72, 0x78, 0x2e, 0x72, 0x75, 0x2f, 0x70,
-	0x65, 0x72, 0x78, 0x69, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x78, 0x69, 0x73, 0x2d, 0x67, 0x6f, 0x2f,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x6f, 0x67, 0x3b, 0x6c, 0x6f, 0x67, 0x62, 0x06, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x62,
+	0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f,
+	0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+	0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x6c, 0x6c,
+	0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x61, 0x74, 0x74, 0x72, 0x18, 0x0a, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x61, 0x74, 0x74, 0x72, 0x12, 0x12,
+	0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61,
+	0x67, 0x73, 0x2a, 0x45, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x08,
+	0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e,
+	0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02,
+	0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x09,
+	0x0a, 0x05, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74,
+	0x2e, 0x70, 0x65, 0x72, 0x78, 0x2e, 0x72, 0x75, 0x2f, 0x70, 0x65, 0x72, 0x78, 0x69, 0x73, 0x2f,
+	0x70, 0x65, 0x72, 0x78, 0x69, 0x73, 0x2d, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
+	0x6c, 0x6f, 0x67, 0x3b, 0x6c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (