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:
python3 --version pip --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:
python -m venv .venv
source .venv/bin/activate
# SDK
pip install middleware-io
# (optional) enable continuous profiling features
pip install 'middleware-io[profiling]'
# Add OpenTelemetry auto-instrumentation libraries for installed packages (e.g., Flask)
middleware-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
export MW_SERVICE_NAME='MyPythonApp' middleware-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.):
from middleware import mw_tracker, MWOptions
mw_tracker(MWOptions(
service_name="MyPythonApp",
console_exporter=True, # echo telemetry to stdout (dev only)
log_level="DEBUG",
))Run it with:
export MW_TRACKER=True
middleware-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:
export MW_API_KEY='<MW_API_KEY>'
export MW_TARGET='https://<MW_UID>.middleware.io:443'
export MW_SERVICE_NAME='MyPythonApp'
middleware-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:
from middleware import mw_tracker, MWOptions, DETECT_AWS_EC2
mw_tracker(MWOptions(
access_token="<MW_API_KEY>",
target="https://<MW_UID>.middleware.io:443",
service_name="MyPythonApp",
detectors=[DETECT_AWS_EC2], # example
otel_propagators="b3,tracecontext",
console_exporter=True,
log_level="DEBUG",
))Run it with:
export MW_TRACKER=True
middleware-run python app.py4. Advanced configuration (optional)
Two ways to set your service name:
export MW_SERVICE_NAME='MyPythonApp'Or set service_name in MWOptions(...).
Enable continuous profiling:
pip install 'middleware-io[profiling]'
export MW_APM_COLLECT_PROFILING=True
# serverless requires MW_API_KEY + MW_TARGET as abovePick the run command that matches your server/framework.
export DJANGO_SETTINGS_MODULE='mysite.settings'
middleware-run python manage.py runserverexport MW_API_KEY='<MW_API_KEY>'
export MW_TARGET='https://<MW_UID>.middleware.io:443'
export DJANGO_SETTINGS_MODULE='demo.settings'
middleware-run gunicorn -c conf/gunicorn.conf.py --workers=4 --bind 0.0.0.0:8000 --timeout 120 demo.wsgiexport MW_API_KEY='<MW_API_KEY>'
export MW_TARGET='https://<MW_UID>.middleware.io:443'
middleware-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:
from opentelemetry.metrics import get_meter_provider
meter = get_meter_provider().get_meter("custom_meter")
request_counter = meter.create_counter(
"request_counter", description="Counts the number of requests"
)
request_counter.add(1, {"endpoint": "/home"})Create and use a tracer to send custom spans:
from opentelemetry.trace import get_tracer
tracer = get_tracer("custom_tracer")
with tracer.start_as_current_span("custom_span"):
print("Doing some work within the span")Use logging to emit logs. If your app already has a logger wrapper, add these calls there:
import logging
logging.info("info sample")
logging.warning("Sample Warning Log")
logging.error("Sample Error Log.", extra={"tester": "Alex"})Attach attributes to spans (they become filter/group dimensions in Middleware):
from opentelemetry.trace import get_tracer
tracer = get_tracer("custom_tracer")
with tracer.start_as_current_span("span_with_attributes") as span:
span.set_attribute("user.email", "[email protected]")
span.set_attribute("user.id", 1234)Record an exception and its stack trace:
from middleware import record_exception
try:
print("Divide by zero:", 1 / 0)
except Exception as e:
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? Contact our support team at [email protected] or join our Slack channel.