Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/dstack/_internal/server/services/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from dstack._internal.server.services import events
from dstack._internal.server.services.locking import get_locker
from dstack._internal.server.services.permissions import get_default_permissions
from dstack._internal.server.utils import otel
from dstack._internal.server.utils.routers import error_forbidden
from dstack._internal.utils import crypto
from dstack._internal.utils.common import get_current_datetime, get_or_error, run_async
Expand Down Expand Up @@ -397,6 +398,7 @@ async def log_in_with_token(session: AsyncSession, token: str) -> Optional[UserM
return None
if user.token.get_plaintext_or_error() != token:
return None
otel.set_current_span_attribute("dstack.user.name", user.name)
return user


Expand Down
11 changes: 11 additions & 0 deletions src/dstack/_internal/server/utils/otel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

if TYPE_CHECKING:
from fastapi import FastAPI
from opentelemetry.util.types import AttributeValue
from sqlalchemy.ext.asyncio import AsyncEngine

try:
Expand Down Expand Up @@ -54,3 +55,13 @@ def record_task_run(name: str, *, error: bool) -> None:
if _task_runs_counter is None:
return
_task_runs_counter.add(1, {"task": name, "status": "error" if error else "success"})


def set_current_span_attribute(key: str, value: "AttributeValue") -> None:
"""
Sets an attribute on the currently active span.
No-op if OpenTelemetry is not installed or tracing is not configured.
"""
if otel_trace is None:
return
otel_trace.get_current_span().set_attribute(key, value)
Loading