Enable tracing and logging for Microsoft Agent Framework (MAF) workflows. Configures OpenTelemetry export to Azure Application Insights and/or a generic OTLP en
复制下面这句话,粘贴给 Claude Code、Codex、Cursor 等 AI 编程工具,它会读取安装说明并在你确认后完成安装。
请阅读 https://ai.atlankj.com/install/asset/gh-maf-tracing-40128039bfbb ,按照其中的说明把「maf-tracing」安装到你(当前 AI 工具)中。执行前先告诉我将运行的命令和写入的位置,等我确认。
查看 AI 将读取的安装说明正在读取 GitHub 原文…
内容来自 GitHub 原始文件,由原作者维护。在 GitHub 查看
Configure OpenTelemetry-based tracing for Microsoft Agent Framework workflows, exporting to Azure Application Insights and/or a generic OTLP endpoint.
Activate this skill when the user wants to:
agent-framework projectMAF automatically emits OpenTelemetry spans for every executor invocation, agent call, and LLM request. No instrumentation changes are needed inside Executor classes. You only need to:
configure_otel_providers() — activates MAF's built-in instrumentationThis must happen once at application startup, before any workflow.run() calls.
requirements.txt, .env, and entry-point script (e.g., main.py, app.py, run_*.py).tracer.start_span() calls inside @handler methods unless the user explicitly asks for custom spans.configure_otel_providers(), and both must happen BEFORE any workflow.run().requirements.txt — Append only the packages the user needs (see Packages section). Do not duplicate existing entries.os.environ or .env..env.example — Provide a template showing which environment variables are required.logging module to export via OpenTelemetry using opentelemetry-sdk log handler.| Variable | Required For | Description |
|---|---|---|
APPLICATIONINSIGHTS_CONNECTION_STRING | Application Insights | Connection string from Azure Portal → App Insights → Overview |
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP export | Base URL of the OTLP collector (e.g., http://localhost:4318) |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT | OTLP export (traces only) | Overrides the base endpoint for trace signals only |
OTEL_EXPORTER_OTLP_PROTOCOL | OTLP export | Protocol: http/protobuf (default) or grpc |
OTEL_SERVICE_NAME | Optional | Service name shown in trace backends (defaults to Python process name) |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINTtakes precedence overOTEL_EXPORTER_OTLP_ENDPOINTfor traces.
| Package | Version | When Needed |
|---|---|---|
agent-framework | >=1.0.1 | Always (provides configure_otel_providers) |
azure-monitor-opentelemetry | >=1.6.4 | Application Insights export |
opentelemetry-exporter-otlp-proto-http | >=1.25.0 | OTLP/HTTP export |
opentelemetry-exporter-otlp-proto-grpc | >=1.25.0 | OTLP/gRPC export (only if OTEL_EXPORTER_OTLP_PROTOCOL=grpc) |
opentelemetry-sdk | >=1.25.0 | Custom spans or Python logging integration |
python-dotenv | any | Loading .env files |
Use when the user wants to send traces to Azure Application Insights.
Required env var: APPLICATIONINSIGHTS_CONNECTION_STRING
Required packages:
azure-monitor-opentelemetry>=1.6.4
Setup code (add at the top of the entry-point script, before workflow.run()):
import os
from dotenv import load_dotenv
from azure.monitor.opentelemetry import configure_azure_monitor
from agent_framework.observability import configure_otel_providers
load_dotenv()
# Step 1: Configure Azure Monitor exporter (traces, metrics, logs → App Insights)
configure_azure_monitor(
connection_string=os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"]
)
# Step 2: Enable MAF's built-in instrumentation (executor, agent, LLM spans)
configure_otel_providers()
Use when the user wants to send traces to a generic OTLP-compatible backend (Jaeger, Grafana Tempo, Aspire Dashboard, etc.).
Required env var: OTEL_EXPORTER_OTLP_ENDPOINT
Required packages:
opentelemetry-sdk>=1.25.0
opentelemetry-exporter-otlp-proto-http>=1.25.0
Setup code:
import os
from dotenv import load_dotenv
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from agent_framework.observability import configure_otel_providers
load_dotenv()
# Step 1: Set up the OTLP exporter with a TracerProvider
resource = Resource.create({
"service.name": os.environ.get("OTEL_SERVICE_NAME", "maf-workflow"),
})
tracer_provider = TracerProvider(resource=resource)
otlp_exporter = OTLPSpanExporter(
endpoint=os.environ.get("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT")
or os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT"),
)
tracer_provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
trace.set_tracer_provider(tracer_provider)
# Step 2: Enable MAF's built-in instrumentation
configure_otel_providers()
Use when the user wants dual export — Application Insights for Azure-native monitoring plus an OTLP backend for local/third-party observability.
Required env vars: APPLICATIONINSIGHTS_CONNECTION_STRING, OTEL_EXPORTER_OTLP_ENDPOINT
Required packages:
azure-monitor-opentelemetry>=1.6.4
opentelemetry-sdk>=1.25.0
opentelemetry-exporter-otlp-proto-http>=1.25.0
Setup code:
import os
from dotenv import load_dotenv
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from agent_framework.observability import configure_otel_providers
load_dotenv()
# Step 1a: Configure Azure Monitor (sets up its own TracerProvider internally)
configure_azure_monitor(
connection_string=os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"]
)
# Step 1b: Add OTLP exporter to the existing TracerProvider
otlp_endpoint = (
os.environ.get("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT")
or os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT")
)
if otlp_endpoint:
otlp_exporter = OTLPSpanExporter(endpoint=otlp_endpoint)
tracer_provider: TracerProvider = trace.get_tracer_provider()
tracer_provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
# Step 2: Enable MAF's built-in instrumentation
configure_otel_providers()
Use when the user also wants Python logging calls to be exported alongside traces.
Additional packages (on top of Pattern A, B, or C):
opentelemetry-sdk>=1.25.0
Setup code (add after the exporter setup, before configure_otel_providers()):
import logging
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry._logs import set_logger_provider
# If using Application Insights, configure_azure_monitor() already handles log export.
# If using OTLP only, set up the OTLP log exporter:
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
logger_provider = LoggerProvider(resource=resource)
logger_provider.add_log_record_processor(
BatchLogRecordProcessor(OTLPLogExporter(
endpoint=os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT"),
))
)
set_logger_provider(logger_provider)
# Bridge Python logging to OpenTelemetry
from opentelemetry.instrumentation.logging import LoggingInstrumentor
LoggingInstrumentor().instrument(set_logging_format=True)
Note: When using
azure-monitor-opentelemetry(Pattern A/C),configure_azure_monitor()already captures Python logs by default. The above is only needed for OTLP-only setups.
Ask the user or infer from context:
If the user says "tracing" without specifying a destination, default to Pattern C (both).
requirements.txtAppend the required packages. Do not duplicate existing entries. Example additions for Pattern C:
azure-monitor-opentelemetry>=1.6.4
opentelemetry-sdk>=1.25.0
opentelemetry-exporter-otlp-proto-http>=1.25.0
.env.exampleAdd the environment variables relevant to the chosen pattern:
# === Tracing & Observability ===
# Application Insights (Azure Portal → App Insights → Overview → Connection String)
APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=xxx;IngestionEndpoint=https://xxx.in.applicationinsights.azure.com/
# OTLP endpoint (e.g., Jaeger, Grafana Tempo, Aspire Dashboard)
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# Optional: override service name in trace backends
OTEL_SERVICE_NAME=my-maf-workflow
Insert the setup code from the appropriate pattern at the top of the entry-point script (after imports, before any workflow.run() call). The setup must execute once at module load / application startup.
Placement rules:
asyncio.run(main()), place setup code inside main() before workflow.run().load_dotenv().http://localhost:16686).configure_azure_monitor() and/or OTLP exporter setup must happen BEFORE configure_otel_providers(). If reversed, MAF spans won't be exported.configure_otel_providers() must run BEFORE workflow.run() — Otherwise, executor-level spans are not generated.@handler method will create duplicate exporters and corrupt traces.configure_azure_monitor() creates its own TracerProvider — When combining with OTLP (Pattern C), add the OTLP exporter to the existing provider via trace.get_tracer_provider() rather than creating a new TracerProvider.configure_otel_providers() — Without this call, you'll see Application Insights or OTLP infrastructure telemetry but no MAF-specific spans (executor transitions, agent calls, LLM requests).APPLICATIONINSIGHTS_CONNECTION_STRING starts with InstrumentationKey= followed by a GUID. Do not confuse it with the Instrumentation Key alone.OTEL_EXPORTER_OTLP_ENDPOINT should be the base URL (e.g., http://localhost:4318). The SDK appends /v1/traces automatically. Do not include /v1/traces in the env var.http/protobuf (port 4318). If the collector uses gRPC (port 4317), set OTEL_EXPORTER_OTLP_PROTOCOL=grpc and install opentelemetry-exporter-otlp-proto-grpc instead."""Entry point for a MAF workflow with full tracing setup."""
import asyncio
import os
from dotenv import load_dotenv
load_dotenv()
def setup_tracing():
"""Configure telemetry exporters and MAF instrumentation. Call once at startup."""
from agent_framework.observability import configure_otel_providers
# Application Insights
appinsights_conn = os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING")
if appinsights_conn:
from azure.monitor.opentelemetry import configure_azure_monitor
configure_azure_monitor(connection_string=appinsights_conn)
# OTLP endpoint (optional, additive)
otlp_endpoint = (
os.environ.get("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT")
or os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT")
)
if otlp_endpoint:
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
otlp_exporter = OTLPSpanExporter(endpoint=otlp_endpoint)
tracer_provider = trace.get_tracer_provider()
# If Azure Monitor already set a TracerProvider, reuse it; otherwise create one
if not isinstance(tracer_provider, TracerProvider):
resource = Resource.create({
"service.name": os.environ.get("OTEL_SERVICE_NAME", "maf-workflow"),
})
tracer_provider = TracerProvider(resource=resource)
trace.set_tracer_provider(tracer_provider)
tracer_provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
# Enable MAF's built-in spans (must be last)
configure_otel_providers()
async def main():
setup_tracing()
# Import and run your workflow here
from workflow import create_workflow
workflow = create_workflow()
result = await workflow.run("Hello, world!")
print(result.get_outputs())
if __name__ == "__main__":
asyncio.run(main())