@azure/mcp-darwin-x64 2.0.0-beta.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.txt +5683 -4849
- package/README.md +148 -27
- package/dist/Azure.Mcp.Tools.AzureMigrate.xml +1060 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/ActivityProcessors.md +119 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/AddApplicationInsightsTelemetry.md +129 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/AddApplicationInsightsTelemetryWorkerService.md +115 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/AddOpenTelemetry.md +153 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/ApplicationInsightsWeb.md +103 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/AzureMonitorExporter.md +137 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/ConfigureOpenTelemetryProvider.md +218 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/ConfigureResource.md +119 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/ConsoleExporter.md +47 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/EntityFrameworkInstrumentation.md +56 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/HttpInstrumentation.md +109 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/LogProcessors.md +101 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/OpenTelemetrySdkCreate.md +146 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/OtlpExporter.md +88 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/RedisInstrumentation.md +63 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/Sampling.md +86 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/SdkCreateTracerProviderBuilder.md +127 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/SqlClientInstrumentation.md +53 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/TelemetryClient.md +122 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/TelemetryConfigurationBuilder.md +173 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/UseAzureMonitor.md +96 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/UseAzureMonitorExporter.md +146 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/WithLogging.md +109 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/WithMetrics.md +105 -0
- package/dist/Instrumentation/Resources/api-reference/dotnet/WithTracing.md +91 -0
- package/dist/Instrumentation/Resources/concepts/dotnet/appinsights-aspnetcore.md +113 -0
- package/dist/Instrumentation/Resources/concepts/dotnet/aspnet-classic-appinsights.md +95 -0
- package/dist/Instrumentation/Resources/concepts/dotnet/azure-monitor-distro.md +102 -0
- package/dist/Instrumentation/Resources/concepts/dotnet/opentelemetry-pipeline.md +57 -0
- package/dist/Instrumentation/Resources/concepts/nodejs/azure-monitor-overview.md +106 -0
- package/dist/Instrumentation/Resources/concepts/nodejs/opentelemetry-pipeline.md +201 -0
- package/dist/Instrumentation/Resources/concepts/python/azure-monitor-overview.md +122 -0
- package/dist/Instrumentation/Resources/concepts/python/opentelemetry-pipeline.md +154 -0
- package/dist/Instrumentation/Resources/examples/dotnet/aspnet-classic-setup.md +80 -0
- package/dist/Instrumentation/Resources/examples/dotnet/aspnetcore-distro-setup.md +156 -0
- package/dist/Instrumentation/Resources/examples/dotnet/aspnetcore-setup.md +160 -0
- package/dist/Instrumentation/Resources/examples/dotnet/workerservice-setup.md +154 -0
- package/dist/Instrumentation/Resources/examples/nodejs/bunyan-setup.md +301 -0
- package/dist/Instrumentation/Resources/examples/nodejs/console-setup.md +284 -0
- package/dist/Instrumentation/Resources/examples/nodejs/express-setup.md +169 -0
- package/dist/Instrumentation/Resources/examples/nodejs/fastify-setup.md +237 -0
- package/dist/Instrumentation/Resources/examples/nodejs/langchain-js-setup.md +310 -0
- package/dist/Instrumentation/Resources/examples/nodejs/mongodb-setup.md +185 -0
- package/dist/Instrumentation/Resources/examples/nodejs/mysql-setup.md +231 -0
- package/dist/Instrumentation/Resources/examples/nodejs/nestjs-setup.md +184 -0
- package/dist/Instrumentation/Resources/examples/nodejs/nextjs-setup.md +320 -0
- package/dist/Instrumentation/Resources/examples/nodejs/postgres-setup.md +147 -0
- package/dist/Instrumentation/Resources/examples/nodejs/redis-setup.md +198 -0
- package/dist/Instrumentation/Resources/examples/nodejs/winston-setup.md +260 -0
- package/dist/Instrumentation/Resources/examples/python/console-setup.md +392 -0
- package/dist/Instrumentation/Resources/examples/python/django-setup.md +269 -0
- package/dist/Instrumentation/Resources/examples/python/fastapi-setup.md +256 -0
- package/dist/Instrumentation/Resources/examples/python/flask-setup.md +218 -0
- package/dist/Instrumentation/Resources/examples/python/genai-setup.md +214 -0
- package/dist/Instrumentation/Resources/examples/python/generic-setup.md +164 -0
- package/dist/Instrumentation/Resources/migration/dotnet/aad-authentication-migration.md +150 -0
- package/dist/Instrumentation/Resources/migration/dotnet/appinsights-2x-to-3x-code-migration.md +164 -0
- package/dist/Instrumentation/Resources/migration/dotnet/appinsights-2x-to-3x-no-code-change.md +92 -0
- package/dist/Instrumentation/Resources/migration/dotnet/aspnet-classic-2x-to-3x-code-migration.md +190 -0
- package/dist/Instrumentation/Resources/migration/dotnet/console-2x-to-3x-code-migration.md +106 -0
- package/dist/Instrumentation/Resources/migration/dotnet/ilogger-migration.md +54 -0
- package/dist/Instrumentation/Resources/migration/dotnet/workerservice-2x-to-3x-code-migration.md +126 -0
- package/dist/Instrumentation/Resources/migration/dotnet/workerservice-2x-to-3x-no-code-change.md +102 -0
- package/dist/azmcp +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Basic Azure Monitor Setup for Django
|
|
2
|
+
|
|
3
|
+
This guide shows how to add Azure Monitor OpenTelemetry to a Django application.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Python 3.8 or higher
|
|
8
|
+
- Django application
|
|
9
|
+
- Azure Application Insights resource
|
|
10
|
+
|
|
11
|
+
## Step 1: Install Packages
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install azure-monitor-opentelemetry django
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or add to your `requirements.txt`:
|
|
18
|
+
```
|
|
19
|
+
azure-monitor-opentelemetry
|
|
20
|
+
django
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Step 2: Initialize at Startup
|
|
24
|
+
|
|
25
|
+
For Django, you have two options for initialization:
|
|
26
|
+
|
|
27
|
+
### Option A: In manage.py (Recommended for Development)
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
#!/usr/bin/env python
|
|
31
|
+
"""Django's command-line utility for administrative tasks."""
|
|
32
|
+
import os
|
|
33
|
+
import sys
|
|
34
|
+
|
|
35
|
+
def main():
|
|
36
|
+
"""Run administrative tasks."""
|
|
37
|
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
|
|
38
|
+
|
|
39
|
+
# Configure Azure Monitor after Django settings are loaded
|
|
40
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
41
|
+
configure_azure_monitor()
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
from django.core.management import execute_from_command_line
|
|
45
|
+
except ImportError as exc:
|
|
46
|
+
raise ImportError(
|
|
47
|
+
"Couldn't import Django. Are you sure it's installed?"
|
|
48
|
+
) from exc
|
|
49
|
+
execute_from_command_line(sys.argv)
|
|
50
|
+
|
|
51
|
+
if __name__ == '__main__':
|
|
52
|
+
main()
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Option B: In wsgi.py (Recommended for Production)
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
"""
|
|
59
|
+
WSGI config for mysite project.
|
|
60
|
+
"""
|
|
61
|
+
import os
|
|
62
|
+
|
|
63
|
+
# Configure Azure Monitor BEFORE Django loads
|
|
64
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
65
|
+
configure_azure_monitor()
|
|
66
|
+
|
|
67
|
+
from django.core.wsgi import get_wsgi_application
|
|
68
|
+
|
|
69
|
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
|
|
70
|
+
|
|
71
|
+
application = get_wsgi_application()
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Option C: In asgi.py (For async Django/Channels)
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
"""
|
|
78
|
+
ASGI config for mysite project.
|
|
79
|
+
"""
|
|
80
|
+
import os
|
|
81
|
+
|
|
82
|
+
# Configure Azure Monitor BEFORE Django loads
|
|
83
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
84
|
+
configure_azure_monitor()
|
|
85
|
+
|
|
86
|
+
from django.core.asgi import get_asgi_application
|
|
87
|
+
|
|
88
|
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
|
|
89
|
+
|
|
90
|
+
application = get_asgi_application()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Step 3: Configure Connection String
|
|
94
|
+
|
|
95
|
+
Add to your `.env` file or environment:
|
|
96
|
+
```env
|
|
97
|
+
APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://...
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Load in `settings.py`:
|
|
101
|
+
```python
|
|
102
|
+
from dotenv import load_dotenv
|
|
103
|
+
load_dotenv()
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## What Gets Auto-Instrumented
|
|
107
|
+
|
|
108
|
+
The Azure Monitor Distro automatically captures:
|
|
109
|
+
- ✅ All HTTP requests to your Django views
|
|
110
|
+
- ✅ Request duration, status codes, and paths
|
|
111
|
+
- ✅ Middleware processing time
|
|
112
|
+
- ✅ Exceptions and error details
|
|
113
|
+
- ✅ Database queries (PostgreSQL via psycopg2)
|
|
114
|
+
- ✅ Outbound HTTP calls
|
|
115
|
+
|
|
116
|
+
## Step 4: Add Custom Telemetry (Optional)
|
|
117
|
+
|
|
118
|
+
### In Views
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# views.py
|
|
122
|
+
from django.http import JsonResponse
|
|
123
|
+
from opentelemetry import trace
|
|
124
|
+
|
|
125
|
+
tracer = trace.get_tracer(__name__)
|
|
126
|
+
|
|
127
|
+
def order_detail(request, order_id):
|
|
128
|
+
with tracer.start_as_current_span("fetch-order") as span:
|
|
129
|
+
span.set_attribute("order.id", order_id)
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
order = Order.objects.get(id=order_id)
|
|
133
|
+
span.set_attribute("order.status", order.status)
|
|
134
|
+
return JsonResponse({"order": order.to_dict()})
|
|
135
|
+
except Order.DoesNotExist:
|
|
136
|
+
span.set_attribute("order.found", False)
|
|
137
|
+
return JsonResponse({"error": "Not found"}, status=404)
|
|
138
|
+
|
|
139
|
+
def process_order(request):
|
|
140
|
+
span = trace.get_active_span()
|
|
141
|
+
span.set_attribute("user.id", request.user.id)
|
|
142
|
+
|
|
143
|
+
# Your processing logic
|
|
144
|
+
return JsonResponse({"status": "processed"})
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### In Class-Based Views
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from django.views import View
|
|
151
|
+
from django.http import JsonResponse
|
|
152
|
+
from opentelemetry import trace
|
|
153
|
+
|
|
154
|
+
tracer = trace.get_tracer(__name__)
|
|
155
|
+
|
|
156
|
+
class OrderView(View):
|
|
157
|
+
def get(self, request, order_id):
|
|
158
|
+
with tracer.start_as_current_span("get-order") as span:
|
|
159
|
+
span.set_attribute("order.id", order_id)
|
|
160
|
+
order = Order.objects.get(id=order_id)
|
|
161
|
+
return JsonResponse(order.to_dict())
|
|
162
|
+
|
|
163
|
+
def post(self, request):
|
|
164
|
+
with tracer.start_as_current_span("create-order") as span:
|
|
165
|
+
# Create order logic
|
|
166
|
+
order = Order.objects.create(**request.POST)
|
|
167
|
+
span.set_attribute("order.id", order.id)
|
|
168
|
+
return JsonResponse({"id": order.id}, status=201)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Step 5: Add Logging Integration
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
# settings.py
|
|
175
|
+
LOGGING = {
|
|
176
|
+
'version': 1,
|
|
177
|
+
'disable_existing_loggers': False,
|
|
178
|
+
'handlers': {
|
|
179
|
+
'console': {
|
|
180
|
+
'class': 'logging.StreamHandler',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
'root': {
|
|
184
|
+
'handlers': ['console'],
|
|
185
|
+
'level': 'INFO',
|
|
186
|
+
},
|
|
187
|
+
'loggers': {
|
|
188
|
+
'django': {
|
|
189
|
+
'handlers': ['console'],
|
|
190
|
+
'level': 'INFO',
|
|
191
|
+
'propagate': False,
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
# views.py
|
|
199
|
+
import logging
|
|
200
|
+
|
|
201
|
+
logger = logging.getLogger(__name__)
|
|
202
|
+
|
|
203
|
+
def my_view(request):
|
|
204
|
+
logger.info("Processing request") # Automatically correlated with trace
|
|
205
|
+
# ...
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Complete Example Structure
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
mysite/
|
|
212
|
+
├── manage.py # Add configure_azure_monitor() here
|
|
213
|
+
├── requirements.txt
|
|
214
|
+
├── .env
|
|
215
|
+
└── mysite/
|
|
216
|
+
├── __init__.py
|
|
217
|
+
├── settings.py
|
|
218
|
+
├── urls.py
|
|
219
|
+
├── wsgi.py # Or add configure_azure_monitor() here
|
|
220
|
+
└── asgi.py
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### manage.py
|
|
224
|
+
```python
|
|
225
|
+
#!/usr/bin/env python
|
|
226
|
+
import os
|
|
227
|
+
import sys
|
|
228
|
+
from dotenv import load_dotenv
|
|
229
|
+
|
|
230
|
+
load_dotenv()
|
|
231
|
+
|
|
232
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
233
|
+
configure_azure_monitor()
|
|
234
|
+
|
|
235
|
+
def main():
|
|
236
|
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
|
|
237
|
+
from django.core.management import execute_from_command_line
|
|
238
|
+
execute_from_command_line(sys.argv)
|
|
239
|
+
|
|
240
|
+
if __name__ == '__main__':
|
|
241
|
+
main()
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Running the Application
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Set connection string
|
|
248
|
+
export APPLICATIONINSIGHTS_CONNECTION_STRING="InstrumentationKey=..."
|
|
249
|
+
|
|
250
|
+
# Run Django
|
|
251
|
+
python manage.py runserver
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Or for production with Gunicorn:
|
|
255
|
+
```bash
|
|
256
|
+
gunicorn mysite.wsgi:application
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Verification
|
|
260
|
+
|
|
261
|
+
1. Make requests to your Django endpoints
|
|
262
|
+
2. Go to Azure Portal → Application Insights
|
|
263
|
+
3. Check "Transaction search" for your requests
|
|
264
|
+
4. View database dependency calls
|
|
265
|
+
|
|
266
|
+
## Links
|
|
267
|
+
|
|
268
|
+
- [Django Documentation](https://docs.djangoproject.com/)
|
|
269
|
+
- [Azure Monitor Python](https://learn.microsoft.com/azure/azure-monitor/app/opentelemetry-enable?tabs=python)
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Basic Azure Monitor Setup for FastAPI
|
|
2
|
+
|
|
3
|
+
This guide shows how to add Azure Monitor OpenTelemetry to a FastAPI application.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Python 3.8 or higher
|
|
8
|
+
- FastAPI application
|
|
9
|
+
- Azure Application Insights resource
|
|
10
|
+
|
|
11
|
+
## Step 1: Install Packages
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install azure-monitor-opentelemetry fastapi uvicorn
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or add to your `requirements.txt`:
|
|
18
|
+
```
|
|
19
|
+
azure-monitor-opentelemetry
|
|
20
|
+
fastapi
|
|
21
|
+
uvicorn[standard]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Step 2: Initialize at Startup
|
|
25
|
+
|
|
26
|
+
Update your main application file (e.g., `main.py` or `app.py`):
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
# IMPORTANT: Configure Azure Monitor BEFORE importing FastAPI
|
|
30
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
31
|
+
configure_azure_monitor()
|
|
32
|
+
|
|
33
|
+
# Now import FastAPI
|
|
34
|
+
from fastapi import FastAPI, HTTPException
|
|
35
|
+
from pydantic import BaseModel
|
|
36
|
+
|
|
37
|
+
app = FastAPI(title="My API")
|
|
38
|
+
|
|
39
|
+
@app.get("/")
|
|
40
|
+
async def root():
|
|
41
|
+
return {"message": "Hello, World!"}
|
|
42
|
+
|
|
43
|
+
@app.get("/api/users/{user_id}")
|
|
44
|
+
async def get_user(user_id: int):
|
|
45
|
+
# This request is automatically tracked
|
|
46
|
+
return {"id": user_id, "name": f"User {user_id}"}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Step 3: Configure Connection String
|
|
50
|
+
|
|
51
|
+
Create a `.env` file:
|
|
52
|
+
```env
|
|
53
|
+
APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://...
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Load environment variables:
|
|
57
|
+
```python
|
|
58
|
+
from dotenv import load_dotenv
|
|
59
|
+
load_dotenv()
|
|
60
|
+
|
|
61
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
62
|
+
configure_azure_monitor()
|
|
63
|
+
|
|
64
|
+
from fastapi import FastAPI
|
|
65
|
+
# ... rest of your app
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## What Gets Auto-Instrumented
|
|
69
|
+
|
|
70
|
+
The Azure Monitor Distro automatically captures:
|
|
71
|
+
- ✅ All HTTP requests to your FastAPI routes
|
|
72
|
+
- ✅ Request duration, status codes, and paths
|
|
73
|
+
- ✅ Path parameters and query strings
|
|
74
|
+
- ✅ Exceptions and error details
|
|
75
|
+
- ✅ Outbound HTTP calls (httpx, requests, aiohttp)
|
|
76
|
+
- ✅ Database queries (asyncpg, psycopg2)
|
|
77
|
+
|
|
78
|
+
## Step 4: Add Custom Telemetry (Optional)
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from fastapi import FastAPI, Request
|
|
82
|
+
from opentelemetry import trace
|
|
83
|
+
|
|
84
|
+
app = FastAPI()
|
|
85
|
+
tracer = trace.get_tracer(__name__)
|
|
86
|
+
|
|
87
|
+
class Order(BaseModel):
|
|
88
|
+
item: str
|
|
89
|
+
quantity: int
|
|
90
|
+
|
|
91
|
+
@app.post("/api/orders")
|
|
92
|
+
async def create_order(order: Order, request: Request):
|
|
93
|
+
with tracer.start_as_current_span("create-order") as span:
|
|
94
|
+
span.set_attribute("order.item", order.item)
|
|
95
|
+
span.set_attribute("order.quantity", order.quantity)
|
|
96
|
+
|
|
97
|
+
# Your business logic
|
|
98
|
+
order_id = await save_order(order)
|
|
99
|
+
|
|
100
|
+
span.set_attribute("order.id", order_id)
|
|
101
|
+
return {"id": order_id, "status": "created"}
|
|
102
|
+
|
|
103
|
+
@app.get("/api/orders/{order_id}")
|
|
104
|
+
async def get_order(order_id: str):
|
|
105
|
+
span = trace.get_active_span()
|
|
106
|
+
span.set_attribute("order.id", order_id)
|
|
107
|
+
|
|
108
|
+
order = await fetch_order(order_id)
|
|
109
|
+
if not order:
|
|
110
|
+
span.set_attribute("order.found", False)
|
|
111
|
+
raise HTTPException(status_code=404, detail="Order not found")
|
|
112
|
+
|
|
113
|
+
return order
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Step 5: Add Middleware for Custom Context
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from fastapi import FastAPI, Request
|
|
120
|
+
from opentelemetry import trace
|
|
121
|
+
|
|
122
|
+
app = FastAPI()
|
|
123
|
+
|
|
124
|
+
@app.middleware("http")
|
|
125
|
+
async def add_custom_context(request: Request, call_next):
|
|
126
|
+
span = trace.get_active_span()
|
|
127
|
+
|
|
128
|
+
# Add custom attributes to every request
|
|
129
|
+
if span:
|
|
130
|
+
span.set_attribute("http.user_agent", request.headers.get("user-agent", ""))
|
|
131
|
+
span.set_attribute("custom.request_id", request.headers.get("x-request-id", ""))
|
|
132
|
+
|
|
133
|
+
response = await call_next(request)
|
|
134
|
+
return response
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Step 6: Add Logging Integration
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
import logging
|
|
141
|
+
from fastapi import FastAPI
|
|
142
|
+
|
|
143
|
+
# Configure logging
|
|
144
|
+
logging.basicConfig(level=logging.INFO)
|
|
145
|
+
logger = logging.getLogger(__name__)
|
|
146
|
+
|
|
147
|
+
app = FastAPI()
|
|
148
|
+
|
|
149
|
+
@app.get("/api/process/{item_id}")
|
|
150
|
+
async def process_item(item_id: str):
|
|
151
|
+
logger.info(f"Processing item {item_id}") # Correlated with trace
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
result = await do_processing(item_id)
|
|
155
|
+
logger.info(f"Successfully processed item {item_id}")
|
|
156
|
+
return result
|
|
157
|
+
except Exception as e:
|
|
158
|
+
logger.error(f"Failed to process item {item_id}: {e}")
|
|
159
|
+
raise
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Complete Example
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# main.py
|
|
166
|
+
import os
|
|
167
|
+
import logging
|
|
168
|
+
from dotenv import load_dotenv
|
|
169
|
+
|
|
170
|
+
# Load environment variables first
|
|
171
|
+
load_dotenv()
|
|
172
|
+
|
|
173
|
+
# Configure Azure Monitor BEFORE importing FastAPI
|
|
174
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
175
|
+
configure_azure_monitor()
|
|
176
|
+
|
|
177
|
+
# Now import FastAPI and other dependencies
|
|
178
|
+
from fastapi import FastAPI, HTTPException, Request
|
|
179
|
+
from pydantic import BaseModel
|
|
180
|
+
from opentelemetry import trace
|
|
181
|
+
|
|
182
|
+
# Setup logging
|
|
183
|
+
logging.basicConfig(level=logging.INFO)
|
|
184
|
+
logger = logging.getLogger(__name__)
|
|
185
|
+
|
|
186
|
+
# Create FastAPI app
|
|
187
|
+
app = FastAPI(
|
|
188
|
+
title="My API",
|
|
189
|
+
description="API with Azure Monitor integration",
|
|
190
|
+
version="1.0.0"
|
|
191
|
+
)
|
|
192
|
+
tracer = trace.get_tracer(__name__)
|
|
193
|
+
|
|
194
|
+
class Item(BaseModel):
|
|
195
|
+
name: str
|
|
196
|
+
price: float
|
|
197
|
+
|
|
198
|
+
@app.get("/")
|
|
199
|
+
async def root():
|
|
200
|
+
return {"status": "healthy"}
|
|
201
|
+
|
|
202
|
+
@app.get("/api/items")
|
|
203
|
+
async def list_items():
|
|
204
|
+
with tracer.start_as_current_span("list-items") as span:
|
|
205
|
+
items = [
|
|
206
|
+
{"id": 1, "name": "Item 1", "price": 10.0},
|
|
207
|
+
{"id": 2, "name": "Item 2", "price": 20.0}
|
|
208
|
+
]
|
|
209
|
+
span.set_attribute("items.count", len(items))
|
|
210
|
+
logger.info(f"Returning {len(items)} items")
|
|
211
|
+
return items
|
|
212
|
+
|
|
213
|
+
@app.post("/api/items")
|
|
214
|
+
async def create_item(item: Item):
|
|
215
|
+
with tracer.start_as_current_span("create-item") as span:
|
|
216
|
+
span.set_attribute("item.name", item.name)
|
|
217
|
+
span.set_attribute("item.price", item.price)
|
|
218
|
+
logger.info(f"Creating item: {item.name}")
|
|
219
|
+
return {"id": 1, **item.dict()}
|
|
220
|
+
|
|
221
|
+
@app.exception_handler(Exception)
|
|
222
|
+
async def global_exception_handler(request: Request, exc: Exception):
|
|
223
|
+
logger.error(f"Unhandled error: {exc}")
|
|
224
|
+
return {"error": "Internal server error"}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Running the Application
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
# Set connection string
|
|
231
|
+
export APPLICATIONINSIGHTS_CONNECTION_STRING="InstrumentationKey=..."
|
|
232
|
+
|
|
233
|
+
# Run with uvicorn
|
|
234
|
+
uvicorn main:app --reload
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Or programmatically:
|
|
238
|
+
```python
|
|
239
|
+
if __name__ == "__main__":
|
|
240
|
+
import uvicorn
|
|
241
|
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Verification
|
|
245
|
+
|
|
246
|
+
1. Make requests to your FastAPI endpoints
|
|
247
|
+
2. Use the auto-generated docs at `/docs` to test
|
|
248
|
+
3. Go to Azure Portal → Application Insights
|
|
249
|
+
4. Check "Transaction search" for your requests
|
|
250
|
+
5. View "Live Metrics" for real-time data
|
|
251
|
+
|
|
252
|
+
## Links
|
|
253
|
+
|
|
254
|
+
- [FastAPI Documentation](https://fastapi.tiangolo.com/)
|
|
255
|
+
- [Azure Monitor Python](https://learn.microsoft.com/azure/azure-monitor/app/opentelemetry-enable?tabs=python)
|
|
256
|
+
- [OpenTelemetry FastAPI Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/fastapi/fastapi.html)
|