Skip to content

Commit a480ccf

Browse files
authored
[BREAKING] Python: Observability cleanup (#905)
* Further observability cleanup and update telemetry samples * Add VS Code Extension config * Fix unit tests * Fix unit tests * Add more comments * Remove live metric
1 parent f527fbe commit a480ccf

24 files changed

Lines changed: 725 additions & 494 deletions

python/.env.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,4 @@ ANTHROPIC_MODEL=""
2323
ENABLE_OTEL=true
2424
ENABLE_SENSITIVE_DATA=true
2525
OTLP_ENDPOINT="http://localhost:4317/"
26-
# APPLICATIONINSIGHTS_LIVE_METRICS=false
2726
# APPLICATIONINSIGHTS_CONNECTION_STRING="..."

python/packages/azure-ai/agent_framework_azure_ai/_chat_client.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ def __init__(
165165
model_deployment_name: The model deployment name to use for agent creation.
166166
Can also be set via 'AZURE_AI_MODEL_DEPLOYMENT_NAME' environment variable.
167167
async_credential: Azure async credential to use for authentication.
168-
setup_tracing: Whether to setup tracing for the project_client. Defaults to True.
169168
env_file_path: Path to environment file for loading settings.
170169
env_file_encoding: Encoding of the environment file.
171170
**kwargs: Additional keyword arguments passed to the parent class.
@@ -216,7 +215,7 @@ def __init__(
216215
)
217216
self._should_close_client = should_close_client
218217

219-
async def setup_observability(self, enable_live_metrics: bool = False) -> None:
218+
async def setup_observability(self) -> None:
220219
"""Use this method to setup tracing in your Azure AI Project.
221220
222221
This will take the connection string from the project project_client.
@@ -227,7 +226,6 @@ async def setup_observability(self, enable_live_metrics: bool = False) -> None:
227226

228227
setup_observability(
229228
applicationinsights_connection_string=await self.project_client.telemetry.get_application_insights_connection_string(), # noqa: E501
230-
enable_live_metrics=enable_live_metrics,
231229
)
232230

233231
async def __aenter__(self) -> "Self":

python/packages/devui/agent_framework_devui/_discovery.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async def discover_entities(self) -> list[EntityInfo]:
4040
logger.info("No Agent Framework entities directory configured")
4141
return []
4242

43-
entities_dir = Path(self.entities_dir).resolve()
43+
entities_dir = Path(self.entities_dir).resolve() # noqa: ASYNC240
4444
await self._scan_entities_directory(entities_dir)
4545

4646
logger.info(f"Discovered {len(self._entities)} Agent Framework entities")
@@ -152,7 +152,7 @@ async def _scan_entities_directory(self, entities_dir: Path) -> None:
152152
Args:
153153
entities_dir: Directory to scan for entities
154154
"""
155-
if not entities_dir.exists():
155+
if not entities_dir.exists(): # noqa: ASYNC240
156156
logger.warning(f"Entities directory not found: {entities_dir}")
157157
return
158158

@@ -164,7 +164,7 @@ async def _scan_entities_directory(self, entities_dir: Path) -> None:
164164
sys.path.insert(0, entities_dir_str)
165165

166166
# Scan for directories and Python files
167-
for item in entities_dir.iterdir():
167+
for item in entities_dir.iterdir(): # noqa: ASYNC240
168168
if item.name.startswith(".") or item.name == "__pycache__":
169169
continue
170170

python/packages/lab/gaia/agent_framework_lab_gaia/gaia.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ def __init__(
3333
enable_tracing: bool = False,
3434
otlp_endpoint: str | None = None,
3535
applicationinsights_connection_string: str | None = None,
36-
enable_live_metrics: bool = False,
3736
trace_to_file: bool = False,
3837
file_path: str | None = None,
3938
):
@@ -44,14 +43,12 @@ def __init__(
4443
enable_tracing: Whether to enable OpenTelemetry tracing
4544
otlp_endpoint: OTLP endpoint for trace export
4645
applicationinsights_connection_string: Azure Monitor connection string
47-
enable_live_metrics: Enable Azure Monitor live metrics
4846
trace_to_file: Whether to export traces to local file
4947
file_path: Path for local file export (defaults to gaia_traces.json)
5048
"""
5149
self.enable_tracing = enable_tracing
5250
self.otlp_endpoint = otlp_endpoint
5351
self.applicationinsights_connection_string = applicationinsights_connection_string
54-
self.enable_live_metrics = enable_live_metrics
5552
self.trace_to_file = trace_to_file
5653
self.file_path = file_path or "gaia_traces.json"
5754

@@ -66,7 +63,6 @@ def setup_observability(self) -> None:
6663
enable_sensitive_data=True, # Enable for detailed task traces
6764
otlp_endpoint=self.otlp_endpoint,
6865
applicationinsights_connection_string=self.applicationinsights_connection_string,
69-
enable_live_metrics=self.enable_live_metrics,
7066
)
7167

7268
# Set up local file export if requested

python/packages/lab/gaia/samples/gaia_sample.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ async def main() -> None:
3030
# Optional: Configure external endpoints
3131
# otlp_endpoint="http://localhost:4317", # For Aspire Dashboard or other OTLP endpoints
3232
# applicationinsights_connection_string="your_connection_string", # For Azure Monitor
33-
# enable_live_metrics=True, # Enable Azure Monitor live metrics
3433
# Configure local file tracing
3534
trace_to_file=True, # Export traces to local file
3635
file_path="gaia_benchmark_traces.jsonl", # Custom file path for traces

python/packages/main/agent_framework/_tools.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -404,18 +404,17 @@ async def invoke(
404404
405405
Args:
406406
arguments: A Pydantic model instance containing the arguments for the function.
407-
otel_settings: Optional model diagnostics settings to override the default settings.
408407
kwargs: keyword arguments to pass to the function, will not be used if `arguments` is provided.
409408
"""
410-
global OTEL_SETTINGS
411-
from .observability import OTEL_SETTINGS
409+
global OBSERVABILITY_SETTINGS
410+
from .observability import OBSERVABILITY_SETTINGS
412411

413412
tool_call_id = kwargs.pop("tool_call_id", None)
414413
if arguments is not None:
415414
if not isinstance(arguments, self.input_model):
416415
raise TypeError(f"Expected {self.input_model.__name__}, got {type(arguments).__name__}")
417416
kwargs = arguments.model_dump(exclude_none=True)
418-
if not OTEL_SETTINGS.ENABLED: # type: ignore[name-defined]
417+
if not OBSERVABILITY_SETTINGS.ENABLED: # type: ignore[name-defined]
419418
logger.info(f"Function name: {self.name}")
420419
logger.debug(f"Function arguments: {kwargs}")
421420
res = self.__call__(**kwargs)
@@ -425,7 +424,7 @@ async def invoke(
425424
return result # type: ignore[reportReturnType]
426425

427426
attributes = get_function_span_attributes(self, tool_call_id=tool_call_id)
428-
if OTEL_SETTINGS.SENSITIVE_DATA_ENABLED: # type: ignore[name-defined]
427+
if OBSERVABILITY_SETTINGS.SENSITIVE_DATA_ENABLED: # type: ignore[name-defined]
429428
attributes.update({
430429
OtelAttr.TOOL_ARGUMENTS: arguments.model_dump_json()
431430
if arguments
@@ -436,7 +435,7 @@ async def invoke(
436435
with get_function_span(attributes=attributes) as span:
437436
attributes[OtelAttr.MEASUREMENT_FUNCTION_TAG_NAME] = self.name
438437
logger.info(f"Function name: {self.name}")
439-
if OTEL_SETTINGS.SENSITIVE_DATA_ENABLED: # type: ignore[name-defined]
438+
if OBSERVABILITY_SETTINGS.SENSITIVE_DATA_ENABLED: # type: ignore[name-defined]
440439
logger.debug(f"Function arguments: {kwargs}")
441440
start_time_stamp = perf_counter()
442441
end_time_stamp: float | None = None
@@ -452,7 +451,7 @@ async def invoke(
452451
raise
453452
else:
454453
logger.info(f"Function {self.name} succeeded.")
455-
if OTEL_SETTINGS.SENSITIVE_DATA_ENABLED: # type: ignore[name-defined]
454+
if OBSERVABILITY_SETTINGS.SENSITIVE_DATA_ENABLED: # type: ignore[name-defined]
456455
try:
457456
json_result = json.dumps(result)
458457
except (TypeError, OverflowError):

python/packages/main/agent_framework/_workflow/_workflow_context.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,8 @@ async def send_message(self, message: T_Out, target_id: str | None = None) -> No
356356
target_id: The ID of the target executor to send the message to.
357357
If None, the message will be sent to all target executors.
358358
"""
359-
global OTEL_SETTINGS
360-
from ..observability import OTEL_SETTINGS
359+
global OBSERVABILITY_SETTINGS
360+
from ..observability import OBSERVABILITY_SETTINGS
361361

362362
# Create publishing span (inherits current trace context automatically)
363363
attributes: dict[str, str] = {OtelAttr.MESSAGE_TYPE: type(message).__name__}
@@ -368,7 +368,7 @@ async def send_message(self, message: T_Out, target_id: str | None = None) -> No
368368
msg = Message(data=message, source_id=self._executor_id, target_id=target_id)
369369

370370
# Inject current trace context if tracing enabled
371-
if OTEL_SETTINGS.ENABLED and span and span.is_recording(): # type: ignore[name-defined]
371+
if OBSERVABILITY_SETTINGS.ENABLED and span and span.is_recording(): # type: ignore[name-defined]
372372
trace_context: dict[str, str] = {}
373373
inject(trace_context) # Inject current trace context for message propagation
374374

0 commit comments

Comments
 (0)