@azure/mcp-linux-arm64 2.0.0-beta.8 → 3.0.0-beta.1
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 +149 -26
- 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/appsettings.json +5 -0
- package/dist/azmcp +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Basic Azure Monitor Setup for Node.js with Winston Logging
|
|
2
|
+
|
|
3
|
+
This guide shows how to add Azure Monitor OpenTelemetry to a Node.js application using Winston for logging.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js 14.x or higher
|
|
8
|
+
- npm or yarn
|
|
9
|
+
- Node.js application with Winston (`winston` package)
|
|
10
|
+
- Azure Application Insights resource
|
|
11
|
+
|
|
12
|
+
## Step 1: Install Package
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @azure/monitor-opentelemetry
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Step 2: Initialize at Startup
|
|
19
|
+
|
|
20
|
+
Create or update your main entry point (typically `index.js` or `server.js`):
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
// IMPORTANT: This must be the first line, before any other imports
|
|
24
|
+
const { useAzureMonitor } = require('@azure/monitor-opentelemetry');
|
|
25
|
+
|
|
26
|
+
// Initialize Azure Monitor with Winston log collection enabled
|
|
27
|
+
useAzureMonitor({
|
|
28
|
+
azureMonitorExporterOptions: {
|
|
29
|
+
connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING
|
|
30
|
+
},
|
|
31
|
+
instrumentationOptions: {
|
|
32
|
+
winston: { enabled: true }
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Now load your application code
|
|
37
|
+
const express = require('express');
|
|
38
|
+
const winston = require('winston');
|
|
39
|
+
|
|
40
|
+
// Create Winston logger
|
|
41
|
+
const logger = winston.createLogger({
|
|
42
|
+
level: process.env.LOG_LEVEL || 'info',
|
|
43
|
+
format: winston.format.combine(
|
|
44
|
+
winston.format.timestamp(),
|
|
45
|
+
winston.format.errors({ stack: true }),
|
|
46
|
+
winston.format.json()
|
|
47
|
+
),
|
|
48
|
+
defaultMeta: { service: 'my-app' },
|
|
49
|
+
transports: [
|
|
50
|
+
new winston.transports.Console({
|
|
51
|
+
format: winston.format.combine(
|
|
52
|
+
winston.format.colorize(),
|
|
53
|
+
winston.format.simple()
|
|
54
|
+
)
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const app = express();
|
|
60
|
+
const port = process.env.PORT || 3000;
|
|
61
|
+
|
|
62
|
+
app.use(express.json());
|
|
63
|
+
|
|
64
|
+
// Request logging middleware
|
|
65
|
+
app.use((req, res, next) => {
|
|
66
|
+
logger.info('Incoming request', {
|
|
67
|
+
method: req.method,
|
|
68
|
+
path: req.path
|
|
69
|
+
});
|
|
70
|
+
next();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
app.get('/api/users', (req, res) => {
|
|
74
|
+
logger.info('Fetching users');
|
|
75
|
+
res.json([{ id: 1, name: 'Alice' }]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
app.listen(port, () => {
|
|
79
|
+
logger.info(`Server listening on port ${port}`);
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Step 3: Configure Connection String
|
|
84
|
+
|
|
85
|
+
Create a `.env` file in your project root:
|
|
86
|
+
|
|
87
|
+
```env
|
|
88
|
+
APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://...
|
|
89
|
+
LOG_LEVEL=info
|
|
90
|
+
PORT=3000
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Install `dotenv` to load environment variables:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm install dotenv
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Load it at the very top of your entry file:
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
require('dotenv').config();
|
|
103
|
+
const { useAzureMonitor } = require('@azure/monitor-opentelemetry');
|
|
104
|
+
// ... rest of code
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## What Gets Collected
|
|
108
|
+
|
|
109
|
+
With Winston instrumentation enabled, the following log data is sent to Azure Monitor:
|
|
110
|
+
|
|
111
|
+
- **Log level**: error, warn, info, debug, etc.
|
|
112
|
+
- **Log message**: The log content
|
|
113
|
+
- **Metadata**: Any additional properties passed to the logger
|
|
114
|
+
- **Timestamp**: When the log was created
|
|
115
|
+
- **Trace context**: Correlation with distributed traces
|
|
116
|
+
|
|
117
|
+
## Log Level Mapping
|
|
118
|
+
|
|
119
|
+
Winston log levels are mapped to Application Insights severity levels:
|
|
120
|
+
|
|
121
|
+
| Winston Level | Application Insights Severity |
|
|
122
|
+
|--------------|------------------------------|
|
|
123
|
+
| error | Error |
|
|
124
|
+
| warn | Warning |
|
|
125
|
+
| info | Information |
|
|
126
|
+
| http | Information |
|
|
127
|
+
| verbose | Verbose |
|
|
128
|
+
| debug | Verbose |
|
|
129
|
+
| silly | Verbose |
|
|
130
|
+
|
|
131
|
+
## Step 4: Structured Logging Best Practices
|
|
132
|
+
|
|
133
|
+
### Add Context to Logs
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
// Good: Structured logging with context
|
|
137
|
+
logger.info('User created', {
|
|
138
|
+
userId: user.id,
|
|
139
|
+
email: user.email,
|
|
140
|
+
action: 'create'
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Good: Error logging with stack trace
|
|
144
|
+
logger.error('Failed to create user', {
|
|
145
|
+
error: err.message,
|
|
146
|
+
stack: err.stack,
|
|
147
|
+
email: req.body.email
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Correlation with Requests
|
|
152
|
+
|
|
153
|
+
Logs are automatically correlated with HTTP requests when using Express:
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
app.get('/api/users/:id', (req, res) => {
|
|
157
|
+
// This log will be correlated with the request trace
|
|
158
|
+
logger.info('Fetching user', { userId: req.params.id });
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
const user = getUserById(req.params.id);
|
|
162
|
+
logger.debug('User found', { user });
|
|
163
|
+
res.json(user);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
logger.error('User not found', {
|
|
166
|
+
userId: req.params.id,
|
|
167
|
+
error: error.message
|
|
168
|
+
});
|
|
169
|
+
res.status(404).json({ error: 'User not found' });
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Step 5: Custom Telemetry (Optional)
|
|
175
|
+
|
|
176
|
+
Combine logging with custom spans:
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
const { trace } = require('@opentelemetry/api');
|
|
180
|
+
|
|
181
|
+
app.post('/api/orders', async (req, res) => {
|
|
182
|
+
const tracer = trace.getTracer('my-app');
|
|
183
|
+
|
|
184
|
+
await tracer.startActiveSpan('create-order', async (span) => {
|
|
185
|
+
logger.info('Creating order', { items: req.body.items.length });
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const order = await createOrder(req.body);
|
|
189
|
+
|
|
190
|
+
logger.info('Order created successfully', {
|
|
191
|
+
orderId: order.id,
|
|
192
|
+
total: order.total
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
span.setAttribute('order.id', order.id);
|
|
196
|
+
res.status(201).json(order);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
logger.error('Failed to create order', {
|
|
199
|
+
error: error.message,
|
|
200
|
+
stack: error.stack
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
span.recordException(error);
|
|
204
|
+
span.setStatus({ code: 2, message: error.message });
|
|
205
|
+
res.status(500).json({ error: 'Failed to create order' });
|
|
206
|
+
} finally {
|
|
207
|
+
span.end();
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Viewing Logs in Azure Portal
|
|
214
|
+
|
|
215
|
+
1. Open your Application Insights resource in Azure Portal
|
|
216
|
+
2. Navigate to "Logs" under Monitoring
|
|
217
|
+
3. Query traces table:
|
|
218
|
+
|
|
219
|
+
```kusto
|
|
220
|
+
traces
|
|
221
|
+
| where timestamp > ago(1h)
|
|
222
|
+
| where customDimensions.service == "my-app"
|
|
223
|
+
| project timestamp, message, severityLevel, customDimensions
|
|
224
|
+
| order by timestamp desc
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
4. Use "Transaction search" to see logs correlated with requests
|
|
228
|
+
|
|
229
|
+
## Troubleshooting
|
|
230
|
+
|
|
231
|
+
### Winston logs not appearing
|
|
232
|
+
|
|
233
|
+
1. Ensure `winston` instrumentation is enabled in options
|
|
234
|
+
2. Verify `useAzureMonitor()` is called **before** importing `winston`
|
|
235
|
+
3. Check that the connection string is valid
|
|
236
|
+
|
|
237
|
+
### Too many logs being sent
|
|
238
|
+
|
|
239
|
+
Control log volume by adjusting the log level:
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
const logger = winston.createLogger({
|
|
243
|
+
level: process.env.NODE_ENV === 'production' ? 'warn' : 'debug',
|
|
244
|
+
// ...
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Or use sampling:
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
useAzureMonitor({
|
|
252
|
+
azureMonitorExporterOptions: {
|
|
253
|
+
connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING
|
|
254
|
+
},
|
|
255
|
+
instrumentationOptions: {
|
|
256
|
+
winston: { enabled: true }
|
|
257
|
+
},
|
|
258
|
+
samplingRatio: 0.5 // Sample 50% of telemetry
|
|
259
|
+
});
|
|
260
|
+
```
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# Basic Azure Monitor Setup for Python Console/Script Applications
|
|
2
|
+
|
|
3
|
+
This guide shows how to add Azure Monitor OpenTelemetry to standalone Python scripts, console applications, or background workers.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Python 3.8 or higher
|
|
8
|
+
- Python script or console application
|
|
9
|
+
- Azure Application Insights resource
|
|
10
|
+
|
|
11
|
+
## Step 1: Install Packages
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install azure-monitor-opentelemetry>=1.8.3
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or add to your `requirements.txt`:
|
|
18
|
+
```
|
|
19
|
+
azure-monitor-opentelemetry>=1.8.3
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Step 2: Initialize at Startup
|
|
23
|
+
|
|
24
|
+
Update your main script file (e.g., `app.py`, `main.py`):
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
# IMPORTANT: Configure Azure Monitor at the very top
|
|
28
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
29
|
+
configure_azure_monitor()
|
|
30
|
+
|
|
31
|
+
# Now import your other libraries
|
|
32
|
+
import time
|
|
33
|
+
import logging
|
|
34
|
+
|
|
35
|
+
# Your application code
|
|
36
|
+
logging.basicConfig(level=logging.INFO)
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
def main():
|
|
40
|
+
logger.info("Application started")
|
|
41
|
+
# Your logic here
|
|
42
|
+
time.sleep(1)
|
|
43
|
+
logger.info("Application completed")
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
main()
|
|
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
|
+
# ... rest of your app
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## What Gets Auto-Instrumented
|
|
68
|
+
|
|
69
|
+
The Azure Monitor Distro automatically captures:
|
|
70
|
+
- ✅ Basic Python logging (via logging module)
|
|
71
|
+
- ✅ Exceptions and error stack traces
|
|
72
|
+
- ✅ Application lifecycle events
|
|
73
|
+
|
|
74
|
+
**Note**: Unlike web frameworks, console apps don't have automatic HTTP request tracing. You need to add library-specific instrumentations.
|
|
75
|
+
|
|
76
|
+
## ⚠️ Important: Instrumentation Order
|
|
77
|
+
|
|
78
|
+
**CRITICAL**: The correct initialization order is:
|
|
79
|
+
1. Import standard libraries and your dependencies (requests, httpx, etc.) **FIRST**
|
|
80
|
+
2. Configure logging with `logging.basicConfig()` **SECOND**
|
|
81
|
+
3. Import and call `configure_azure_monitor()` **THIRD**
|
|
82
|
+
4. Get logger with `logging.getLogger(__name__)` **FOURTH**
|
|
83
|
+
5. Import and call instrumentor `.instrument()` methods **LAST**
|
|
84
|
+
|
|
85
|
+
**Incorrect Order** (logs won't appear in Application Insights):
|
|
86
|
+
```python
|
|
87
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
88
|
+
configure_azure_monitor() # ❌ Before logging config
|
|
89
|
+
logging.basicConfig(level=logging.INFO)
|
|
90
|
+
LoggingInstrumentor().instrument()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Correct Order** (logs will appear in Application Insights):
|
|
94
|
+
```python
|
|
95
|
+
import logging
|
|
96
|
+
import requests
|
|
97
|
+
|
|
98
|
+
logging.basicConfig(level=logging.INFO) # ✅ 1. Configure logging after regular imports
|
|
99
|
+
|
|
100
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
101
|
+
configure_azure_monitor() # ✅ 2. Then configure Azure Monitor
|
|
102
|
+
|
|
103
|
+
logger = logging.getLogger(__name__) # ✅ 3. Get logger after configure_azure_monitor
|
|
104
|
+
|
|
105
|
+
from opentelemetry.instrumentation.logging import LoggingInstrumentor
|
|
106
|
+
LoggingInstrumentor().instrument() # ✅ 4. Finally instrument
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This order applies to all instrumentors (HTTPXClientInstrumentor, URLLib3Instrumentor, AioHttpClientInstrumentor, AsyncioInstrumentor, etc.).
|
|
110
|
+
|
|
111
|
+
## Adding Library-Specific Instrumentations
|
|
112
|
+
|
|
113
|
+
### For HTTP Clients (requests, httpx, urllib3)
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pip install opentelemetry-instrumentation-requests
|
|
117
|
+
pip install opentelemetry-instrumentation-httpx
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
import logging
|
|
122
|
+
import requests
|
|
123
|
+
import httpx
|
|
124
|
+
|
|
125
|
+
logging.basicConfig(
|
|
126
|
+
level=logging.INFO,
|
|
127
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
131
|
+
configure_azure_monitor()
|
|
132
|
+
|
|
133
|
+
logger = logging.getLogger(__name__)
|
|
134
|
+
|
|
135
|
+
from opentelemetry.instrumentation.requests import RequestsInstrumentor
|
|
136
|
+
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
|
|
137
|
+
from opentelemetry.instrumentation.logging import LoggingInstrumentor
|
|
138
|
+
|
|
139
|
+
RequestsInstrumentor().instrument()
|
|
140
|
+
HTTPXClientInstrumentor().instrument()
|
|
141
|
+
LoggingInstrumentor().instrument()
|
|
142
|
+
|
|
143
|
+
# Now these calls are automatically traced
|
|
144
|
+
response = requests.get("https://api.example.com/data")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### For Database Clients (psycopg2, pymongo, redis)
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pip install opentelemetry-instrumentation-psycopg2
|
|
151
|
+
pip install opentelemetry-instrumentation-pymongo
|
|
152
|
+
pip install opentelemetry-instrumentation-redis
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
import logging
|
|
157
|
+
import psycopg2
|
|
158
|
+
|
|
159
|
+
logging.basicConfig(level=logging.INFO)
|
|
160
|
+
|
|
161
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
162
|
+
configure_azure_monitor()
|
|
163
|
+
|
|
164
|
+
logger = logging.getLogger(__name__)
|
|
165
|
+
|
|
166
|
+
from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor
|
|
167
|
+
Psycopg2Instrumentor().instrument()
|
|
168
|
+
|
|
169
|
+
# Database queries are now traced
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### For Async Operations
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
pip install opentelemetry-instrumentation-asyncio
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
import logging
|
|
180
|
+
import asyncio
|
|
181
|
+
|
|
182
|
+
logging.basicConfig(level=logging.INFO)
|
|
183
|
+
|
|
184
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
185
|
+
configure_azure_monitor()
|
|
186
|
+
|
|
187
|
+
logger = logging.getLogger(__name__)
|
|
188
|
+
|
|
189
|
+
from opentelemetry.instrumentation.asyncio import AsyncioInstrumentor
|
|
190
|
+
AsyncioInstrumentor().instrument()
|
|
191
|
+
|
|
192
|
+
# Async tasks are now traced
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Adding Custom Tracing
|
|
196
|
+
|
|
197
|
+
Use OpenTelemetry APIs to create custom spans for your business logic:
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
201
|
+
configure_azure_monitor()
|
|
202
|
+
|
|
203
|
+
from opentelemetry import trace
|
|
204
|
+
|
|
205
|
+
tracer = trace.get_tracer(__name__)
|
|
206
|
+
|
|
207
|
+
def process_data(data):
|
|
208
|
+
with tracer.start_as_current_span("process_data") as span:
|
|
209
|
+
span.set_attribute("data.size", len(data))
|
|
210
|
+
|
|
211
|
+
# Your processing logic
|
|
212
|
+
result = do_something(data)
|
|
213
|
+
|
|
214
|
+
span.set_attribute("result.count", len(result))
|
|
215
|
+
return result
|
|
216
|
+
|
|
217
|
+
def do_something(data):
|
|
218
|
+
# This automatically becomes a child span
|
|
219
|
+
with tracer.start_as_current_span("do_something"):
|
|
220
|
+
# Processing logic
|
|
221
|
+
return [item * 2 for item in data]
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Example: Complete Console Application
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
"""Example console application with Azure Monitor."""
|
|
228
|
+
from dotenv import load_dotenv
|
|
229
|
+
load_dotenv()
|
|
230
|
+
|
|
231
|
+
import logging
|
|
232
|
+
import requests
|
|
233
|
+
import time
|
|
234
|
+
|
|
235
|
+
logging.basicConfig(
|
|
236
|
+
level=logging.INFO,
|
|
237
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
241
|
+
configure_azure_monitor()
|
|
242
|
+
|
|
243
|
+
logger = logging.getLogger(__name__)
|
|
244
|
+
|
|
245
|
+
from opentelemetry.instrumentation.requests import RequestsInstrumentor
|
|
246
|
+
from opentelemetry.instrumentation.logging import LoggingInstrumentor
|
|
247
|
+
RequestsInstrumentor().instrument()
|
|
248
|
+
LoggingInstrumentor().instrument()
|
|
249
|
+
|
|
250
|
+
from opentelemetry import trace
|
|
251
|
+
|
|
252
|
+
tracer = trace.get_tracer(__name__)
|
|
253
|
+
|
|
254
|
+
def fetch_data(url):
|
|
255
|
+
"""Fetch data from API - automatically traced."""
|
|
256
|
+
logger.info(f"Fetching data from {url}")
|
|
257
|
+
response = requests.get(url, timeout=10)
|
|
258
|
+
response.raise_for_status()
|
|
259
|
+
return response.json()
|
|
260
|
+
|
|
261
|
+
def process_batch(items):
|
|
262
|
+
"""Process items with custom tracing."""
|
|
263
|
+
with tracer.start_as_current_span("process_batch") as span:
|
|
264
|
+
span.set_attribute("batch.size", len(items))
|
|
265
|
+
|
|
266
|
+
results = []
|
|
267
|
+
for i, item in enumerate(items):
|
|
268
|
+
with tracer.start_as_current_span(f"process_item_{i}"):
|
|
269
|
+
time.sleep(0.1) # Simulate processing
|
|
270
|
+
results.append(item * 2)
|
|
271
|
+
|
|
272
|
+
span.set_attribute("results.count", len(results))
|
|
273
|
+
logger.info(f"Processed {len(results)} items")
|
|
274
|
+
return results
|
|
275
|
+
|
|
276
|
+
def main():
|
|
277
|
+
"""Main application entry point."""
|
|
278
|
+
with tracer.start_as_current_span("main") as span:
|
|
279
|
+
logger.info("Application started")
|
|
280
|
+
|
|
281
|
+
try:
|
|
282
|
+
# Fetch data (HTTP call is auto-traced)
|
|
283
|
+
data = fetch_data("https://jsonplaceholder.typicode.com/posts")
|
|
284
|
+
span.add_event("data_fetched", {"count": len(data)})
|
|
285
|
+
|
|
286
|
+
# Process data (custom spans)
|
|
287
|
+
results = process_batch(data[:10])
|
|
288
|
+
|
|
289
|
+
logger.info(f"Application completed successfully. Processed {len(results)} items")
|
|
290
|
+
span.set_status(trace.Status(trace.StatusCode.OK))
|
|
291
|
+
|
|
292
|
+
except Exception as e:
|
|
293
|
+
logger.error(f"Application failed: {e}", exc_info=True)
|
|
294
|
+
span.record_exception(e)
|
|
295
|
+
span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))
|
|
296
|
+
raise
|
|
297
|
+
|
|
298
|
+
if __name__ == "__main__":
|
|
299
|
+
main()
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Common Use Cases
|
|
303
|
+
|
|
304
|
+
### Batch Processing Scripts
|
|
305
|
+
```python
|
|
306
|
+
with tracer.start_as_current_span("batch_job") as span:
|
|
307
|
+
span.set_attribute("job.type", "daily_report")
|
|
308
|
+
process_records()
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### CLI Tools
|
|
312
|
+
```python
|
|
313
|
+
import click
|
|
314
|
+
|
|
315
|
+
@click.command()
|
|
316
|
+
@click.option('--input', required=True)
|
|
317
|
+
def cli_tool(input):
|
|
318
|
+
with tracer.start_as_current_span("cli_execution") as span:
|
|
319
|
+
span.set_attribute("cli.input", input)
|
|
320
|
+
# Process CLI logic
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Background Workers
|
|
324
|
+
```python
|
|
325
|
+
while True:
|
|
326
|
+
with tracer.start_as_current_span("worker_iteration"):
|
|
327
|
+
process_queue()
|
|
328
|
+
time.sleep(60)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Available Instrumentations
|
|
332
|
+
|
|
333
|
+
| Library | Instrumentation Package | What's Traced |
|
|
334
|
+
|---------|------------------------|---------------|
|
|
335
|
+
| requests | `opentelemetry-instrumentation-requests` | HTTP requests |
|
|
336
|
+
| httpx | `opentelemetry-instrumentation-httpx` | HTTP/2 requests |
|
|
337
|
+
| urllib3 | `opentelemetry-instrumentation-urllib3` | Low-level HTTP |
|
|
338
|
+
| psycopg2 | `opentelemetry-instrumentation-psycopg2` | PostgreSQL queries |
|
|
339
|
+
| pymongo | `opentelemetry-instrumentation-pymongo` | MongoDB operations |
|
|
340
|
+
| redis | `opentelemetry-instrumentation-redis` | Redis commands |
|
|
341
|
+
| asyncio | `opentelemetry-instrumentation-asyncio` | Async tasks |
|
|
342
|
+
| logging | Built-in | Log records |
|
|
343
|
+
|
|
344
|
+
## Configuration Options
|
|
345
|
+
|
|
346
|
+
### Control Sampling
|
|
347
|
+
|
|
348
|
+
Sample only 10% of traces to reduce costs:
|
|
349
|
+
|
|
350
|
+
```python
|
|
351
|
+
import os
|
|
352
|
+
os.environ["OTEL_TRACES_SAMPLER"] = "traceidratio"
|
|
353
|
+
os.environ["OTEL_TRACES_SAMPLER_ARG"] = "0.1"
|
|
354
|
+
|
|
355
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
356
|
+
configure_azure_monitor()
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Set Service Name
|
|
360
|
+
|
|
361
|
+
```python
|
|
362
|
+
import os
|
|
363
|
+
os.environ["OTEL_SERVICE_NAME"] = "my-batch-processor"
|
|
364
|
+
|
|
365
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
366
|
+
configure_azure_monitor()
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Add Resource Attributes
|
|
370
|
+
|
|
371
|
+
```python
|
|
372
|
+
import os
|
|
373
|
+
os.environ["OTEL_RESOURCE_ATTRIBUTES"] = "deployment.environment=production,service.version=1.2.3"
|
|
374
|
+
|
|
375
|
+
from azure.monitor.opentelemetry import configure_azure_monitor
|
|
376
|
+
configure_azure_monitor()
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Viewing Telemetry
|
|
380
|
+
|
|
381
|
+
Once configured, view your console app telemetry in Azure Portal:
|
|
382
|
+
1. Go to your Application Insights resource
|
|
383
|
+
2. Navigate to **Transaction search** for individual executions
|
|
384
|
+
3. Check **Performance** for operation timing
|
|
385
|
+
4. Use **Failures** to track exceptions
|
|
386
|
+
5. Create custom queries in **Logs** for batch job analytics
|
|
387
|
+
|
|
388
|
+
## Next Steps
|
|
389
|
+
|
|
390
|
+
- OpenTelemetry Pipeline Concepts(see in opentelemetry-pipeline-python.md)
|
|
391
|
+
- Azure Monitor Python Overview(see in azure-monitor-python.md)
|
|
392
|
+
- [OpenTelemetry Python Documentation](https://opentelemetry.io/docs/instrumentation/python/)
|