Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5f81dca
Enable A365 tracing in agentserver-core when hosted
singankit May 4, 2026
0392a27
Add agent_id, blueprint_id, and tenant_id resolution to tracing enric…
singankit May 4, 2026
8db62c6
Enable a365_enable_observability_exporter in A365 tracing config
singankit May 4, 2026
d8bb33e
Add a365_observability_scope_override to A365 tracing config
singankit May 5, 2026
a0c1637
Fix streaming context: capture full context (span + baggage) for iter…
singankit May 5, 2026
046cc7b
Fix baggage propagation: extract only W3C baggage from request headers
singankit May 6, 2026
aee8584
Fix W3C baggage propagation in invocations and add tests for both pac…
singankit May 6, 2026
167bd4a
Fix test: remove assertion for server-added baggage at span start time
singankit May 6, 2026
ce9ae4f
Fix test: use correct span name 'invoke_agent' instead of 'create_res…
singankit May 6, 2026
dab1c87
Fix invocations test: remove assertion for server-added baggage at sp…
singankit May 6, 2026
078502d
Add bkey/bval to local cspell ignore lists
singankit May 6, 2026
3cda909
Remove unused imports detach_context and set_current_span
singankit May 6, 2026
d9d5982
Add enable_sensitive_data param to configure_observability
singankit May 7, 2026
36b9d38
Fix test assertions to include enable_sensitive_data param
singankit May 7, 2026
0a1e5ec
Add microsoft.foundry.agent.type attribute scoped to invoke_agent spans
singankit May 8, 2026
0c0eea7
Remove invoke_agent SERVER span, keep W3C context propagation
singankit May 13, 2026
b9c187c
Add proper span parenting test for responses package
singankit May 13, 2026
7410482
Bump azure-ai-agentserver-core min dependency to >=2.0.0b4
singankit May 14, 2026
21e8641
Make request_context backward-compatible with core 2.0.0b3
singankit May 14, 2026
69b2660
Add e2e span parenting test with real caller span
singankit May 14, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,13 @@ def __init__(

# Observability (logging + tracing) --------------------------------
_conn_str = applicationinsights_connection_string or self.config.appinsights_connection_string
_sensitive_data = os.environ.get("FOUNDRY_ENABLE_SENSITIVE_DATA", "true").lower() not in ("false", "0")
if configure_observability is not None:
try:
configure_observability(
connection_string=_conn_str,
log_level=log_level,
enable_sensitive_data=_sensitive_data,
)
except ValueError:
raise # invalid log_level etc. — user should fix their config
Expand Down Expand Up @@ -326,55 +328,24 @@ def _build_server_version(self) -> str:
# Tracing (for protocol subclasses)
# ------------------------------------------------------------------

#: Default instrumentation scope for tracing spans.
#: Protocol subclasses should override this per the spec.
_INSTRUMENTATION_SCOPE = "Azure.AI.AgentServer"

@contextlib.contextmanager
def request_span(
def request_context(
self,
headers: Any,
request_id: str,
operation: str,
*,
operation_name: Optional[str] = None,
session_id: str = "",
end_on_exit: bool = True,
) -> Any:
"""Create a request-scoped span with this host's identity attributes.
"""Extract W3C trace context and attach as the current OTel context.

Delegates to :func:`_tracing.request_span` with pre-populated
agent identity from environment variables.
Delegates to :func:`_tracing.request_context`. No span is created —
this only ensures downstream framework spans are correctly parented
under the caller's trace context.

:param headers: HTTP request headers.
:type headers: any
:param request_id: The request/invocation ID.
:type request_id: str
:param operation: Span operation (e.g. ``"invoke_agent"``).
:type operation: str
:keyword operation_name: Optional ``gen_ai.operation.name`` value.
:paramtype operation_name: str or None
:keyword session_id: Session ID.
:paramtype session_id: str
:keyword end_on_exit: Whether to end the span when the context exits.
:paramtype end_on_exit: bool
:return: Context manager yielding the OTel span.
:return: Context manager (yields nothing).
:rtype: any
"""
with _tracing.request_span(
headers,
request_id,
operation,
agent_id=self.config.agent_id,
agent_name=self.config.agent_name,
agent_version=self.config.agent_version,
project_id=self.config.project_id,
operation_name=operation_name,
session_id=session_id,
end_on_exit=end_on_exit,
instrumentation_scope=self._INSTRUMENTATION_SCOPE,
) as span:
yield span
with _tracing.request_context(headers):
yield

# ------------------------------------------------------------------
# Shutdown handler (server-level lifecycle)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@

_ENV_FOUNDRY_AGENT_NAME = "FOUNDRY_AGENT_NAME"
_ENV_FOUNDRY_AGENT_VERSION = "FOUNDRY_AGENT_VERSION"
_ENV_FOUNDRY_AGENT_INSTANCE_CLIENT_ID = "FOUNDRY_AGENT_INSTANCE_CLIENT_ID"
_ENV_FOUNDRY_AGENT_BLUEPRINT_CLIENT_ID = "FOUNDRY_AGENT_BLUEPRINT_CLIENT_ID"
_ENV_FOUNDRY_AGENT_TENANT_ID = "FOUNDRY_AGENT_TENANT_ID"
_ENV_FOUNDRY_HOSTING_ENVIRONMENT = "FOUNDRY_HOSTING_ENVIRONMENT"
_ENV_FOUNDRY_PROJECT_ENDPOINT = "FOUNDRY_PROJECT_ENDPOINT"
_ENV_FOUNDRY_PROJECT_ARM_ID = "FOUNDRY_PROJECT_ARM_ID"
Expand Down Expand Up @@ -283,6 +286,46 @@ def resolve_agent_version() -> str:
return os.environ.get(_ENV_FOUNDRY_AGENT_VERSION, "")


def resolve_agent_id() -> str:
"""Resolve the agent ID.

Resolution order:
1. ``FOUNDRY_AGENT_INSTANCE_CLIENT_ID`` environment variable.
2. ``<agent_name>:<agent_version>`` if both are set.
3. ``<agent_name>`` if only name is set.
4. Empty string if nothing is available.

:return: The resolved agent ID, or an empty string if not determinable.
:rtype: str
"""
agent_id = os.environ.get(_ENV_FOUNDRY_AGENT_INSTANCE_CLIENT_ID, "")
if agent_id:
return agent_id
agent_name = os.environ.get(_ENV_FOUNDRY_AGENT_NAME, "")
agent_version = os.environ.get(_ENV_FOUNDRY_AGENT_VERSION, "")
if agent_name and agent_version:
return f"{agent_name}:{agent_version}"
return agent_name


def resolve_agent_blueprint_id() -> str:
"""Resolve the agent blueprint client ID from the ``FOUNDRY_AGENT_BLUEPRINT_CLIENT_ID`` environment variable.

:return: The agent blueprint client ID, or an empty string if not set.
:rtype: str
"""
return os.environ.get(_ENV_FOUNDRY_AGENT_BLUEPRINT_CLIENT_ID, "")


def resolve_agent_tenant_id() -> str:
"""Resolve the agent tenant ID from the ``FOUNDRY_AGENT_TENANT_ID`` environment variable.

:return: The agent tenant ID, or an empty string if not set.
:rtype: str
"""
return os.environ.get(_ENV_FOUNDRY_AGENT_TENANT_ID, "")


def resolve_project_id() -> str:
"""Resolve the Foundry project ARM resource ID from the ``FOUNDRY_PROJECT_ARM_ID`` environment variable.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class Constants:
# Tracing
APPLICATIONINSIGHTS_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING"
OTEL_EXPORTER_OTLP_ENDPOINT = "OTEL_EXPORTER_OTLP_ENDPOINT"
FOUNDRY_AGENT365_TRACING_ENABLED = "FOUNDRY_AGENT365_TRACING_ENABLED"
FOUNDRY_ENABLE_SENSITIVE_DATA = "FOUNDRY_ENABLE_SENSITIVE_DATA"

# SSE keep-alive
SSE_KEEPALIVE_INTERVAL = "SSE_KEEPALIVE_INTERVAL"
Expand Down
Loading
Loading