Python
| Traces | Metrics | App Logs | Custom Logs | Profiling | 
|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ | 
1. Prerequisites
Before you instrument anything, make sure the basics are in place:
- Python 3.8+ and pip 23.1.2+ – verify your versions:1python3 --version 2pip --version
- (Host mode only) If your app runs in a container, point it at the Host Agent using MW_AGENT_SERVICE.- Docker default bridge gateway: 172.17.0.1
- Kubernetes service name: mw-service.mw-agent-ns.svc.cluster.local(discover withkubectl get service --all-namespaces | grep mw-service).
 
- Docker default bridge gateway: 
2. Install
Create an isolated environment, install the SDK, then add auto-instrumentation shims for your frameworks:
1python -m venv .venv
2source .venv/bin/activate
3
4# SDK
5pip install middleware-io
6
7# (optional) enable continuous profiling features
8pip install 'middleware-io[profiling]'
9
10# Add OpenTelemetry auto-instrumentation libraries for installed packages (e.g., Flask)
11middleware-bootstrap -a installWhat middleware-bootstrap -a install does: it scans your active site-packages and installs the matching opentelemetry-instrumentation-* libraries for any frameworks you already have (e.g., Flask → opentelemetry-instrumentation-flask).
You can confirm with pip list | grep -i flask. For containers, add RUN middleware-bootstrap -a install to your Dockerfile.
3. Instrumentation
Pick Host (with the Middleware Host Agent) or Serverless (send directly to Middleware). Within each, choose Auto (zero-code) or Manual (call the tracker in code).
- Auto instrumentation (zero-code) Use the CLI wrapper that the SDK installs; it starts your app with the correct instrumentation: - 1export MW_SERVICE_NAME='MyPythonApp' 2middleware-run python app.py- The SDK adds a - middleware-runCLI to your venv; use it instead of raw commands like flask run so telemetry is captured. In Host mode, the OTLP target defaults to the local agent (- http://localhost:9319).
- Manual instrumentation (in code) Call - mw_tracker(...)once at startup for more control (sampling, detectors, debug output, etc.):- 1from middleware import mw_tracker, MWOptions 2 3mw_tracker(MWOptions( 4 service_name="MyPythonApp", 5 console_exporter=True, # echo telemetry to stdout (dev only) 6 log_level="DEBUG", 7))- Run it with: - 1export MW_TRACKER=True 2middleware-run python app.py- MW_TRACKER=Trueis required when you instrument using- mw_tracker().
- Auto instrumentation (zero-code) Set the tenant endpoint and API key, then start with the same runner: - 1export MW_API_KEY='<MW_API_KEY>' 2export MW_TARGET='https://<MW_UID>.middleware.io:443' 3export MW_SERVICE_NAME='MyPythonApp' 4middleware-run python app.py- In serverless mode the app exports directly to Middleware, so both - MW_API_KEYand- MW_TARGETare required. (docs.middleware.io)
- Manual instrumentation (in code) Supply the target and token via - MWOptions:- 1from middleware import mw_tracker, MWOptions, DETECT_AWS_EC2 2 3mw_tracker(MWOptions( 4 access_token="<MW_API_KEY>", 5 target="https://<MW_UID>.middleware.io:443", 6 service_name="MyPythonApp", 7 detectors=[DETECT_AWS_EC2], # example 8 otel_propagators="b3,tracecontext", 9 console_exporter=True, 10 log_level="DEBUG", 11))- Run it with: - 1export MW_TRACKER=True 2middleware-run python app.py
4. Advanced configuration (optional)
- Service name (two ways):Or set1export MW_SERVICE_NAME='MyPythonApp'service_nameinMWOptions(...).
- Continuous profiling:1pip install 'middleware-io[profiling]' 2 export MW_APM_COLLECT_PROFILING=True 3 # serverless requires MW_API_KEY + MW_TARGET as above
Framework-specific run examples:
- Django - 1export DJANGO_SETTINGS_MODULE='mysite.settings' 2middleware-run python manage.py runserver
- Gunicorn - 1export MW_API_KEY='<MW_API_KEY>' 2export MW_TARGET='https://<MW_UID>.middleware.io:443' 3export DJANGO_SETTINGS_MODULE='demo.settings' 4middleware-run gunicorn -c conf/gunicorn.conf.py --workers=4 --bind 0.0.0.0:8000 --timeout 120 demo.wsgi
- Uvicorn (FastAPI/Starlette) - 1export MW_API_KEY='<MW_API_KEY>' 2export MW_TARGET='https://<MW_UID>.middleware.io:443' 3middleware-run uvicorn main:app --host localhost --port 5002
- Use the serverless env set if you’re not running a Host Agent.) 
- Host networking in containers: - Docker default gateway is 172.17.0.1.
- On Kubernetes, find the service and set MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local.
 
- Docker default gateway is 
What “Zero-code” actually does: automatic patching via monkey-patching of popular libraries at runtime (e.g., Flask), driven by the instrumentation packages you installed with middleware-bootstrap.
5. Sending custom data
- Custom Metrics- Create and use a meter to send custom metrics: - 1from opentelemetry.metrics import get_meter_provider 2 3# Create a meter 4meter = get_meter_provider().get_meter("custom_meter") 5 6# Create a counter 7request_counter = meter.create_counter( 8 "request_counter", description="Counts the number of requests" 9) 10 11# Use the counter 12request_counter.add(1, {"endpoint": "/home"})
- Custom Traces- Create and use a tracer to send custom spans: - 1from opentelemetry.trace import get_tracer 2 3# Create a tracer 4tracer = get_tracer("custom_tracer") 5 6# Start a span 7with tracer.start_as_current_span("custom_span"): 8 print("Doing some work within the span")
- Custom Logs- Utilize - loggingmethod to send logs with a given priority. It is recommended to integrate these calls function inside your existing logger:- 1logging.info("info sample") 2logging.warning("Sample Warning Log") 3logging.error("Sample Error Log.", extra={'tester': 'Alex'})
- Custom Attributes- All custom attributes collected will be available as filtering and grouping functions inside of the Middleware platform. - Using similar methods from the above Traces and Logs sections you can attach custom attributes to any trace, span or log: - 1from opentelemetry.trace import get_tracer 2 3tracer = get_tracer("custom_tracer") 4 5with tracer.start_as_current_span("span_with_attributes") as span: 6 span.set_attribute("user.email", "[email protected]") 7 span.set_attribute("user.id", 1234)
- Adding Stack Traces- Use - record_exception()method to record a stack trace when an exception occurs:- 1from middleware import record_exception 2 try: 3 print("Divide by zero:",1/0) 4 except Exception as e: 5 record_exception(e)
6. Environment variables
OTel env vars are supported and take the highest priority if present. Then Middleware env vars, then code options.
| Config attribute | Environment variable(s) | Description/default | Example | 
|---|---|---|---|
| access_token | MW_API_KEY | Auth token (required for serverless/direct). | xxxxxxxx… | 
| service_name | MW_SERVICE_NAME, OTEL_SERVICE_NAME | Service name shown in APM. | payments-api | 
| collect_traces | MW_APM_COLLECT_TRACES | Enable traces (default true). | true | 
| collect_metrics | MW_APM_COLLECT_METRICS | Enable metrics (default true). | true | 
| collect_logs | MW_APM_COLLECT_LOGS | Enable logs (default true). | true | 
| collect_profiling | MW_APM_COLLECT_PROFILING | Enable profiling (requires profiling extra). | true | 
| log_level | MW_LOG_LEVEL, OTEL_LOG_LEVEL | Logging level (default INFO). | DEBUG | 
| mw_agent_service | MW_AGENT_SERVICE | Host Agent address in containers. | 172.17.0.1 / mw-service.mw-agent-ns... | 
| target | MW_TARGET, OTEL_EXPORTER_OTLP_ENDPOINT | OTLP endpoint (Host default: http://localhost:9319). | https://<MW_UID>.middleware.io:443 | 
| custom_resource_attributes | MW_CUSTOM_RESOURCE_ATTRIBUTES | Comma-sep k=vlist. | call_id=123,region=us-east-1 | 
| otel_propagators | MW_PROPAGATORS, OTEL_PROPAGATORS | Context propagation (default b3). | b3,tracecontext | 
| console_exporter | MW_CONSOLE_EXPORTER | Echo telemetry to console (dev). | true | 
| debug_log_file | MW_DEBUG_LOG_FILE | Log telemetry to files (with console exporter). | true | 
| project_name | MW_PROJECT_NAME | Logical app/project name. | ShopApp | 
| sample_rate | MW_SAMPLE_RATE | 0..1 (AlwaysOn=1, AlwaysOff=0). | 0.5 | 
| detectors | MW_DETECTORS | e.g., aws_lambda,gcp,azure,envvars. | aws_lambda,gcp | 
7. View your data
After you start the app, give it 3–5 minutes, then open APM → Traces, Logs, and APM → Continuous Profiling in Middleware. See “Application Instrumentation” for where to find dashboards, trace viewer, Log Explorer, and Alerts.
8. Troubleshooting
- No data (Host mode): Ensure you’re using middleware-run, the Host Agent is installed, and (in containers)MW_AGENT_SERVICEis set to the correct address/service.
- No data (Serverless): Make sure both MW_API_KEYandMW_TARGETare exported before starting.
- Instrumentation didn’t hook: Re-run middleware-bootstrap -a installafter adding frameworks, and verify withpip listthatopentelemetry-instrumentation-*packages exist.
- Need to confirm register/init ran? Temporarily setMW_CONSOLE_EXPORTER=true(andMW_DEBUG_LOG_FILE=true) to echo spans/logs to stdout/files while you test.
- Kubernetes reachability: find the service, then set MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local.
Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.