Python
| Traces | Metrics | App Logs | Custom Logs | Profiling |
|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ |
1. Prerequisites#
Before you instrument anything, make sure the basics are in place:
- Python 3.9+ 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:The SDK adds a
1export MW_SERVICE_NAME='MyPythonApp' 2middleware-run python app.pymiddleware-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).
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.pyMW_TRACKER=True is required when you instrument using mw_tracker().
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.pyIn serverless mode the app exports directly to Middleware, so both MW_API_KEY and MW_TARGET are required. (docs.middleware.io)
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.py4. Advanced configuration (optional)#
Two ways to set your service name:
1export MW_SERVICE_NAME='MyPythonApp'Or set service_name in MWOptions(...).
Enable continuous profiling:
1pip install 'middleware-io[profiling]'
2export MW_APM_COLLECT_PROFILING=True
3# serverless requires MW_API_KEY + MW_TARGET as abovePick the run command that matches your server/framework.
1export DJANGO_SETTINGS_MODULE='mysite.settings'
2middleware-run python manage.py runserver1export 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.wsgi1export MW_API_KEY='<MW_API_KEY>'
2export MW_TARGET='https://<MW_UID>.middleware.io:443'
3middleware-run uvicorn main:app --host localhost --port 5002If you’re running in a container with Host mode, set MW_AGENT_SERVICE so your app can reach the Host Agent:
- Docker default gateway:
172.17.0.1 - Kubernetes service:
mw-service.mw-agent-ns.svc.cluster.local
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#
Create and use a meter to send custom metrics:
1from opentelemetry.metrics import get_meter_provider
2
3meter = get_meter_provider().get_meter("custom_meter")
4
5request_counter = meter.create_counter(
6 "request_counter", description="Counts the number of requests"
7)
8
9request_counter.add(1, {"endpoint": "/home"})Create and use a tracer to send custom spans:
1from opentelemetry.trace import get_tracer
2
3tracer = get_tracer("custom_tracer")
4
5with tracer.start_as_current_span("custom_span"):
6 print("Doing some work within the span")Use logging to emit logs. If your app already has a logger wrapper, add these calls there:
1import logging
2
3logging.info("info sample")
4logging.warning("Sample Warning Log")
5logging.error("Sample Error Log.", extra={"tester": "Alex"})Attach attributes to spans (they become filter/group dimensions in Middleware):
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)Record an exception and its stack trace:
1from middleware import record_exception
2
3try:
4 print("Divide by zero:", 1 / 0)
5except Exception as e:
6 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=v list. | 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.
Use this option if you want upstream OpenTelemetry auto-instrumentation (opentelemetry-distro, opentelemetry-instrument) and OTLP export directly to Middleware.
- Full guide: Python (OpenTelemetry)
Need assistance or want to learn more about Middleware? Get in touch with us via our Contact Us or join our Slack channel.
What did you think of this content?