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
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
import time
from collections.abc import Callable, Sequence
from typing import Any, final
from urllib.parse import urlparse

import requests
from microsoft_agents_a365.runtime.power_platform_api_discovery import PowerPlatformApiDiscovery
from opentelemetry.sdk.trace import ReadableSpan
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
from opentelemetry.trace import StatusCode
Expand All @@ -25,6 +23,7 @@
INVOKE_AGENT_OPERATION_NAME,
)
from .utils import (
build_export_url,
get_validated_domain_override,
hex_span_id,
hex_trace_id,
Expand All @@ -39,6 +38,7 @@
# Hardcoded constants - not configurable
DEFAULT_HTTP_TIMEOUT_SECONDS = 30.0
DEFAULT_MAX_RETRIES = 3
DEFAULT_ENDPOINT_URL = "https://agent365.svc.cloud.microsoft"

# Create logger for this module - inherits from 'microsoft_agents_a365.observability.core'
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -97,30 +97,13 @@ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
payload = self._build_export_request(activities)
body = json.dumps(payload, separators=(",", ":"), ensure_ascii=False)

# Resolve endpoint + token
# Resolve endpoint: domain override > default URL
if self._domain_override:
endpoint = self._domain_override
else:
discovery = PowerPlatformApiDiscovery(self._cluster_category)
endpoint = discovery.get_tenant_island_cluster_endpoint(tenant_id)
endpoint = DEFAULT_ENDPOINT_URL

endpoint_path = (
f"/maven/agent365/service/agents/{agent_id}/traces"
if self._use_s2s_endpoint
else f"/maven/agent365/agents/{agent_id}/traces"
)

# Construct URL - if endpoint has a scheme (http:// or https://), use it as-is
# Otherwise, prepend https://
# Note: Check for "://" to distinguish between real protocols and domain:port format
# (urlparse treats "example.com:8080" as having scheme="example.com")
parsed = urlparse(endpoint)
if parsed.scheme and "://" in endpoint:
# Endpoint is a full URL, append path
url = f"{endpoint}{endpoint_path}?api-version=1"
else:
# Endpoint is just a domain (possibly with port), prepend https://
url = f"https://{endpoint}{endpoint_path}?api-version=1"
url = build_export_url(endpoint, agent_id, tenant_id, self._use_s2s_endpoint)

# Debug: Log endpoint being used
logger.info(
Expand All @@ -146,6 +129,7 @@ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:

# Basic retry loop
ok = self._post_with_retries(url, body, headers)

if not ok:
any_failure = True

Expand All @@ -169,8 +153,6 @@ def shutdown(self) -> None:
def force_flush(self, timeout_millis: int = 30000) -> bool:
return True

# ------------- Helper methods -------------------

# ------------- HTTP helper ----------------------

@staticmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,32 @@ def get_validated_domain_override() -> str | None:
return domain_override


def build_export_url(
endpoint: str, agent_id: str, tenant_id: str, use_s2s_endpoint: bool = False
) -> str:
"""Construct the full export URL from endpoint and agent ID.

Args:
endpoint: Base endpoint URL or domain.
agent_id: The agent identifier to include in the URL path.
tenant_id: The tenant identifier to include in the URL path.
use_s2s_endpoint: Whether to use the S2S endpoint path format.

Returns:
The fully constructed export URL with path and query parameters.
"""
endpoint_path = (
f"/observabilityService/tenants/{tenant_id}/agents/{agent_id}/traces"
if use_s2s_endpoint
else f"/observability/tenants/{tenant_id}/agents/{agent_id}/traces"
)

parsed = urlparse(endpoint)
if parsed.scheme and "://" in endpoint:
return f"{endpoint}{endpoint_path}?api-version=1"
return f"https://{endpoint}{endpoint_path}?api-version=1"


def is_agent365_exporter_enabled() -> bool:
"""Check if Agent 365 exporter is enabled."""
# Check environment variable
Expand Down
Loading