|
5 | 5 |
|
6 | 6 | from api.api_routes import router as backend_router |
7 | 7 |
|
8 | | -from azure.monitor.opentelemetry.exporter import AzureMonitorLogExporter, AzureMonitorTraceExporter |
| 8 | +from azure.monitor.opentelemetry import configure_azure_monitor |
9 | 9 |
|
10 | 10 | from common.config.config import app_config |
11 | 11 | from common.logger.app_logger import AppLogger |
| 12 | +from common.telemetry import patch_instrumentors |
12 | 13 |
|
13 | 14 | from dotenv import load_dotenv |
14 | 15 |
|
|
17 | 18 |
|
18 | 19 | from helper.azure_credential_utils import get_azure_credential |
19 | 20 |
|
20 | | -from opentelemetry import trace |
21 | | -from opentelemetry._logs import set_logger_provider |
22 | 21 | from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor |
23 | | -from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler |
24 | | -from opentelemetry.sdk._logs.export import BatchLogRecordProcessor |
25 | | -from opentelemetry.sdk.trace import TracerProvider |
26 | | -from opentelemetry.sdk.trace.export import BatchSpanProcessor |
27 | 22 |
|
28 | 23 | from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent # pylint: disable=E0611 |
29 | 24 |
|
@@ -138,52 +133,23 @@ def create_app() -> FastAPI: |
138 | 133 | # This must happen AFTER app creation but BEFORE route registration |
139 | 134 | instrumentation_key = os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING") |
140 | 135 | if instrumentation_key: |
141 | | - # SOLUTION: Use manual telemetry setup instead of configure_azure_monitor |
142 | | - # This gives us precise control over what gets instrumented, avoiding interference |
143 | | - # with Semantic Kernel's async generators while still tracking Azure SDK calls |
144 | | - |
145 | | - # Set up Azure Monitor exporter for traces |
146 | | - azure_trace_exporter = AzureMonitorTraceExporter(connection_string=instrumentation_key) |
147 | | - |
148 | | - # Create a tracer provider and add the Azure Monitor exporter |
149 | | - tracer_provider = TracerProvider() |
150 | | - tracer_provider.add_span_processor(BatchSpanProcessor(azure_trace_exporter)) |
151 | | - |
152 | | - # Set the global tracer provider |
153 | | - trace.set_tracer_provider(tracer_provider) |
154 | | - |
155 | | - # Set up Azure Monitor exporter for logs (appears in traces table) |
156 | | - azure_log_exporter = AzureMonitorLogExporter(connection_string=instrumentation_key) |
157 | | - |
158 | | - # Create a logger provider and add the Azure Monitor exporter |
159 | | - logger_provider = LoggerProvider() |
160 | | - logger_provider.add_log_record_processor(BatchLogRecordProcessor(azure_log_exporter)) |
161 | | - set_logger_provider(logger_provider) |
162 | | - |
163 | | - # Attach OpenTelemetry handler to Python's root logger |
164 | | - handler = LoggingHandler(logger_provider=logger_provider) |
165 | | - logging.getLogger().addHandler(handler) |
| 136 | + # Fix: Patch buggy instrumentors before Azure Monitor loads them |
| 137 | + # See: https://github.com/microsoft/semantic-kernel/issues/13715 |
| 138 | + patch_instrumentors() |
| 139 | + |
| 140 | + # Configure Azure Monitor with FULL auto-instrumentation |
| 141 | + configure_azure_monitor( |
| 142 | + connection_string=instrumentation_key, |
| 143 | + enable_live_metrics=True |
| 144 | + ) |
166 | 145 |
|
167 | | - # Instrument ONLY FastAPI for HTTP request/response tracing |
168 | | - # This is safe because it only wraps HTTP handlers, not internal async operations |
| 146 | + # Instrument FastAPI for HTTP request/response tracing |
169 | 147 | FastAPIInstrumentor.instrument_app( |
170 | 148 | app, |
171 | | - excluded_urls="socket,ws", # Exclude WebSocket URLs to reduce noise |
172 | | - tracer_provider=tracer_provider |
| 149 | + excluded_urls="health,socket,ws", |
173 | 150 | ) |
174 | 151 |
|
175 | | - # Optional: Add manual spans in your code for Azure SDK operations using: |
176 | | - # from opentelemetry import trace |
177 | | - # tracer = trace.get_tracer(__name__) |
178 | | - # with tracer.start_as_current_span("operation_name"): |
179 | | - # # your Azure SDK call here |
180 | | - |
181 | | - logger.logger.info("Application Insights configured with selective instrumentation") |
182 | | - logger.logger.info("✓ FastAPI HTTP tracing enabled") |
183 | | - logger.logger.info("✓ Python logging export to Application Insights enabled") |
184 | | - logger.logger.info("✓ Manual span support enabled for Azure SDK operations") |
185 | | - logger.logger.info("✓ Custom events via OpenTelemetry enabled") |
186 | | - logger.logger.info("✓ Semantic Kernel async generators unaffected") |
| 152 | + logger.logger.info("Application Insights configured with full auto-instrumentation") |
187 | 153 | else: |
188 | 154 | logger.logger.warning("No Application Insights connection string found. Telemetry disabled.") |
189 | 155 |
|
|
0 commit comments