diff --git a/src/dstack/_internal/core/models/events.py b/src/dstack/_internal/core/models/events.py index 3fb556101e..caf6d60e47 100644 --- a/src/dstack/_internal/core/models/events.py +++ b/src/dstack/_internal/core/models/events.py @@ -37,6 +37,15 @@ class EventTarget(CoreModel): ) ), ] + project_name: Annotated[ + Optional[str], + Field( + description=( + "Name of the project the target entity belongs to," + " or `null` for target types not bound to a project (e.g., users)" + ) + ), + ] id: Annotated[uuid.UUID, Field(description="ID of the target entity")] name: Annotated[str, Field(description="Name of the target entity")] diff --git a/src/dstack/_internal/server/services/events.py b/src/dstack/_internal/server/services/events.py index 34e7b72378..028570fb86 100644 --- a/src/dstack/_internal/server/services/events.py +++ b/src/dstack/_internal/server/services/events.py @@ -370,7 +370,12 @@ async def list_events( .order_by(*order_by) .limit(limit) .options( - joinedload(EventModel.targets), + ( + joinedload(EventModel.targets) + .joinedload(EventTargetModel.entity_project) + .load_only(ProjectModel.name) + .noload(ProjectModel.owner) + ), joinedload(EventModel.actor_user).load_only(UserModel.name), ) ) @@ -395,6 +400,7 @@ def event_model_to_event(event_model: EventModel) -> Event: EventTarget( type=target.entity_type, project_id=target.entity_project_id, + project_name=target.entity_project.name if target.entity_project else None, id=target.entity_id, name=target.entity_name, ) diff --git a/src/tests/_internal/server/routers/test_events.py b/src/tests/_internal/server/routers/test_events.py index 149f28ee3a..8cdf386661 100644 --- a/src/tests/_internal/server/routers/test_events.py +++ b/src/tests/_internal/server/routers/test_events.py @@ -79,6 +79,7 @@ async def test_response_format(self, session: AsyncSession, client: AsyncClient) { "type": "project", "project_id": str(project.id), + "project_name": "test_project", "id": str(project.id), "name": "test_project", }, @@ -94,12 +95,14 @@ async def test_response_format(self, session: AsyncSession, client: AsyncClient) { "type": "project", "project_id": str(project.id), + "project_name": "test_project", "id": str(project.id), "name": "test_project", }, { "type": "user", "project_id": None, + "project_name": None, "id": str(user.id), "name": "test_user", },